Flutter音频波形录制插件waveform_recorder的使用

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

Flutter音频波形录制插件waveform_recorder的使用

waveform_recorder插件为Flutter应用提供了一个用于展示音频录制时波形的组件,该组件以现代AI聊天包中常见的样式呈现。以下是关于如何设置和使用此插件的详细说明。

Setup(设置)

要使此插件正常工作,您需要根据setup and permission instructions来配置底层的record包。这是因为waveform_recorder依赖于record来进行实际的音频录制功能。

Usage(用法)

示例代码

下面是一个完整的示例代码,展示了如何使用WaveformRecorder小部件进行音频录制并允许用户回放录音:

import 'dart:async';

import 'package:audioplayers/audioplayers.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:waveform_recorder/waveform_recorder.dart';

void main() => runApp(const MyApp());

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final _textController = TextEditingController();
  final _waveController = WaveformRecorderController();

  @override
  void dispose() {
    _textController.dispose();
    _waveController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) => MaterialApp(
        home: Scaffold(
          appBar: AppBar(title: const Text('WaveForm Example')),
          body: ListenableBuilder(
            listenable: _waveController,
            builder: (context, _) => Column(
              children: [
                Expanded(
                  child: Center(
                    child: OutlinedButton(
                      onPressed: !_waveController.isRecording &&
                              _waveController.file != null
                          ? _playRecording
                          : null,
                      child: const Text('Play'),
                    ),
                  ),
                ),
                Padding(
                  padding: const EdgeInsets.all(16),
                  child: Row(
                    children: [
                      Expanded(
                        child: DecoratedBox(
                          decoration: BoxDecoration(
                            border: Border.all(color: Colors.grey),
                            borderRadius: BorderRadius.circular(8),
                          ),
                          child: _waveController.isRecording
                              ? WaveformRecorder(
                                  height: 48,
                                  controller: _waveController,
                                  onRecordingStopped: _onRecordingStopped,
                                )
                              : TextField(
                                  controller: _textController,
                                  maxLines: 1,
                                  decoration: const InputDecoration(
                                    border: InputBorder.none,
                                    contentPadding: EdgeInsets.symmetric(
                                      horizontal: 8,
                                    ),
                                  ),
                                ),
                        ),
                      ),
                      const Gap(8),
                      IconButton(
                        icon: Icon(
                          _waveController.isRecording ? Icons.stop : Icons.mic,
                        ),
                        onPressed: _toggleRecording,
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),
        ),
      );

  Future<void> _toggleRecording() => switch (_waveController.isRecording) {
        true => _waveController.stopRecording(),
        false => _waveController.startRecording(),
      };

  Future<void> _onRecordingStopped() async {
    final file = _waveController.file;
    if (file == null) return;

    _textController.text = ''
        '${file.name}: '
        '${_waveController.length.inMilliseconds / 1000} seconds';

    debugPrint('XFile properties:');
    debugPrint('  path: ${file.path}');
    debugPrint('  name: ${file.name}');
    debugPrint('  mimeType: ${file.mimeType}');
  }

  Future<void> _playRecording() async {
    final file = _waveController.file;
    if (file == null) return;
    final source = kIsWeb ? UrlSource(file.path) : DeviceFileSource(file.path);
    await AudioPlayer().play(source);
  }
}

使用注意事项

  • 对于除Web之外的所有平台,录音操作的输出是硬盘上的文件;应用程序有责任在使用完临时文件后将其删除。
  • 在Web上执行时,记录的音频文件将包含指向blob URL的路径,但其他情况下它将是文件系统中的文件。可以通过WaveformRecorderController.file.path获取该文件的路径。

清理录音文件

为了确保应用程序不会留下不必要的临时文件,可以在不再需要录音文件时调用以下函数来删除它们:

Future<void> _deleteRecording() async {
  final file = _waveController.file;
  if (file == null) return;
  if (!kIsWeb) await File(file.path).delete();
}

Feedback(反馈)

如果您有任何问题或建议,请通过issuesPRs提交给开发者!


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

1 回复

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


当然,以下是如何在Flutter项目中集成并使用waveform_recorder插件来录制音频并显示波形图的详细步骤和代码示例。

1. 添加依赖

首先,在你的pubspec.yaml文件中添加waveform_recorder的依赖:

dependencies:
  flutter:
    sdk: flutter
  waveform_recorder: ^latest_version_here  # 请替换为最新版本号

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

2. 导入插件

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

import 'package:flutter/material.dart';
import 'package:waveform_recorder/waveform_recorder.dart';

3. 配置权限

AndroidManifest.xml中添加必要的权限,因为录音需要麦克风权限:

<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

对于iOS,你需要在Info.plist中添加麦克风权限请求:

<key>NSMicrophoneUsageDescription</key>
<string>This app needs access to your microphone to record audio.</string>

4. 创建录音界面

在你的主页面或者需要录音的页面中使用WaveformRecorder组件。以下是一个简单的示例:

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Waveform Recorder Example'),
        ),
        body: WaveformRecorderExample(),
      ),
    );
  }
}

class WaveformRecorderExample extends StatefulWidget {
  @override
  _WaveformRecorderExampleState createState() => _WaveformRecorderExampleState();
}

class _WaveformRecorderExampleState extends State<WaveformRecorderExample> {
  late WaveformRecorderController _controller;

  @override
  void initState() {
    super.initState();
    _controller = WaveformRecorderController();
    _controller.initialize().then((_) {
      // 请求麦克风权限
      _controller.requestPermissions().then((permissionsGranted) {
        if (permissionsGranted) {
          // 权限被授予,可以开始录音
          // 你可以在这里添加其他初始化代码
        } else {
          // 权限被拒绝,处理拒绝逻辑
        }
      });
    });
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(16.0),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          WaveformRecorderWidget(
            controller: _controller,
            style: WaveformRecorderStyle(
              height: 200,
              backgroundColor: Colors.grey[200],
              waveformColor: Colors.blue,
            ),
          ),
          SizedBox(height: 20),
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              ElevatedButton(
                onPressed: () async {
                  if (await _controller.isRecording) {
                    await _controller.stopRecording();
                  } else {
                    await _controller.startRecording(filePath: 'path_to_save_audio_file.wav');
                  }
                },
                child: Text(
                  _controller.isRecording ? 'Stop Recording' : 'Start Recording',
                ),
              ),
            ],
          ),
        ],
      ),
    );
  }
}

5. 运行应用

确保你已经连接了Android模拟器或iOS模拟器,或者将物理设备连接到你的开发环境,然后运行flutter run来启动应用。

注意事项

  • filePath参数应该是一个有效的文件路径,你可以使用path_provider插件来获取应用沙盒内的路径。
  • 录音结束后,你可以通过_controller.audioFilePath来获取录音文件的路径。
  • 插件的具体方法和参数可能会随着版本更新而变化,请参考最新的waveform_recorder文档来获取最新信息。

希望这个示例能帮助你顺利地在Flutter项目中集成waveform_recorder插件!

回到顶部