基于flutter sound插件实现录音与播放功能

目录
  • 插件介绍:
  • 插件信息:
  • 插件使用前的准备工作
    • 设置麦克风权限描述
    • 权限管理插件 permission_handler
    • 音频硬件配置插件 audio_session
    • 动画插件
  • 常用的方法
    • 录音常见的方法
    • 初始化录音对象
    • 开启录音
    • 麦克风权限
    • 开始录音
    • 结束录音
    • 播放常见的方法
    • 初始化播放器
    • 初始化操作
    • 开始播放
    • 结束播放
  • 动画实现
    • 加载GIF动画
    • 加载动画文件
  • 上传文件
    • 上传音频文件
  • 总结

插件介绍:

flutter_sound这个插件可以实现iOS和Android平台的录音和播放功能。即可以播放本地音频文件,也可以播放远程URL文件。在这里我讲介绍这个插件的用法以及碰到的一些常见问题如何解决。

  • flutter_sound支持多种录音格式
  • flutter_sound支持多种播放格式
  • flutter_sound支持音频振幅大小

插件信息:

插件地址:github.com/ryanheise/a…

插件版本:9.2.9

插件使用前的准备工作

设置麦克风权限描述

  • iOS:需要在info.plist文件添加一下权限
<key>NSMicrophoneUsageDescription</key>
<string>描述你使用麦克风用来干嘛</string>

注意:还需要在Podfile文件中配置

post_install do |installer|
  installer.pods_project.targets.each do |target|
    flutter_additional_ios_build_settings(target)
  target.build_configurations.each do |config|
        config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
          '$(inherited)',
          ## dart: PermissionGroup.microphone
          'PERMISSION_MICROPHONE=1',
        ]
      end
    end
  end

还需要在iOS工程中增加libc++.tbd库,具体路径

  • Android:需要设置AndroidManifest.xml
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

这里还用了下面几个插件

权限管理插件 permission_handler

插件信息:permission_handler: ^9.2.0

插件地址:pub.flutter-io.cn/packages/pe…

音频硬件配置插件 audio_session

插件信息:audio_session: ^0.1.6

插件地址:github.com/ryanheise/a…

动画插件

插件信息:lottie: 1.2.1

插件地址:pub.flutter-io.cn/packages/fl…

常用的方法

录音常见的方法

初始化录音对象

FlutterSoundRecorder recorderModule = FlutterSoundRecorder();

开启录音

Future<void> init() async {
  //开启录音
  await recorderModule.openRecorder();
  //设置订阅计时器
  await recorderModule
      .setSubscriptionDuration(const Duration(milliseconds: 10));
  //初始化日期插件
  await initializeDateFormatting();
}

麦克风权限

Future<bool> getPermissionStatus() async {
  Permission permission = Permission.microphone;
  //granted 通过,denied 被拒绝,permanentlyDenied 拒绝且不在提示
  PermissionStatus status = await permission.status;
  if (status.isGranted) {
    return true;
  } else if (status.isDenied) {
    requestPermission(permission);
  } else if (status.isPermanentlyDenied) {
    openAppSettings();
  } else if (status.isRestricted) {
    requestPermission(permission);
  } else {}
  return false;
}

///申请权限
void requestPermission(Permission permission) async {
  PermissionStatus status = await permission.request();
  if (status.isPermanentlyDenied) {
    openAppSettings();
  }
}

开始录音

/// 开始录音
_startRecorder() async {
  try {
    //获取麦克风权限
    await getPermissionStatus().then((value) async {
      if (!value) {
        return;
      }
      //用户允许使用麦克风之后开始录音
      Directory tempDir = await getTemporaryDirectory();
      var time = DateTime.now().millisecondsSinceEpoch;
      String path = '${tempDir.path}/$time${ext[Codec.aacADTS.index]}';

      //这里我录制的是aac格式的,还有其他格式
      await recorderModule.startRecorder(
        toFile: path,
        codec: Codec.aacADTS,
        bitRate: 8000,
        numChannels: 1,
        sampleRate: 8000,
      );
      /// 监听录音
      _recorderSubscription = recorderModule.onProgress!.listen((e) {
        var date = DateTime.fromMillisecondsSinceEpoch(
            e.duration.inMilliseconds,
            isUtc: true);
        var txt = DateFormat('mm:ss:SS', 'en_GB').format(date);
        //设置了最大录音时长
        if (date.second >= _maxLength) {
          _stopRecorder();
          return;
        }
        setState(() {
          //更新录音时长
          _recordText = txt.substring(1, 5);
        });
      });
      setState(() {
         //更新录音状态和录音文件路径
        _state = RecordPlayState.recording;
        _path = path;
      });
    });
  } catch (err) {
    setState(() {
      _stopRecorder();
      _state = RecordPlayState.record;
      _cancelRecorderSubscriptions();
    });
  }
}

结束录音

/// 结束录音
_stopRecorder() async {
  try {
    await recorderModule.stopRecorder();
    _cancelRecorderSubscriptions();
    // _getDuration();
  } catch (err) {}
  setState(() {
    _state = RecordPlayState.record;
  });
}
///销毁录音
void dispose() {
  super.dispose();
  _cancelRecorderSubscriptions();
  _releaseFlauto();
}
/// 取消录音监听
void _cancelRecorderSubscriptions() {
  if (_recorderSubscription != null) {
    _recorderSubscription!.cancel();
    _recorderSubscription = null;
  }
}
/// 释放录音
Future<void> _releaseFlauto() async {
  try {
    await recorderModule.closeRecorder();
  } catch (e) {}
}
/// 判断文件是否存在
Future<bool> _fileExists(String path) async {
  return await File(path).exists();
}

播放常见的方法

初始化播放器

FlutterSoundPlayer playerModule = FlutterSoundPlayer();

初始化操作

init() async {
  await playerModule.closePlayer();
  await playerModule.openPlayer();
  await playerModule
      .setSubscriptionDuration(const Duration(milliseconds: 10));
//这块是设置音频,暂时没用到可以不用设置
  final session = await AudioSession.instance;
  await session.configure(AudioSessionConfiguration(
    avAudioSessionCategory: AVAudioSessionCategory.playAndRecord,
    avAudioSessionCategoryOptions:
        AVAudioSessionCategoryOptions.allowBluetooth |
            AVAudioSessionCategoryOptions.defaultToSpeaker,
    avAudioSessionMode: AVAudioSessionMode.spokenAudio,
    avAudioSessionRouteSharingPolicy:
        AVAudioSessionRouteSharingPolicy.defaultPolicy,
    avAudioSessionSetActiveOptions: AVAudioSessionSetActiveOptions.none,
    androidAudioAttributes: const AndroidAudioAttributes(
      contentType: AndroidAudioContentType.speech,
      flags: AndroidAudioFlags.none,
      usage: AndroidAudioUsage.voiceCommunication,
    ),
    androidAudioFocusGainType: AndroidAudioFocusGainType.gain,
    androidWillPauseWhenDucked: true,
  ));
}

开始播放

///开始播放,这里做了一个播放状态的回调
void startPlayer(PlayStateBack callBack) async {
  try {
    if (path.contains('http')) {
      await playerModule.startPlayer(
          fromURI: path,
          codec: Codec.mp3,
          sampleRate: 44000,
          whenFinished: () {
            stopPlayer();
            callBack(0);
          });
    } else {
      //判断文件是否存在
      if (await _fileExists(path)) {
        if (playerModule.isPlaying) {
          playerModule.stopPlayer();
        }
        await playerModule.startPlayer(
            fromURI: path,
            codec: Codec.aacADTS,
            sampleRate: 44000,
            whenFinished: () {
              stopPlayer();
              callBack(0);
            });
      } else {}
    }
    //监听播放进度
    _playerSubscription = playerModule.onProgress!.listen((e) {});
    callBack(1);
  } catch (err) {
    callBack(0);
  }
}

结束播放

/// 结束播放
void stopPlayer() async {
  try {
    await playerModule.stopPlayer();
    cancelPlayerSubscriptions();
  } catch (err) {}
}
/// 取消播放监听
void cancelPlayerSubscriptions() {
  if (_playerSubscription != null) {
    _playerSubscription!.cancel();
    _playerSubscription = null;
  }
}
///获取播放状态
Future<PlayerState> getPlayState() async {
  return await playerModule.getPlayerState();
}
/// 释放播放器
void releaseFlauto() async {
  try {
    await playerModule.closePlayer();
  } catch (e) {
    print(e);
  }
}
/// 判断文件是否存在
Future<bool> _fileExists(String path) async {
  return await File(path).exists();
}

动画实现

在进行录音和播放的过程中难免使用到动画,这里我说下如何加载gif和动画文件

加载GIF动画

Visibility(
  visible: (item.playing.value == 1) ? true : false,
  child: Image.asset('assets/-comm/comm_audio_paly.gif', width: 20, height: 20,),
  replacement: const Image(
    image: AssetImage('assets/-comm/comm_audio_icon.png'),
    width: 20,
    height: 20,
  ),
)

加载动画文件

Lottie.asset('assets/-comm/record_audio_animation.json',
    height: 25,
    width: ScreenAdapter.screenWidth() -ScreenAdapter.width(160),
    animate: true)

上传文件

上传音频文件

var map = {
  "file": MultipartFile.fromBytes(
      await File.fromUri(Uri(path: path)).readAsBytes(),
      filename: "$fileName.mp3",
      contentType: MediaType.parse("audio/mp3"))
};

总结

上面介绍了如何录音,如何播放本地和远程音频文件,以及如何实现动画,在录制完音频文件后如何上传,这些都是我们平常使用这个功能会遇到的问题。在使用的过程中遇到的问题也有列出,希望对您有所帮助。

到此这篇关于基于flutter sound插件实现录音与播放功能的文章就介绍到这了,更多相关flutter sound录音与播放内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 详解Flutter中视频播放器插件的使用教程

    目录 创建一个新的视频播放器 添加播放和暂停按钮 创建一个快进 添加一个视频进度指示器 应用视频的字幕 结论 您已经看到很多包含视频内容的应用程序,比如带有视频教程的食谱应用程序.电影应用程序和体育相关的应用程序.您是否想知道如何将视频内容添加到您的下一个Flutter应用程序中? 从头开始实现视频功能将是一项繁重的任务.但有几个插件可以让开发者的生活变得轻松.视频播放器插件是可用于 Flutter 的最佳插件之一,可满足这一要求. 在这篇文章中,您将学习如何应用视频播放器插件以及控制视频播放器

  • 基于flutter sound插件实现录音与播放功能

    目录 插件介绍: 插件信息: 插件使用前的准备工作 设置麦克风权限描述 权限管理插件 permission_handler 音频硬件配置插件 audio_session 动画插件 常用的方法 录音常见的方法 初始化录音对象 开启录音 麦克风权限 开始录音 结束录音 播放常见的方法 初始化播放器 初始化操作 开始播放 结束播放 动画实现 加载GIF动画 加载动画文件 上传文件 上传音频文件 总结 插件介绍: flutter_sound这个插件可以实现iOS和Android平台的录音和播放功能.即可

  • 基于JS实现web端录音与播放功能

    纯js实现web端录音功能,功能并不是特别多,逐步增加中,详细地址:github. getUserMedia在非localhost和127的情况下,需要开启https,由于腾讯云的没备案,demo就不放了,可以自行获取代码并启动测试. 实现方式 实现原理的话,主要是以下三点, 利用webrtc的getUserMedia方法获取设备音频输入,使用audioprocess得到音频流(pcm流,范围-1到1). 转码,利用前端中的ArrayBuffer等二进制操作按采样位数处理流信息. 使用decod

  • 基于Flutter实现图片选择和图片上传

    目录 内容简介 图片选择插件 权限申请 UI 改造 图片上传 内容简介 本篇将介绍 Flutter 中如何完成图片上传,以及上传成功后的表单提交.涉及的知识点如下: 图片选择插件wechat_assets_picker的使用. 图片选择 iOS 和安卓的应用权限配置. 图片选择组件的封装. 图片上传接口的封装. 添加和编辑页面中图片上传实现. 图片选择插件 Flutter 的图片选择插件很多,包括了官方的 image_picker,multi_image_picker(基于2.0出了 multi

  • Android基于Flutter编写文件下载管理器

    目录 前言 Dio 的下载方法 download 监测下载进度 取消下载 删除已经下载的文件 调试过程中遇到的一些错误 运行结果及代码 总结 前言 文件下载在很多类型的应用中会涉及,例如音乐.文档.包括图片(只是图片可以使用一些组件完成无感知的下载).本篇介绍使用 Dio 的下载方法完成文件的下载,涉及到的内容如下: Dio 插件的 download 方法介绍: 使用 download 的回调方法监测下载进度: 使用 CancelToken 取消正在下载的任务: 删除已下载的文件: path_p

  • 基于Bootstrap3表格插件和分页插件实例详解

    首先看下实现效果图,如果觉得还不错,请参考实现代码. 上面数据 下面分页 使用方法 1 导入bootstrap的css <link rel="stylesheet" href="css/v3/bootstrap.min.css"> 2 导入jquery <script src="js/jquery-1.10.1.min.js" type="text/javascript"></script>

  • 基于jQuery Circlr插件实现产品图片360度旋转

    Circlr是一款可以对产品图片进行360度全方位旋转展示的jQuery插件.Circlr通过按一定角度规律拍摄的产品图片,制作出可以使用鼠标拖动.鼠标滚轮和移动触摸来进行图片逐帧旋转的效果.比先前的Rollerblade,动画顺畅了许多,也更易于控制,该插件非常适合于商品的展示. 它的特点有: 支持水平或垂直方向旋转. 支持移动触摸事件. 支持滚动事件. 图片预加载处理. 可以反向和循环旋转图片. jQ酷实例教程:jQuery产品图片360度旋转Circlr 引入核心文件 <script sr

  • 基于Marquee.js插件实现的跑马灯效果示例

    本文实例讲述了基于Marquee.js插件实现的跑马灯效果.分享给大家供大家参考,具体如下: 1.Marquee.js文件 /**************************************************************** - Marquee.js - 参数: - ID:滚动对象(必须) - Direction:滚动方向("top": 0, "up": 0, "bottom": 1, "down"

  • 纯JavaScript基于notie.js插件实现消息提示特效

    本文实例介绍了纯JavaScript实现消息提示特效是一款基于notie.js插件实现的可以制作Alert提示框,确认框和带输入的消息框,分享给大家供大家参考,具体内容如下 效果图: 实现的代码: html代码: <br><br><br><br><br><br> <article class="zzsc"> <div class="div-ext"> <div cl

  • 基于jquery fly插件实现加入购物车抛物线动画效果

    先给大家展示下效果图: 在购物网站中,加入购物车的功能是必须的功能,有的网站在用户点击加入购物车按钮时,就会出现该商品从点击出以抛物线的动画相似加入购物车,这个功能看起来非常炫,对用户体验也有一定的提高.下面介绍基于jquery fly插件实现加入购物车抛物线动画效果. 使用jquery.fly插件很方便时实现抛物线动画加入购物车的功能 一.插件下载 插件官方:https://github.com/amibug/fly 二.载入jQuery库文件和jquery.fly.min.js插件 <scr

  • 基于jQuery Tipso插件实现消息提示框特效

    基于jQuery Tipso插件实现消息提示框的特点是可以定义提示框的显示位置,以及动态改变提示框的提示内容,应该说是一款相当灵活的jQuery消息提示框插件,分享给大家供大家参考,具体内容如下 在线演示 源码下载 实现的代码: <div class="dowebok"> <h2> 1.默认</h2> <div class="inner"> <span id="tip1" data-tipso

随机推荐