Flutter开发笔记 —— 语音消息功能实现

前言

最近在开发一款即时通讯(IM)的聊天App,在实现语音消息功能模块后,写下该文章以做记录。

注:本文不提供相关图片资源以及IM聊天中具体实现代码,单论语音功能实现思路

需求分析

比起上来直接贴代码,我们先来逐步分析一下一个正常语音消息的需求是如何的?

  • 长按语音按钮录制用户语音内容

  • 松开按钮后发送语音消息至目标

从上可得,我们需要针对于用户的语音 录制 & 播放 方面下手!

Flutter_sound

目标地址:https://pub.dev/packages/flutter_sound

简介:Flutter_sound 是一款可以处理用户声音库

通过该插件的GitHub示例中可以了解到实现录制语音和播放的相关API为

  • FlutterSoundPlayer下的startRecorder方法 (录制)

  • FlutterSoundPlayer下的startPlayer方法 (播放)

实现思路

初始化Flutter_Sound配置

定义相关变量

  • FlutterSoundPlayer flutterSoundPlayer = FlutterSoundPlayer(); //声音播放器

  • FlutterSoundRecorder recordSound = FlutterSoundRecorder(); //声音录制器

  • Timer? recordTimer // 计时器,用来控制录音时长;

  • String timeString = "" // 用来做回显时长

  • List voicePlayList =[]; //用来控制语音播放列表

  • String voicePath = ""; //临时储存语音文件路径

初始化声音配置方法

dart 复制代码
  /*
   * @author Marinda
   * @date 2023/6/26 15:25
   * @description 初始化声音设置
   */
  initSoundSetting() async{
    await flutterSoundPlayer.openPlayer();
    await recordSound.openRecorder();
  }

录制用户语音

dart 复制代码
  /*
   * @author Marinda
   * @date 2023/6/26 15:31
   * @description 录音
   */
   recordSound() async{
    PermissionStatus status = await Permission.microphone.request();
    int time = 0;
    //权限校验
    if (status != PermissionStatus.granted) throw RecordingPermissionException("麦克风权限未授权!");
    var dir = await getExternalStorageDirectory();
    Uuid uuid = Uuid();
    String filePath = p.join(dir?.path ?? "",uuid.v4()+".mp4");
    File file = File(filePath);
    file.openWrite();
    state.voicePath.value = filePath;
    Log.i("录音保存的位置:${filePath}");
    await state.recordSound.startRecorder(
        //目标文件位置
        toFile: filePath,
        //这里可以认为是那种源
        codec: Codec.aacMP4,
        //采样率
        bitRate: 8000,
        //为1即可
        numChannels: 1
    );
  
    recordTimer = Timer.periodic(Duration(seconds: 1), (_) {
      time++;
      timeString = time.toString();
    });
  }

播放实现

dart 复制代码
  /*
   * @author Marinda
   * @date 2023/10/7 14:28
   * @description 播放语音信息 目前先做本地语音缓存处理
   */
  playVoice(String voiceUrl) async{
    Uint8List uint8list = Uint8List(0);
    //视为网络http
    if(voiceUrl.startsWith("http")){
      uint8list = ...获取MP4文件二进;
    }else{
      File voiceFile = File(voiceUrl);
      //如果不存在
      if(!voiceFile.existsSync()){
        BotToast.showText(text: "语音播放失败");
        return;
      }
      uint8list  = await voiceFile.readAsBytes();
    }

    //如果存在则进行移除播放
    if(voicePlayList.contains(tag)){
      voicePlayList.remove(tag);
      await flutterSoundPlayer.stopPlayer();
      return;
    }
    //加入语音信息队列
    voicePlayList.add(tag);
 
    await flutterSoundPlayer.startPlayer(
      fromURI: data.expandAddress,
      fromDataBuffer: uint8list,
      codec: Codec.aacMP4,
      sampleRate: 8000,
        numChannels: 1,
      whenFinished: (){
      //  播放完毕
        state.voicePlayList.remove(tag);
      }
    );
  }

结束录制

dart 复制代码
  /*
   * @author Marinda
   * @date 2023/6/26 15:33
   * @description
   */
  stopRecordSound() async{
    await recordSound.stopRecorder();
    if(recordTimer!.isActive){
      recordTimer!.cancel();
      recordTimer = null;
    }
    // 这里实现你的语音消息发送逻辑
    Log.i("停止录制!");
    timeString.value = "";
    voicePath.value = "";
  }

结束语

难度不大,主要是围绕着录音文件进行处理

值得注意的点是在播放录音文件时

记得获取目标的二进制流一并携带至startPlayer方法fromDataBuffer字段中

否则可能会出现无法播放或程序未响应等危险情况!

感谢你的观看!

相关推荐
PinkandWhite8 小时前
MySQL复习笔记
数据库·笔记·mysql
肥肠可耐的西西公主9 小时前
前端(AJAX)学习笔记(CLASS 4):进阶
前端·笔记·学习
LinXunFeng9 小时前
Flutter - iOS编译加速
flutter·xcode·apple
我是大咖10 小时前
c语言笔记 一维数组与二维数组
c语言·笔记·算法
傍晚冰川10 小时前
【江协科技STM32】ADC数模转换器-学习笔记
笔记·科技·stm32·单片机·嵌入式硬件·学习
pengyu11 小时前
系统化掌握Flutter开发之隐式动画(一):筑基之旅
android·flutter·dart
无情大菜刀12 小时前
/***************************所有笔记汇总目录***************************/
笔记
豪门土狗13 小时前
渗透测试之利用sql拿shell(附完整流程+防御方案)【上】
数据库·笔记·sql·网络安全
new出对象14 小时前
C++文件读写操作笔记
开发语言·c++·笔记·文件
AntG14 小时前
flutter webview crash 问题
flutter