Google 语音 API 来自 websocket 的流式音频

Google Speech API streaming audio from websocket

我正在尝试从 Fleck websocket 音频流中获取最终演讲 transcription/recognition 结果。 OnOpen 方法在首次建立 websocket 连接时执行代码,而 OnBinary 方法在从客户端接收到二进制数据时执行代码。我通过将语音回显到 websocket 并以相同的速率将相同的二进制数据写回 websocket 来测试 websocket。这个测试有效,所以我知道二进制数据被正确发送(640 字节消息,帧大小为 20 毫秒)。

因此,我的代码失败了,而不是服务。我的目标是执行以下操作:

  1. 创建 websocket 连接后,使用 SingleUtterance == true
  2. 将初始音频配置请求发送到 API
  3. 运行一个监听流结果等待isFinal == true
  4. 的后台任务
  5. 将收到的每个二进制消息发送到 API 进行转录
  6. 当后台任务识别出 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)
    });
}