基于flutter?sound插件實現(xiàn)錄音與播放功能
插件介紹:
flutter_sound
這個插件可以實現(xiàn)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, ); /// 監(jiān)聽錄音 _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(() { //更新錄音狀態(tài)和錄音文件路徑 _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(); } /// 取消錄音監(jiān)聽 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, )); }
開始播放
///開始播放,這里做了一個播放狀態(tài)的回調(diào) 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 {} } //監(jiān)聽播放進度 _playerSubscription = playerModule.onProgress!.listen((e) {}); callBack(1); } catch (err) { callBack(0); } }
結束播放
/// 結束播放 void stopPlayer() async { try { await playerModule.stopPlayer(); cancelPlayerSubscriptions(); } catch (err) {} } /// 取消播放監(jiān)聽 void cancelPlayerSubscriptions() { if (_playerSubscription != null) { _playerSubscription!.cancel(); _playerSubscription = null; } } ///獲取播放狀態(tài) 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(); }
動畫實現(xiàn)
在進行錄音和播放的過程中難免使用到動畫,這里我說下如何加載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")) };
總結
上面介紹了如何錄音,如何播放本地和遠程音頻文件,以及如何實現(xiàn)動畫,在錄制完音頻文件后如何上傳,這些都是我們平常使用這個功能會遇到的問題。在使用的過程中遇到的問題也有列出,希望對您有所幫助。
到此這篇關于基于flutter sound插件實現(xiàn)錄音與播放功能的文章就介紹到這了,更多相關flutter sound錄音與播放內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Android控件之SlidingDrawer(滑動式抽屜)詳解與實例分享
這篇文章詳細介紹了Android控件之SlidingDrawer(滑動式抽屜)與實例,有需要的朋友可以參考一下2013-10-10ViewPager和SlidingPaneLayout的滑動事件沖突解決方法
下面小編就為大家分享一篇ViewPager和SlidingPaneLayout的滑動事件沖突解決方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-01-01Android從Fragment跳轉到其他Activity的簡單實例
這篇文章主要介紹了Android從Fragment跳轉到其他Activity的簡單實例,本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2020-02-02在當前Activity之上創(chuàng)建懸浮view之WindowManager懸浮窗效果
這篇文章主要介紹了在當前Activity之上創(chuàng)建懸浮view之WindowManager懸浮窗效果的相關資料,需要的朋友可以參考下2016-01-01AndroidStduio3.0 使用gradle將module打包jar文件的方法
這篇文章主要介紹了AndroidStduio3.0 使用gradle將module打包jar文件的方法,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下2019-04-04