flutter_sound系列(一)音频录音和播放

简介

flutter_sound播放插件是一款非常优秀的音频记录,播放,音频文件转换插件。它更新速度非常快,我在这里不敢列出版本,免得不小心文章又过时了。

插件介绍

以目前最新版本flutter_sound: ^8.4.2为例:

flutter_sound系列(一)音频录音和播放

你如果只是看Example会完全不知所云,所以,我们要找到它的github仓库,仓库地址为:https://github.com/canardoux/flutter_sound,然后咱们打开example项目https://github.com/Canardoux/flutter_sound/tree/master/flutter_sound/example

flutter_sound系列(一)音频录音和播放
下载下来,并用android studio打开运行,注意,需要更新android studio到最新版本。

android配置

这里有两部分配置,一部分是build.gradle的配置,引入相应的jar包:

    implementation 'com.arthenica:mobile-ffmpeg-full:4.4.LTS'
    implementation 'androidx.core:core:1.3.2'
    implementation 'androidx.media:media:1.2.0'
    implementation 'androidx.appcompat:appcompat:1.2.0'

    // -------------------------------------------------------------------------------------
    // CAUTION: The following instruction is for developping and debugging the Flauto Engine
    // DO NOT INCLUDE THE FOLLOWING LINE IN A REAL APP !!!
    //implementation project(':flutter_sound_core')
    implementation 'com.github.canardoux:flutter_sound_core:8.4.1'
    // -------------------------------------------------------------------------------------

另外一部分是在AndroidManifest.xml中添加权限:

    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.RECORD_AUDIO"/>
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="Manifest.permission.CAPTURE_AUDIO_OUTPUT" />

布局

布局两个按钮,一个播放,一个录音,非常简单:

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('flutter_sound demo'),
      ),
      body: Row(
        children: [
          SizedBox(
            width: 3,
          ),
          ElevatedButton(
              onPressed: () {
                play();
              },
              child: Text('Play')),
          SizedBox(
            width: 20,
          ),
          // 一般播放和录音没啥关系
          ElevatedButton(
              onPressed: () {
                if (recording) {
                  stopRecorder();
                } else {
                  record();
                }
              },
              child: Text(recording ? 'Stop' : 'Record'))
        ],
      ),
    );
  }

界面显示也非常简单:

flutter_sound系列(一)音频录音和播放

初始化

初始化主要是定义好FlutterSoundPlayer和FlutterSoundRecorder两个对象,并初始化。

  Codec _codec = Codec.aacMP4;
  String _mPath = 'tau_file.mp4';
  bool recording = false;

  FlutterSoundPlayer? _mPlayer = FlutterSoundPlayer();
  FlutterSoundRecorder? _mRecorder = FlutterSoundRecorder();

  Future<void> openTheRecorder() async {
    var status = await Permission.microphone.request();
    if (status != PermissionStatus.granted) {
      throw RecordingPermissionException('Microphone permission not granted');
    }
    await _mRecorder!.openAudioSession();

    if (!await _mRecorder!.isEncoderSupported(_codec) && kIsWeb) {
      _codec = Codec.opusWebM;
      _mPath = 'tau_file.webm';
      if (!await _mRecorder!.isEncoderSupported(_codec) && kIsWeb) {
        return;
      }
    }
  }

  @override
  void initState() {
    _mPlayer!.openAudioSession().then((value) {});

    // await openTheRecorder().then((value) {});
    // TODO: implement initState

    openTheRecorder().then((value) {
      setState(() {});
    });
    super.initState();
  }

播放方法

  void play() {
    _mPlayer!
        .startPlayer(
            fromURI: _mPath,
            // 'https://file-examples-com.github.io/uploads/2017/11/file_example_MP3_700KB.mp3',
            //codec: kIsWeb ? Codec.opusWebM : Codec.aacADTS,
            whenFinished: () {
              setState(() {});
            })
        .then((value) {
      setState(() {});
    });
  }

_mPath是音频位置,可以是本地音频,也可以是网络音频。

录音和停止录音方法
  void record() async {
    _mRecorder!
        .startRecorder(
          toFile: _mPath,
          codec: _codec,
          audioSource: AudioSource.microphone,
        )
        .then((value) {});

    setState(() {
      recording = true;
    });
  }

  void stopRecorder() async {
    await _mRecorder!.stopRecorder().then((value) {
      setState(() {
        recording = false;
      });
    });
  }

也不复杂,就是startRecorder和stopRecorder两个方法。

全部代码

界面就很好操作了,播放和停止两个按钮就行了。全部代码如下:

import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:flutter_sound/flutter_sound.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:flutter_sound_platform_interface/flutter_sound_recorder_platform_interface.dart';

class Demo extends StatefulWidget {
  Demo({Key? key}) : super(key: key);

  @override
  _DemoState createState() => _DemoState();
}

class _DemoState extends State<Demo> {
  Codec _codec = Codec.aacMP4;
  String _mPath = 'tau_file.mp4';
  bool recording = false;

  FlutterSoundPlayer? _mPlayer = FlutterSoundPlayer();
  FlutterSoundRecorder? _mRecorder = FlutterSoundRecorder();

  Future<void> openTheRecorder() async {
    var status = await Permission.microphone.request();
    if (status != PermissionStatus.granted) {
      throw RecordingPermissionException('Microphone permission not granted');
    }
    await _mRecorder!.openAudioSession();

    if (!await _mRecorder!.isEncoderSupported(_codec) && kIsWeb) {
      _codec = Codec.opusWebM;
      _mPath = 'tau_file.webm';
      if (!await _mRecorder!.isEncoderSupported(_codec) && kIsWeb) {
        return;
      }
    }
  }

  @override
  void initState() {
    _mPlayer!.openAudioSession().then((value) {});

    // await openTheRecorder().then((value) {});
    // TODO: implement initState

    openTheRecorder().then((value) {
      setState(() {});
    });
    super.initState();
  }

  void play() {
    _mPlayer!
        .startPlayer(
            fromURI: _mPath,
            // 'https://file-examples-com.github.io/uploads/2017/11/file_example_MP3_700KB.mp3',
            //codec: kIsWeb ? Codec.opusWebM : Codec.aacADTS,
            whenFinished: () {
              setState(() {});
            })
        .then((value) {
      setState(() {});
    });
  }

  void record() async {
    _mRecorder!
        .startRecorder(
          toFile: _mPath,
          codec: _codec,
          audioSource: AudioSource.microphone,
        )
        .then((value) {});

    setState(() {
      recording = true;
    });
  }

  void stopRecorder() async {
    await _mRecorder!.stopRecorder().then((value) {
      setState(() {
        recording = false;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('flutter_sound demo'),
      ),
      body: Row(
        children: [
          SizedBox(
            width: 3,
          ),
          ElevatedButton(
              onPressed: () {
                play();
              },
              child: Text('Play')),
          SizedBox(
            width: 20,
          ),
          // 一般播放和录音没啥关系
          ElevatedButton(
              onPressed: () {
                if (recording) {
                  stopRecorder();
                } else {
                  record();
                }
              },
              child: Text(recording ? 'Stop' : 'Record'))
        ],
      ),
    );
  }
}

github地址如下:https://gitee.com/jishaofeng89/dongda_flutter_sound/,晚一点之后我会把b站视频录制一下。

上一篇:ffmpeg整体结构


下一篇:opencv 视频处理相关