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

通过HTTP流读取WAV到AudioInputStream时语音识别结果极差

问题:通过HTTP流推送WAV文件到Azure Speech Service时识别结果极差,本地文件正常

我尝试从URL下载WAV文件并通过AudioInputStream推送到Azure Speech Service进行识别时,得到的结果极差,但将文件下载到本地后用AudioConfig.FromWavFileInput读取时识别完全准确。怀疑问题出在BinaryReader读取流的环节,但不确定具体原因,寻求排查和解决建议。

相关代码:

HttpResponseMessage wavresponse = await _httpClient.GetAsync($"{recordingUrl}.wav").ConfigureAwait(continueOnCapturedContext: false);
using var httpStream = await wavresponse.Content.ReadAsStreamAsync();

var speechConfig = SpeechConfig.FromSubscription(_speechOptions.Key, _speechOptions.Region);
speechConfig.SpeechRecognitionLanguage = "de-DE";

var reader = new BinaryReader(httpStream);
using var audioInputStream = AudioInputStream.CreatePushStream();

//using var audioConfig2 = AudioConfig.FromWavFileInput($"{recordingUrl}.wav");
using var audioConfig = AudioConfig.FromStreamInput(audioInputStream);
using var recognizer = new SpeechRecognizer(speechConfig, audioConfig);

byte[] readBytes;
do
{
    readBytes = reader.ReadBytes(1024);
    audioInputStream.Write(readBytes, readBytes.Length);
} while (readBytes.Length > 0);

var stopRecognition = new TaskCompletionSource<int>();

var textRecognition = "";

recognizer.Recognized += (s, e) =>
{
    if (e.Result.Reason == ResultReason.RecognizedSpeech)
    {
        textRecognition += e.Result.Text;
    }
};

recognizer.Canceled += (s, e) =>
{
    stopRecognition.TrySetResult(0);
};
recognizer.SessionStopped += (s, e) =>
{
    stopRecognition.TrySetResult(0);
};

// Starts continuous recognition. Uses StopContinuousRecognitionAsync() to stop recognition.
await recognizer.StartContinuousRecognitionAsync().ConfigureAwait(false);

// Waits for completion.
// Use Task.WaitAny to keep the task rooted.
System.Threading.Tasks.Task.WaitAny(new[] { stopRecognition.Task });
// Stops recognition.
await recognizer.StopContinuousRecognitionAsync().ConfigureAwait(false);

核心问题分析

你的代码存在两个关键问题:

  1. 推流与识别的时序错误:先把整个流的数据一次性写入AudioInputStream,再启动识别。Azure Speech的PushStream需要边推流边识别,一次性写完所有数据会导致音频时序解析异常,识别引擎无法正确处理批量推送的静态数据。
  2. 不必要的BinaryReader包装:BinaryReader主要用于读取结构化二进制数据(如带类型的数值),对于纯音频流的读取完全多余,反而可能引入流Position管理、同步/异步冲突等潜在问题。

排查与解决步骤

1. 调整推流逻辑:边读边推+提前启动识别

修改代码顺序,先启动识别,再逐步从HTTP流读取数据并推送到AudioInputStream,模拟真实音频流的时序:

HttpResponseMessage wavresponse = await _httpClient.GetAsync($"{recordingUrl}.wav").ConfigureAwait(false);
using var httpStream = await wavresponse.Content.ReadAsStreamAsync().ConfigureAwait(false);

var speechConfig = SpeechConfig.FromSubscription(_speechOptions.Key, _speechOptions.Region);
speechConfig.SpeechRecognitionLanguage = "de-DE";

using var audioInputStream = AudioInputStream.CreatePushStream();
using var audioConfig = AudioConfig.FromStreamInput(audioInputStream);
using var recognizer = new SpeechRecognizer(speechConfig, audioConfig);

var stopRecognition = new TaskCompletionSource<int>();
var textRecognition = "";

// 绑定识别事件
recognizer.Recognized += (s, e) =>
{
    if (e.Result.Reason == ResultReason.RecognizedSpeech)
    {
        textRecognition += e.Result.Text;
    }
};

recognizer.Canceled += (s, e) => stopRecognition.TrySetResult(0);
recognizer.SessionStopped += (s, e) => stopRecognition.TrySetResult(0);

// 先启动识别任务
await recognizer.StartContinuousRecognitionAsync().ConfigureAwait(false);

// 边读HTTP流边推送数据
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = await httpStream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false)) > 0)
{
    audioInputStream.Write(buffer, bytesRead);
    // 可选:添加微小延迟,适配部分场景下的流时序要求
    // await Task.Delay(10).ConfigureAwait(false);
}

// 推送完成后关闭流,触发识别结束
audioInputStream.Close();

// 等待识别任务完成
await stopRecognition.Task.ConfigureAwait(false);
await recognizer.StopContinuousRecognitionAsync().ConfigureAwait(false);

2. 验证HTTP流的完整性

先将HTTP流保存到本地,对比直接下载的文件是否一致,确认流没有被截断或篡改:

// 临时保存流到本地
using var fileStream = File.Create("temp_verify.wav");
await httpStream.CopyToAsync(fileStream).ConfigureAwait(false);
// 用本地文件方式读取验证识别结果
using var localAudioConfig = AudioConfig.FromWavFileInput("temp_verify.wav");
using var localRecognizer = new SpeechRecognizer(speechConfig, localAudioConfig);
// 执行识别逻辑,确认结果是否正常

如果本地验证文件识别正常,说明流本身没问题,问题完全出在推流时序上。

3. 确认WAV文件格式合规

Azure Speech Service要求WAV文件满足:

  • PCM编码(16位深度)
  • 单声道
  • 采样率建议16kHz(8kHz支持但识别效果差)
    可以用FFmpeg工具检查文件格式:
ffmpeg -i your_recording.wav

虽然本地文件识别正常,但格式边缘情况可能在流推送时放大问题。


内容的提问来源于stack exchange,提问作者Max

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 16:37:08