Flutter音频录制插件flutter_audio_recorder3的使用

发布于 1周前 作者 sinazl 来自 Flutter

Flutter音频录制插件flutter_audio_recorder3的使用

简介

flutter_audio_recorder3 是一个支持Flutter应用程序在Android和iOS平台上进行音频录制的插件。它提供了录音、暂停、恢复和停止的功能,并且可以访问音频电平计量属性(如平均功率和峰值功率)。

工作平台

  • Android
  • iOS

安装

  1. pubspec.yaml 文件中添加 flutter_audio_recorder3 依赖:
    dependencies:
      flutter_audio_recorder3: ^最新版本号
    

权限设置

iOS权限
  1. Info.plist 文件中添加麦克风使用描述:
    <key>NSMicrophoneUsageDescription</key>
    <string>Can We Use Your Microphone Please</string>
    
  2. 使用 hasPermission API 在需要时请求用户权限。
Android权限
  1. ./android/app/src/main/AndroidManifest.xml 文件中添加以下权限:
    <uses-permission android:name="android.permission.RECORD_AUDIO"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    
  2. 使用 hasPermission API 在需要时请求用户权限。

配置

  • iOS部署目标:iOS 8.0及以上。
  • Android
    • AndroidX:使用最新版本(如 0.5.x)。
    • 旧版Android:使用旧版本(如 0.4.9)。

使用方法

推荐的API使用顺序为:hasPermission => init > start -> (pause <-> resume) * n -> stop,在开始新的录音前再次调用 init

检查权限
bool hasPermission = await FlutterAudioRecorder3.hasPermissions;
初始化

在开始录音之前运行此代码,以检查给定名称的文件是否已存在:

var recorder = FlutterAudioRecorder3("file_path.mp4"); // 支持 .wav .aac .m4a
await recorder.initialized;

或指定音频格式:

var recorder = FlutterAudioRecorder3("file_path", audioFormat: AudioFormat.AAC); // 或 AudioFormat.WAV
await recorder.initialized;

设置采样率(默认为16000):

var recorder = FlutterAudioRecorder3("file_path", audioFormat: AudioFormat.AAC, sampleRate: 22000);
await recorder.initialized;
开始录音
await recorder.start();
var recording = await recorder.current(channel: 0);
获取录音详情
var current = await recording.current(channel: 0);
// print(current.status);

可以使用定时器每50毫秒获取一次录音详情:

new Timer.periodic(tick, (Timer t) async {
  var current = await recording.current(channel: 0);
  // print(current.status);
  setState(() {
  });
});
暂停
await recorder.pause();
恢复
await recorder.resume();
停止

停止录音后,重新调用 init 以创建新的录音:

var result = await recorder.stop();
File file = widget.localFileSystem.file(result.path);

示例代码

以下是一个完整的示例代码,展示了如何使用 flutter_audio_recorder3 插件进行音频录制、暂停、恢复和播放:

import 'dart:async';
import 'dart:io' as io;

import 'package:audioplayers/audioplayers.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_audio_recorder3/flutter_audio_recorder3.dart';
import 'package:path_provider/path_provider.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  SystemChrome.setEnabledSystemUIOverlays([]);
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  [@override](/user/override)
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: SafeArea(
          child: RecorderExample(),
        ),
      ),
    );
  }
}

class RecorderExample extends StatefulWidget {
  final LocalFileSystem localFileSystem;

  RecorderExample({LocalFileSystem? localFileSystem})
      : this.localFileSystem = localFileSystem ?? LocalFileSystem();

  [@override](/user/override)
  State<StatefulWidget> createState() => RecorderExampleState();
}

class RecorderExampleState extends State<RecorderExample> {
  FlutterAudioRecorder3? _recorder;
  Recording? _current;
  RecordingStatus _currentStatus = RecordingStatus.Unset;

  [@override](/user/override)
  void initState() {
    super.initState();
    _init();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Center(
      child: Padding(
        padding: EdgeInsets.all(8.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: [
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: TextButton(
                    onPressed: () {
                      switch (_currentStatus) {
                        case RecordingStatus.Initialized:
                          _start();
                          break;
                        case RecordingStatus.Recording:
                          _pause();
                          break;
                        case RecordingStatus.Paused:
                          _resume();
                          break;
                        case RecordingStatus.Stopped:
                          _init();
                          break;
                        default:
                          break;
                      }
                    },
                    child: _buildText(_currentStatus),
                    style: ButtonStyle(
                      backgroundColor: MaterialStateProperty.all<Color>(Colors.lightBlue),
                    ),
                  ),
                ),
                TextButton(
                  onPressed: _currentStatus != RecordingStatus.Unset ? _stop : null,
                  child: Text("Stop", style: TextStyle(color: Colors.white)),
                  style: ButtonStyle(
                    backgroundColor: MaterialStateProperty.all<Color>(Colors.blueAccent.withOpacity(0.5)),
                  ),
                ),
                SizedBox(width: 8),
                TextButton(
                  onPressed: onPlayAudio,
                  child: Text("Play", style: TextStyle(color: Colors.white)),
                  style: ButtonStyle(
                    backgroundColor: MaterialStateProperty.all<Color>(Colors.blueAccent.withOpacity(0.5)),
                  ),
                ),
              ],
            ),
            Text("Status : $_currentStatus"),
            Text('Avg Power: ${_current?.metering?.averagePower}'),
            Text('Peak Power: ${_current?.metering?.peakPower}'),
            Text("File path of the record: ${_current?.path}"),
            Text("Format: ${_current?.audioFormat}"),
            Text("isMeteringEnabled: ${_current?.metering?.isMeteringEnabled}"),
            Text("Extension : ${_current?.extension}"),
            Text("Audio recording duration : ${_current?.duration.toString()}"),
          ],
        ),
      ),
    );
  }

  _init() async {
    try {
      bool hasPermission = await FlutterAudioRecorder3.hasPermissions ?? false;

      if (hasPermission) {
        String customPath = '/flutter_audio_recorder_';
        io.Directory appDocDirectory;
        if (io.Platform.isIOS) {
          appDocDirectory = await getApplicationDocumentsDirectory();
        } else {
          appDocDirectory = await getExternalStorageDirectory();
        }

        customPath = appDocDirectory.path + customPath + DateTime.now().millisecondsSinceEpoch.toString();

        _recorder = FlutterAudioRecorder3(customPath, audioFormat: AudioFormat.WAV);

        await _recorder!.initialized;
        var current = await _recorder!.current(channel: 0);
        setState(() {
          _current = current;
          _currentStatus = current!.status!;
        });
      } else {
        ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("You must accept permissions")));
      }
    } catch (e) {
      print(e);
    }
  }

  _start() async {
    try {
      await _recorder!.start();
      var recording = await _recorder!.current(channel: 0);
      setState(() {
        _current = recording;
      });

      const tick = Duration(milliseconds: 50);
      Timer.periodic(tick, (Timer t) async {
        if (_currentStatus == RecordingStatus.Stopped) {
          t.cancel();
        }

        var current = await _recorder!.current(channel: 0);
        setState(() {
          _current = current;
          _currentStatus = _current!.status!;
        });
      });
    } catch (e) {
      print(e);
    }
  }

  _resume() async {
    await _recorder!.resume();
    setState(() {});
  }

  _pause() async {
    await _recorder!.pause();
    setState(() {});
  }

  _stop() async {
    var result = await _recorder!.stop();
    File file = widget.localFileSystem.file(result.path);
    setState(() {
      _current = result;
      _currentStatus = _current!.status!;
    });
  }

  Widget _buildText(RecordingStatus status) {
    var text = "";
    switch (_currentStatus) {
      case RecordingStatus.Initialized:
        text = 'Start';
        break;
      case RecordingStatus.Recording:
        text = 'Pause';
        break;
      case RecordingStatus.Paused:
        text = 'Resume';
        break;
      case RecordingStatus.Stopped:
        text = 'Init';
        break;
      default:
        break;
    }
    return Text(text, style: TextStyle(color: Colors.white));
  }

  void onPlayAudio() async {
    AudioPlayer audioPlayer = AudioPlayer();
    await audioPlayer.play(_current!.path!, isLocal: true);
  }
}

更多关于Flutter音频录制插件flutter_audio_recorder3的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter音频录制插件flutter_audio_recorder3的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用flutter_audio_recorder3插件进行音频录制的示例代码。这个插件提供了录制音频的功能,并支持多种配置选项。

首先,确保你已经在pubspec.yaml文件中添加了flutter_audio_recorder3依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_audio_recorder3: ^x.y.z  # 请替换为最新版本号

然后运行flutter pub get来安装依赖。

接下来,是一个简单的Flutter应用示例,演示如何使用flutter_audio_recorder3进行音频录制。

1. 导入必要的包

在你的Dart文件中(例如main.dart),导入flutter_audio_recorder3包:

import 'package:flutter/material.dart';
import 'package:flutter_audio_recorder3/flutter_audio_recorder3.dart';
import 'package:path_provider/path_provider.dart';

2. 创建录制控制器

在你的State类中,创建一个AudioRecorder实例:

class _MyHomePageState extends State<MyHomePage> {
  late AudioRecorder recorder;
  late String recordedFilePath;
  bool isRecording = false;

  @override
  void initState() {
    super.initState();
    initializeRecorder();
  }

  void initializeRecorder() async {
    recorder = AudioRecorder();
    recorder.setSubscriptionDurationInMs(5000); // 每5秒回调一次
    
    // 获取应用的外部存储目录
    final directory = await getApplicationDocumentsDirectory();
    recordedFilePath = "${directory.path}/audio_file.aac";

    recorder.setAudioPath(recordedFilePath);
    recorder.onRecorderStateChanged.listen((state) {
      setState(() {
        isRecording = state == RecorderState.RECORDING;
      });
    });

    recorder.onCurrentPositionChanged.listen((duration) {
      // 可以在这里更新UI显示录制时长
    });

    recorder.onProcessCompleted.listen((data) {
      // 录制完成后的回调
    });

    recorder.onError.listen((error) {
      // 错误处理
    });
  }

  @override
  void dispose() {
    recorder.stop();
    recorder.dispose();
    super.dispose();
  }

3. 添加UI控件

build方法中,添加用于开始和停止录制的按钮:

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text('Audio Recorder Demo'),
    ),
    body: Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          ElevatedButton(
            onPressed: () async {
              if (!isRecording) {
                await recorder.start(config: AudioRecorderConfig(
                  audioFormat: AudioFormat.AAC,
                  sampleRate: 44100,
                  bitRate: 128000,
                  channelConfig: ChannelConfig.STEREO,
                ));
              } else {
                await recorder.stop();
              }
            },
            child: Text(isRecording ? 'Stop Recording' : 'Start Recording'),
          ),
          SizedBox(height: 20),
          Text(isRecording ? 'Recording...' : 'Ready to Record'),
        ],
      ),
    ),
  );
}

4. 完整代码

将以上代码片段组合成一个完整的Flutter应用:

import 'package:flutter/material.dart';
import 'package:flutter_audio_recorder3/flutter_audio_recorder3.dart';
import 'package:path_provider/path_provider.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  late AudioRecorder recorder;
  late String recordedFilePath;
  bool isRecording = false;

  @override
  void initState() {
    super.initState();
    initializeRecorder();
  }

  void initializeRecorder() async {
    recorder = AudioRecorder();
    recorder.setSubscriptionDurationInMs(5000); // 每5秒回调一次
    
    final directory = await getApplicationDocumentsDirectory();
    recordedFilePath = "${directory.path}/audio_file.aac";

    recorder.setAudioPath(recordedFilePath);
    recorder.onRecorderStateChanged.listen((state) {
      setState(() {
        isRecording = state == RecorderState.RECORDING;
      });
    });

    recorder.onCurrentPositionChanged.listen((duration) {
      // 可以在这里更新UI显示录制时长
    });

    recorder.onProcessCompleted.listen((data) {
      // 录制完成后的回调
    });

    recorder.onError.listen((error) {
      // 错误处理
    });
  }

  @override
  void dispose() {
    recorder.stop();
    recorder.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Audio Recorder Demo'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            ElevatedButton(
              onPressed: () async {
                if (!isRecording) {
                  await recorder.start(config: AudioRecorderConfig(
                    audioFormat: AudioFormat.AAC,
                    sampleRate: 44100,
                    bitRate: 128000,
                    channelConfig: ChannelConfig.STEREO,
                  ));
                } else {
                  await recorder.stop();
                }
              },
              child: Text(isRecording ? 'Stop Recording' : 'Start Recording'),
            ),
            SizedBox(height: 20),
            Text(isRecording ? 'Recording...' : 'Ready to Record'),
          ],
        ),
      ),
    );
  }
}

这段代码展示了如何使用flutter_audio_recorder3插件进行音频录制,并提供了基本的UI控件来开始和停止录制。你可以根据需要对UI和功能进行进一步的定制和扩展。

回到顶部