You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter macOS录音生成空文件无声音问题求助

macOS下Flutter录音后播放无声音问题解决

问题现象

在macOS系统中使用Flutter开发录音功能,采用record包实现录音、audioplayers包实现音频播放,但录制生成的音频文件播放时无声音,如同空文件。

使用依赖包

  • 录音:record
  • 播放:audioplayers

问题根源分析

  1. 录音路径初始化异步问题:Recorder组件的getDir()是异步方法,在initState中直接调用但未等待其完成,导致调用_start()录音时,path可能仍为null,录音文件被写入空路径或无效位置,最终生成空文件。
  2. macOS麦克风权限缺失:未在项目中配置麦克风使用权限,导致录音功能无法正常获取音频输入。
  3. 编码器支持检查的打印错误:_isEncoderSupported方法中循环打印支持的编码器时,错误使用了传入的encoder.name而非当前遍历的e.name,无法正确输出支持的编码器列表。

修复方案

1. 修复录音路径初始化逻辑

修改Recorder组件的初始化逻辑,确保录音路径在使用前已正确初始化:

@override
void initState() {
  super.initState();
  _audioRecorder = AudioRecorder();
  // 在帧渲染完成后初始化路径,确保异步操作完成
  WidgetsBinding.instance.addPostFrameCallback((_) async {
    await getDir();
  });

  _recordSub = _audioRecorder.onStateChanged().listen((recordState) {
    _updateRecordState(recordState);
  });

  _amplitudeSub = _audioRecorder
      .onAmplitudeChanged(const Duration(milliseconds: 300))
      .listen((amp) {
    setState(() => _amplitude = amp);
  });
}

// 同时在_start方法中增加路径检查,确保路径有效
Future<void> _start() async {
  setState(() => recordingDone = false);
  try {
    if (await _audioRecorder.hasPermission()) {
      // 确保路径已初始化
      if (path == null) {
        await getDir();
      }
      const encoder = AudioEncoder.aacLc;

      if (!await _isEncoderSupported(encoder)) {
        return;
      }

      final devs = await _audioRecorder.listInputDevices();
      debugPrint(devs.toString());

      const config = RecordConfig(encoder: encoder, numChannels: 1);
      _audioRecorder.start(config, path: path ?? '');

      _recordDuration = 0;

      _startTimer();
    }
  } catch (e) {
    if (kDebugMode) {
      print(e);
    }
  }
}

2. 添加macOS麦克风权限

在项目的macOS/Runner/Info.plist文件中添加麦克风权限描述:

<key>NSMicrophoneUsageDescription</key>
<string>需要使用麦克风进行录音</string>

3. 修正编码器支持检查的打印错误

修改_isEncoderSupported方法中的打印逻辑:

Future<bool> _isEncoderSupported(AudioEncoder encoder) async {
  final isSupported = await _audioRecorder.isEncoderSupported(
    encoder,
  );

  if (!isSupported) {
    debugPrint('${encoder.name} is not supported on this platform.');
    debugPrint('Supported encoders are:');

    for (final e in AudioEncoder.values) {
      if (await _audioRecorder.isEncoderSupported(e)) {
        // 修正为e.name
        debugPrint('- ${e.name}');
      }
    }
  }

  return isSupported;
}

4. 验证音频文件有效性

在_stop方法中添加文件大小检查,确认录音文件已正确生成:

Future<void> _stop() async {
  path = await _audioRecorder.stop();

  if (path != null) {
    final file = File(path!);
    if (await file.exists()) {
      final size = await file.length();
      debugPrint('录音文件大小:$size 字节');
      if (size == 0) {
        debugPrint('警告:生成的录音文件为空');
      }
    }
    widget.onStop(path!);
    setState(() {
      recordingDone = true;
    });
  }
}

验证步骤

  1. 重新运行项目,确保麦克风权限请求弹窗正常弹出并授权。
  2. 录制一段音频,查看控制台输出的录音文件路径和大小,确认文件非空。
  3. 使用audioplayers播放录制的音频,验证声音正常输出。

内容的提问来源于stack exchange,提问作者Shruti Ramnandan Sharma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 03:28:12