Google 语音 API 来自 websocket 的流式音频
Google Speech API streaming audio from websocket
我正在尝试从 Fleck websocket 音频流中获取最终演讲 transcription/recognition 结果。 OnOpen
方法在首次建立 websocket 连接时执行代码,而 OnBinary
方法在从客户端接收到二进制数据时执行代码。我通过将语音回显到 websocket 并以相同的速率将相同的二进制数据写回 websocket 来测试 websocket。这个测试有效,所以我知道二进制数据被正确发送(640 字节消息,帧大小为 20 毫秒)。
因此,我的代码失败了,而不是服务。我的目标是执行以下操作:
- 创建 websocket 连接后,使用
SingleUtterance == true
将初始音频配置请求发送到 API
- 运行一个监听流结果等待
isFinal == true
的后台任务
- 将收到的每个二进制消息发送到 API 进行转录
- 当后台任务识别出
isFinal == true
时,停止当前流式传输请求并创建新请求 - 重复步骤 1 到 4
此项目的背景是转录实时 phone 通话中的所有单个话语。
socket.OnOpen = () =>
{
firstMessage = true;
};
socket.OnBinary = async binary =>
{
var speech = SpeechClient.Create();
var streamingCall = speech.StreamingRecognize();
if (firstMessage == true)
{
await streamingCall.WriteAsync(
new StreamingRecognizeRequest()
{
StreamingConfig = new StreamingRecognitionConfig()
{
Config = new RecognitionConfig()
{
Encoding = RecognitionConfig.Types.AudioEncoding.Linear16,
SampleRateHertz = 16000,
LanguageCode = "en",
},
SingleUtterance = true,
}
});
Task getUtterance = Task.Run(async () =>
{
while (await streamingCall.ResponseStream.MoveNext(
default(CancellationToken)))
{
foreach (var result in streamingCall.ResponseStream.Current.Results)
{
if (result.IsFinal == true)
{
Console.WriteLine("This test finally worked");
}
}
}
});
firstMessage = false;
}
else if (firstMessage == false)
{
streamingCall.WriteAsync(new StreamingRecognizeRequest()
{
AudioContent = Google.Protobuf.ByteString.CopyFrom(binary, 0, 640)
}).Wait();
}
};
.Wait()
是在 async/await 中调用的阻塞调用。它们不能很好地混合,并可能导致死锁。
一直保持代码异步
//...omitted for brevity
else if (firstMessage == false) {
await streamingCall.WriteAsync(new StreamingRecognizeRequest() {
AudioContent = Google.Protobuf.ByteString.CopyFrom(binary, 0, 640)
});
}
我正在尝试从 Fleck websocket 音频流中获取最终演讲 transcription/recognition 结果。 OnOpen
方法在首次建立 websocket 连接时执行代码,而 OnBinary
方法在从客户端接收到二进制数据时执行代码。我通过将语音回显到 websocket 并以相同的速率将相同的二进制数据写回 websocket 来测试 websocket。这个测试有效,所以我知道二进制数据被正确发送(640 字节消息,帧大小为 20 毫秒)。
因此,我的代码失败了,而不是服务。我的目标是执行以下操作:
- 创建 websocket 连接后,使用
SingleUtterance == true
将初始音频配置请求发送到 API
- 运行一个监听流结果等待
isFinal == true
的后台任务
- 将收到的每个二进制消息发送到 API 进行转录
- 当后台任务识别出
isFinal == true
时,停止当前流式传输请求并创建新请求 - 重复步骤 1 到 4
此项目的背景是转录实时 phone 通话中的所有单个话语。
socket.OnOpen = () =>
{
firstMessage = true;
};
socket.OnBinary = async binary =>
{
var speech = SpeechClient.Create();
var streamingCall = speech.StreamingRecognize();
if (firstMessage == true)
{
await streamingCall.WriteAsync(
new StreamingRecognizeRequest()
{
StreamingConfig = new StreamingRecognitionConfig()
{
Config = new RecognitionConfig()
{
Encoding = RecognitionConfig.Types.AudioEncoding.Linear16,
SampleRateHertz = 16000,
LanguageCode = "en",
},
SingleUtterance = true,
}
});
Task getUtterance = Task.Run(async () =>
{
while (await streamingCall.ResponseStream.MoveNext(
default(CancellationToken)))
{
foreach (var result in streamingCall.ResponseStream.Current.Results)
{
if (result.IsFinal == true)
{
Console.WriteLine("This test finally worked");
}
}
}
});
firstMessage = false;
}
else if (firstMessage == false)
{
streamingCall.WriteAsync(new StreamingRecognizeRequest()
{
AudioContent = Google.Protobuf.ByteString.CopyFrom(binary, 0, 640)
}).Wait();
}
};
.Wait()
是在 async/await 中调用的阻塞调用。它们不能很好地混合,并可能导致死锁。
一直保持代码异步
//...omitted for brevity
else if (firstMessage == false) {
await streamingCall.WriteAsync(new StreamingRecognizeRequest() {
AudioContent = Google.Protobuf.ByteString.CopyFrom(binary, 0, 640)
});
}