在Flutter中实现录音时播放波形动图,可以使用record库进行录音,结合CustomPaint或第三方波形库绘制动态波形。以下是实现步骤和示例代码:
1. 添加依赖
在pubspec.yaml中添加:
dependencies:
record: ^4.5.0
2. 实现录音与波形绘制
import 'package:flutter/material.dart';
import 'package:record/record.dart';
class AudioWaveformScreen extends StatefulWidget {
@override
_AudioWaveformScreenState createState() => _AudioWaveformScreenState();
}
class _AudioWaveformScreenState extends State<AudioWaveformScreen> {
final Record _audioRecord = Record();
bool _isRecording = false;
List<double> _waveformData = []; // 存储音频振幅数据
@override
void initState() {
super.initState();
_initRecorder();
}
_initRecorder() async {
final hasPermission = await _audioRecord.hasPermission();
if (!hasPermission) return;
// 配置录音参数(支持实时振幅)
await _audioRecord.start(
const RecordConfig(
encoder: AudioEncoder.aacLc,
numChannels: 1,
sampleRate: 44100,
),
onAmplitudeChanged: (amplitude) {
// 实时更新振幅数据(转换为0-1范围)
setState(() {
_waveformData.add((amplitude.current + 160) / 160);
if (_waveformData.length > 100) _waveformData.removeAt(0);
});
},
);
}
_toggleRecording() async {
if (_isRecording) {
await _audioRecord.stop();
} else {
await _audioRecord.start(...); // 复用init中的配置
}
setState(() => _isRecording = !_isRecording);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
// 波形图区域
Container(
height: 150,
child: CustomPaint(
painter: WaveformPainter(_waveformData),
size: Size.infinite,
),
),
// 录音按钮
ElevatedButton(
onPressed: _toggleRecording,
child: Text(_isRecording ? '停止录音' : '开始录音'),
),
],
),
);
}
}
// 自定义波形绘制
class WaveformPainter extends CustomPainter {
final List<double> amplitudes;
WaveformPainter(this.amplitudes);
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()
..color = Colors.blue
..strokeWidth = 2
..style = PaintingStyle.stroke;
final path = Path();
final centerY = size.height / 2;
for (int i = 0; i < amplitudes.length; i++) {
final x = i * (size.width / amplitudes.length);
final y = centerY - amplitudes[i] * centerY;
if (i == 0) path.moveTo(x, y);
else path.lineTo(x, y);
}
canvas.drawPath(path, paint);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}
3. 关键说明
- 振幅处理:
onAmplitudeChanged 回调提供实时振幅数据(负值),需转换为正数比例
- 波形更新:通过
setState更新数据触发重绘,限制数据长度避免内存溢出
- 性能优化:可考虑使用
StreamBuilder分离UI与数据逻辑
4. 扩展建议
- 使用
just_audio等库实现播放时的波形显示
- 添加平滑动画:通过
Tween实现波形点的插值动画
- 使用
fft库进行频谱分析实现更复杂效果
此方案实现了基础的录音波形动态显示,可根据需求调整波形样式和动画效果。