使用NAudio录制麦克风音频生成WAV格式MemoryStream对接云API问题
解决NAudio录制直接生成合法WAV格式MemoryStream的问题
你遇到的问题核心是:直接将录制的裸PCM音频数据写入MemoryStream,缺少WAV文件必需的文件头信息(RIFF头、fmt格式块),云API无法识别这种裸数据,因此返回Bad Request。
正确的实现思路
用NAudio的WaveFileWriter直接包装MemoryStream,它会自动处理WAV头的生成和后续更新(包括录制结束后修正头中的文件大小字段),确保最终的MemoryStream是完整合法的WAV格式。
完整代码示例
1. 声明变量
private WaveIn? _waveIn; private MemoryStream? _audioMemStream; private WaveFileWriter? _waveFileWriter;
2. 启动录制的方法
private void StartRecording() { // 设置录制格式,要和你之前测试的本地WAV文件格式一致(比如16kHz、16位单声道) var recordFormat = new WaveFormat(16000, 16, 1); _waveIn = new WaveIn { WaveFormat = recordFormat }; // 初始化MemoryStream,并用WaveFileWriter包装它,自动写入WAV头 _audioMemStream = new MemoryStream(); _waveFileWriter = new WaveFileWriter(_audioMemStream, recordFormat); // 绑定事件 _waveIn.DataAvailable += OnRecordingDataAvailable; _waveIn.RecordingStopped += OnRecordingStopped; _waveIn.StartRecording(); }
3. 数据可用事件处理
private void OnRecordingDataAvailable(object sender, WaveInEventArgs e) { if (InvokeRequired) { BeginInvoke(new EventHandler<WaveInEventArgs>(OnRecordingDataAvailable), sender, e); return; } if (_waveFileWriter == null) return; // 直接写入WaveFileWriter,它会自动处理WAV头和音频数据的拼接 _waveFileWriter.Write(e.Buffer, 0, e.BytesRecorded); // 计算录制时长并判断是否停止 int recordedSeconds = (int)(_waveFileWriter.Length / _waveFileWriter.WaveFormat.AverageBytesPerSecond); if (recordedSeconds >= 5) { StopRecording(); } else { progressBar1.Value = recordedSeconds; } }
4. 录制停止后的处理(调用API)
private void OnRecordingStopped(object sender, StoppedEventArgs e) { if (InvokeRequired) { BeginInvoke(new EventHandler<StoppedEventArgs>(OnRecordingStopped), sender, e); return; } // 释放资源,确保WaveFileWriter完成头信息的更新 _waveFileWriter?.Flush(); _waveFileWriter?.Dispose(); _waveIn?.Dispose(); if (_audioMemStream == null) return; // 将MemoryStream的位置重置到开头,确保API从WAV头开始读取 _audioMemStream.Position = 0; // 调用云API var recResult = speechToText.Recognize( audio: _audioMemStream, model: "pt-BR_Multimedia", contentType: "audio/wav"); // 处理识别结果... } private void StopRecording() { _waveIn?.StopRecording(); }
关键注意事项
- 格式匹配:确保录制的
WaveFormat和你之前测试的本地WAV文件完全一致(采样率、位深、声道数),云API通常对音频格式有严格要求,格式不匹配也会导致请求失败。 - MemoryStream位置重置:录制结束后必须将
Position设为0,否则API会从流的末尾开始读取,无法获取有效数据。 - 资源释放:录制停止后要正确释放
WaveFileWriter和WaveIn资源,确保WAV头的文件大小字段被正确更新。
内容的提问来源于stack exchange,提问作者Marcio Correa
相关产品推荐
相关产品推荐

