flutter sound录音与播放
周糖果 人气:18插件介绍:
flutter_sound
这个插件可以实现iOS和Android
平台的录音和播放功能。即可以播放本地音频文件,也可以播放远程URL文件。在这里我讲介绍这个插件的用法以及碰到的一些常见问题如何解决。
flutter_sound支持多种录音格式
flutter_sound支持多种播放格式
flutter_sound支持音频振幅大小
插件信息:
插件版本: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
动画插件
插件信息: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")) };
总结
上面介绍了如何录音,如何播放本地和远程音频文件,以及如何实现动画,在录制完音频文件后如何上传,这些都是我们平常使用这个功能会遇到的问题。在使用的过程中遇到的问题也有列出,希望对您有所帮助。
加载全部内容