flutter_sound基本用法整理

简介:本篇文章主要是根据'flutter_sound_master'中的示例代码进行整理(没有根据对应代码的注释进行整理,因此会有遗漏),并以具体功能为分类标准介绍flutter_sound的用法,适合初学者

flutter_sound主要功能:flutter_sound是基于flutter开发的音频处理依赖包,主要实现用户的音频任务,包括录音任务和播放任务,支持实时流处理和文件处理。

Player

  • 播放器类获取
    • FlutterSoundPlayer player = FlutterSoundPlayer()
  • 播放器初始化
    • player.openPlayer()
      • bool isBGService:是否后台播放
    • 播放器初始化应当放在init生命周期中
  • 开始播放
    • 从文件中播放
      • player.startPlayer()
        • Codec codec:编码格式,如mp3,wav,aac等
        • int sampleRate:采样率,只用于PCM格式音频
        • int numChannels:声道数,只用于PCM格式音频
        • void Function()  whenFinished:播放结束时调用
        • 两种数据获取方式
          • String fromURI:从网址或指定路径获取
            • 远程文件URL
            • 本地文件路径
            • 临时文件名
          • Uint8List fromDataBuffer:从字节缓冲区获取
            • Uint8List指的是8位无符号整数列表(字节列表)
    • 从流中播放(可以播放实时音频,而不需要等待完整的音频流加载到文件或内存中)
      • 流的播放关键在于Food,只有当buffer有内容时才可以进行播放,主要通过sink接口对流进行管理
      • 流的获取
        • 本地获取
          • data = rootBundle.load(path).buffer.asUint8List()
            • rootBundle主要用于加载应用的资源文件
            • 加载对应的资源文件,以Uint8List格式访问
      • player.startPlayerFromStream()
        • 介绍:进行流播放器的初始化操作(注意,并没有开始播放音频)
        • Codec codec
        • bool interleaved:音频数据的组织方式,交错模式(L1R1L2L2...)或计划模式(L1L2...R1R2...)
        • int numChannels
        • int sampleRate
        • int bufferSize:缓冲区大小设置
        • void Function()   onBufferUnderflow:缓冲区溢出时调用
      • player.uint8ListSink.add(Uint8List event)
        • 直接打开播放器的流管理接口(uint8List格式)并向其中添加内容(无背压音频播放)
        • 问题:数据直接添加进去,而播放器数据处理能力不足例如缓冲区大小不够,数据处理速度过慢则会导致数据丢失等问题
      • Future<int> player.feedUint8FromStream(Uint8List event)
        • 注意设置event的大小为min(剩余数据,bufferSize)防止溢出
        • 这是一个耗时操作,await player.feedUint8FromStream(Uint8List event)就可以实现等待音频处理结束,然后输入新的数据
        •   Future<void> feedHim(Uint8List buffer) async {
              var start = 0;
              var totalLength = buffer.length;
              while (totalLength > 0 && !_mPlayer.isStopped) {
                var ln = totalLength > kBLOCKSIZE ? kBLOCKSIZE : totalLength;
                if (flowControl) {
                  await _mPlayer.feedUint8FromStream(
                      buffer.sublist(start, start + ln)); // with await !!!!
                } else {
                  _mPlayer.uint8ListSink!.add(data.sublist(start, start + ln));
                }
                start += ln;
                totalLength -= ln;
              }
              _mPlayer.logger.d('Finished');
            }
  • 停止播放
    • player.stopPlayer()
  • 暂停播放
    • player.pausePlayer()
  • 继续播放
    • player.resumePlayer()
  • 跳转到指定的播放时间
    • player.seekToPlayer( Duration( ... ) )
    • 跳转后会延续之前的播放状态
  • 播放器销毁
    • player.closePlayer()
    • 在窗口销毁前应该销毁播放器
  • 音量控制
    • player.setVolume(0.9)
  • 音量平衡(音量+左右声道音量比例)
    • player.setVolumePan( double volume , double pan)
    • pan(-1~1)代表左右音道比例
  • 播放速度控制
    • player.setSpeed( double speed )
  • 订阅(监视器,这里是单个订阅,一个流只有一个订阅,获取流的状态,多订阅需要broadcast)
    • 订阅器事件产生设置
      • player.setSubscriptionDuration(
                Duration(milliseconds: 400)
        )
      • 设置订阅事件间隔,每隔400ms唤醒一次产生一次订阅事件
    • 订阅器
      • 流订阅器类:
        • StreamSubcription sub
      • 订阅取消
        • sub.cancel()
      • 订阅事件onProgress(onProgress是一个流Stream<PlaybackDisposition>包含(均为Duration类)duration和position)
        • sub = player.onProgress.listen((e){
                          pos = e.position.inMilliseconds;
                  }
          )
        • listen订阅该流Stream并返回一个订阅器
        • 这样就实现了对流进程的订阅
        • var date = DateTime.fromMillisecondsSinceEpoch(e.position.in...)
          var txt = FateFormat('mm:ss:SS','en_GB').format(date)
          txt.substring(0,8)
          //这段代码可以实现对于播放时间的显示

Recorder

  • 录音器类获取
    • recorder = FlutterSoundRecorder()
  • 录音器类初始化
    • recorder.openRecorder()
    • 初始化前需要获取录音权限,Permission.microphone.request()
  • 开始录音
    • 准备工作
      • 录音前需要检查设备的录音编码支持,设置为可行的的录音编码
      • recorder.isEncoderSupported(codec)检查codec是否可行
    • 保存文件路径和文件操作
      • 目录获取
        • 临时目录:getTemporaryDirectory
        • 应用私有目录:getApplicationDocumentsDirectory
        • 外部存储目录(需要权限):getExternalStorageDirectory
      • 文件操作(这里只有使用到的操作)
        • file = File(path)
        • file.existesSync():检查文件是否存在
        • file.delete():删除文件
        • Future<IOSink>   file.openWrite():简单的写入操作,并返回流操作接口sink
    • 录音到文件中
      • recorder.startRecorder()
        • toFile
        • codec
        • enableVoiceProcessing:是否启动语音处理如回声消除,噪声抑制等
        • audioSource
    • 录音到流中(主要使用流控制器StreamController和其接口sink)
      • 流控制器
        • 定义:controller = StreamController<Uint8List>()
        • 为流控制器的流添加订阅(当buffer不足时,会删去旧数据,因此需要处理)
          • StreamSink<List<int>> sink; (uint8List是List<int>的特殊形式)
          • sink = outputFile.openWrite()  //获取对应文件的写入流控制接口
          • controller.stream.listen((buffer){
                    sink.add(buffer);//当stream接收到新传来的List<int>时调用
            })
      • recorder.startRecorder()
        • toStream:controller.sink
        • codec
        • numChannels
        • sampleRate
        • bufferSize:单声道8192,双声道16384
        • audioSource
        • 每次接收到bufferSize大小的数据就会发送到stream中
      • 设置录音进度更新频率(和streamcontroller无关)
        • recorder.setSubscriptionDuration(...)
  • 录音器销毁:recorder.closeRecorder()

其它

  • 音频文件格式转换:FlutterSoundHelper().waveToPCMBuffer(inputBuffer:...)将wav转换为PCM文件,需要将wav文件以Uint8List形式导入
  • 设置日志级别:player.setLogLevel
  • player.log.d(...)
  • 非uint8List格式的音频
    • 上面的播放器使用的方法是player.feedUint8FromStream(Uint8List event),此外还有其他的方法如FeedF32和FeedInt16,分别表示不同的PCM格式
    • 但是录音器的toStream要求Uint8List,此时需要改为对应的toStreamFloat32,to StreamInt 16
  • 自制混合模式:这个原文中有,手动根据数据重新打包,感兴趣的可以去看看
  • 属性辨析
    • Codec:编码格式,指的是音频模拟信号转换为数字信号的方式,pcm16指的是2字节有符号数保存的采样点
    • 音频数据输出到流的方法
      • toStream:以Uint8(字节形式)输出,通常用于文件保存等要求字节形式的数据
      • toStreamInt16:以Int16形式输出,适合int16采样点的处理,但是不适合保存文件,因为不是字节格式
      • toStreamFloat32:以Float32形式输出
      • 综上所述,toStream适合直接对数据进行操纵,会输出所有数据如音频格式头,而其他格式是直接对采样点进行处理,不会输出如音频格式头
    • 流控制器:选择了流输出方法后应该使用对应格式的控制器进行接收

最后附上一张作者示例的运行截图,作者的example比较全面地展示了各种功能,除此之外,关于Flutter应用的整体架构和组件也涉及很多,通过这个具体的应用可以简略窥见Flutter应用设计的基本步骤和模板,还是多多推荐大家去看看源代码啊。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值