基于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"))
};

复制代码

总结

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

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: Flutter 可以使用 `video_player` 插件播放视频。安装方法如下: 1. 在 `pubspec.yaml` 文件中添加 `video_player` 依赖: ``` dependencies: flutter: sdk: flutter video_player: ^X.X.X ``` 注意:将 `X.X.X` 替换为最新版本号。 2. 运行 `flutter pub get` 命令来下载该插件。 3. 在 Flutter 应用程序中导入该插件: ``` import 'package:video_player/video_player.dart'; ``` 然后就可以使用 `VideoPlayer` 类来播放视频了。如果需要了解更多关于如何使用 `video_player` 插件的信息,可以参考官方文档:https://pub.dev/packages/video_player ### 回答2: Flutter是一个跨平台的移动应用开发框架,可以帮助开发者快速构建漂亮且高性能的移动应用。在Flutter中,我们可以使用插件来扩展应用的功能。以下是关于Flutter播放video插件的解答。 要在Flutter播放video,我们可以使用一些常用的video播放插件。一个非常流行的插件是video_player插件。video_player插件提供了一个简单易用的API,用于加载和播放video。 首先,我们需要在pubspec.yaml文件中添加video_player插件的依赖。然后,在Flutter应用程序的代码中,我们可以使用video_player插件来开发video播放功能。 video_player插件提供了一个VideoPlayer控件,我们可以使用该控件来展示和控制video的播放。在代码中,我们需要创建一个VideoPlayerController对象,然后通过VideoPlayer控件将其与视图关联起来。 详细步骤如下: 1. 导入video_player插件的包,这可以通过在代码的开头添加`import 'package:video_player/video_player.dart';`来实现。 2. 在StatefulWidget的类中创建一个VideoPlayerController对象,这可以通过在`initState()`方法中使用`VideoPlayerController.asset()`或`VideoPlayerController.network()`方法来实现。前者用于从assets加载video,后者用于从网络加载video。并且,注意给video_player控件传递controller参数。 3. 在Widget树中使用VideoPlayer控件来展示和控制video的播放。我们可以使用`AspectRatio`控件来调整视频播放器的宽高比,并且通过`controller`参数将VideoPlayerController与VideoPlayer控件关联。 4. 可以使用类似于`controller.play()`、`controller.pause()`等方法来控制video的播放。 通过这些步骤,我们就可以在Flutter应用中实现video播放功能了。当然,这只是video播放的基本用法,我们还可以通过video_player插件的其他API来实现更多复杂的功能,如全屏播放、进度条控制等。 总而言之,使用video_player插件,我们可以在Flutter中方便地实现video播放功能,使得我们的应用程序更加丰富和多样化。 ### 回答3: Flutter是一种跨平台的移动应用开发框架,它允许开发者使用单一代码库来创建iOS和Android应用。Flutter提供了丰富的插件系统,其中包括用于播放视频的插件。 在Flutter中,可以使用video_player插件播放视频。video_player是一个流行的Flutter插件,它提供了一种简单、方便的方法来集成视频播放功能到应用中。 要使用video_player插件,首先需要在Flutter项目的pubspec.yaml文件中添加依赖。然后在代码中导入video_player库,并创建一个VideoPlayerController对象来管理视频播放。VideoPlayerController提供了一系列方法,用于控制视频的播放、暂停、停止等操作。可以通过VideoPlayerWidget来显示视频播放的界面。 以下是使用video_player插件播放视频的基本代码: ```dart import 'package:flutter/material.dart'; import 'package:video_player/video_player.dart'; class VideoPlayerScreen extends StatefulWidget { @override _VideoPlayerScreenState createState() => _VideoPlayerScreenState(); } class _VideoPlayerScreenState extends State<VideoPlayerScreen> { VideoPlayerController _controller; Future<void> _initializeVideoPlayerFuture; @override void initState() { super.initState(); _controller = VideoPlayerController.network( 'https://example.com/sample_video.mp4'); _initializeVideoPlayerFuture = _controller.initialize(); } @override void dispose() { super.dispose(); _controller.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Video Player'), ), body: FutureBuilder( future: _initializeVideoPlayerFuture, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.done) { // 显示视频播放界面 return AspectRatio( aspectRatio: _controller.value.aspectRatio, child: VideoPlayer(_controller), ); } else { // 显示加载中的进度指示器 return Center(child: CircularProgressIndicator()); } }, ), floatingActionButton: FloatingActionButton( onPressed: () { // 播放/暂停视频 setState(() { if (_controller.value.isPlaying) { _controller.pause(); } else { _controller.play(); } }); }, child: Icon( _controller.value.isPlaying ? Icons.pause : Icons.play_arrow, ), ), ); } } ``` 通过上述代码,我们可以实现一个简单的视频播放器。对于更复杂的视频播放需求,video_player插件还提供了其他功能,例如控制视频播放进度、调整音量、全屏播放等。 总而言之,使用video_player插件可以轻松地在Flutter应用中集成视频播放功能,使用户能够享受流畅的视频体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值