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字段中

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

感谢你的观看!

相关推荐
hanlin035 小时前
刷题笔记:力扣第32题-最长有效括号
笔记·算法·leetcode
xian_wwq6 小时前
【学习笔记】Milvus 如何完成一次向量相似度检索,Milvus 索引到底应该怎么选?-15
笔记·学习·milvus
wujiuhsu9 小时前
图片里的简体中文怎么翻译成繁体?商品图、详情页和海报批量转换方法
经验分享·笔记
程序员老刘10 小时前
跨平台开发地图 | 2026年10月
flutter·ai编程·客户端
林瞅瞅12 小时前
Flutter 开发环境从零搭建与调试记录
flutter
keyipatience13 小时前
JS学习笔记(2)数组,函数,作用域,对象
前端·javascript·笔记·学习·html
你想知道什么?13 小时前
词向量总结-学习笔记
人工智能·笔记·学习
He BianGu13 小时前
【笔记】WPF中RenderOptions类的详细功能
笔记·wpf
用AI来创业吧13 小时前
网站建设公司哪家好:报价差 3 倍,差在哪四项成本上(选型笔记)
笔记·性能优化·软件工程·安全威胁分析
一支蜉蝣15 小时前
Day25 XD安全笔记 安全开发-PHP 应用&文件管理模块&包含&上传&遍历&写入&删除&下载&安全
笔记·网络安全·php