Flutter中录制音频时实时显示声波的实现方案求助
Flutter 录制音频+实时声波效果实现方案
核心依赖组合
不用找一站式专属包,用两个成熟包搭配就能实现需求:
audio_recorder2:负责音频录制,支持实时获取音频振幅数据flutter_waveforms:专门用于绘制声波/波形图,支持自定义样式
实现步骤
1. 添加依赖到pubspec.yaml
dependencies: flutter: sdk: flutter audio_recorder2: ^2.0.0 flutter_waveforms: ^1.0.0
执行flutter pub get完成依赖安装。
2. 权限配置
- Android:在
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>需要访问麦克风进行音频录制</string>
3. 核心代码实现
import 'package:flutter/material.dart'; import 'package:audio_recorder2/audio_recorder2.dart'; import 'package:flutter_waveforms/flutter_waveforms.dart'; class AudioRecorderWithWaveform extends StatefulWidget { const AudioRecorderWithWaveform({super.key}); @override State<AudioRecorderWithWaveform> createState() => _AudioRecorderWithWaveformState(); } class _AudioRecorderWithWaveformState extends State<AudioRecorderWithWaveform> { bool _isRecording = false; List<double> _waveformData = []; late RecorderController _recorderController; @override void initState() { super.initState(); _recorderController = RecorderController() ..onAmplitudeChanged = (amplitude) { if (_isRecording) { setState(() { // 将振幅归一化到0-1范围,适配波形图绘制 _waveformData.add(amplitude.normalized); // 限制数据长度,避免内存占用过高 if (_waveformData.length > 100) { _waveformData.removeAt(0); } }); } }; } @override void dispose() { _recorderController.dispose(); super.dispose(); } Future<void> _toggleRecording() async { if (_isRecording) { await _recorderController.stop(); setState(() => _isRecording = false); } else { await _recorderController.start(); setState(() { _isRecording = true; _waveformData.clear(); }); } } @override Widget build(BuildContext context) { return Scaffold( body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ // 实时波形图区域 Container( height: 150, width: double.infinity, padding: const EdgeInsets.symmetric(horizontal: 20), child: WaveformWidget( data: _waveformData, style: WaveformStyle( waveColor: Colors.blue, backgroundColor: Colors.grey[200], showMiddleLine: false, ), ), ), const SizedBox(height: 40), // 录制控制按钮 ElevatedButton( onPressed: _toggleRecording, style: ElevatedButton.styleFrom( shape: const CircleBorder(), padding: const EdgeInsets.all(20), ), child: Icon(_isRecording ? Icons.stop : Icons.mic), ), ], ), ), ); } }
4. 自定义波形样式
如果默认样式不符合需求,可通过WaveformStyle调整:
- 修改
waveColor设置波形颜色 - 调整
waveThickness改变线条粗细 - 设置
maxHeight控制波形最大高度 - 开启
showMiddleLine显示中线
备选方案:自定义绘制波形
如果flutter_waveforms不满足需求,可通过CustomPaint手动绘制:
class CustomWaveform extends StatelessWidget { final List<double> data; const CustomWaveform({super.key, required this.data}); @override Widget build(BuildContext context) { return CustomPaint( painter: WaveformPainter(data: data), size: const Size(double.infinity, 150), ); } } class WaveformPainter extends CustomPainter { final List<double> data; WaveformPainter({required this.data}); @override void paint(Canvas canvas, Size size) { final paint = Paint()..color = Colors.blue; final step = size.width / data.length; for (int i = 0; i < data.length; i++) { final height = data[i] * size.height; canvas.drawRect( Rect.fromLTWH( i * step, (size.height - height) / 2, step - 2, height, ), paint, ); } } @override bool shouldRepaint(covariant WaveformPainter oldDelegate) { return oldDelegate.data != data; } }
内容的提问来源于stack exchange,提问作者VolkanUstekidag
相关产品推荐
相关产品推荐

