Flutter如何实现录音时播放波形动图

在Flutter中,我想实现录音时实时显示波形动图的效果,类似音频可视化。目前已经通过mic_streamrecord插件实现了录音功能,但不知道如何将音频数据实时转换为波形并动态渲染到界面上。有没有成熟的方案或插件推荐?需要注意哪些性能问题?能否提供简单的代码示例?

2 回复

在Flutter中,使用audioplayerssound_stream库录制音频,结合flutter_audio_waveforms或自定义CustomPainter绘制实时波形。通过Stream获取音频数据,更新UI实现动态波形效果。

更多关于Flutter如何实现录音时播放波形动图的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在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库进行频谱分析实现更复杂效果

此方案实现了基础的录音波形动态显示,可根据需求调整波形样式和动画效果。

回到顶部