Google 语音转文本 API 的 Twilio Base64 媒体负载无响应

Twilio Base64 Media Payload for Google Speech To Text API not Responding

我需要使用 Google 语音转文本 api 从 twilio phone 调用中进行一些实时转录,我已经关注了一些演示应用程序,展示了如何设置这个。我的应用程序在 .net core 3.1 中,我正在使用带有 Twilio 定义的回调方法的 webhooks。通过回调从 Twilio 检索媒体后,它作为原始音频以 base64 编码传递,如您在此处所见。

https://www.twilio.com/docs/voice/twiml/stream

我也引用了 this demo on Live Transcribing 并试图模仿 c# 中的 case 语句。一切都正确连接,媒体和有效负载从 Twilio 传递到我的应用程序中。

然后将音频字符串转换为byte[]传递给需要转录音频的Task

 byte[] audioBytes = Convert.FromBase64String(info);

我正在关注基于 Google 文档的示例,这些示例要么从文件流式传输,要么从音频输入(例如微型 phone。)我的用例不同的是,我已经有了每个音频块的字节。我引用的例子可以在这里看到。 Transcribing audio from streaming input

下面是我对后者的实现,尽管使用的是原始音频字节。当 Twilio websocket 连接命中媒体事件时,将命中下面的任务。我将有效载荷直接传递给它。从我的控制台日志记录中,我得到了 Print Responses hit... 控制台日志,但它不会进入 while (await responseStream.MoveNextAsync()) 块并将记录记录到控制台。我没有收到任何错误(这会破坏应用程序)。这甚至可能吗?我还尝试将字节加载到 memorystream 对象中,并像 Google 文档示例一样将它们传递进来。

    static async Task<object> StreamingRecognizeAsync(byte[] audioBytes)
    {

        var speech = SpeechClient.Create();
        var streamingCall = speech.StreamingRecognize();
        // Write the initial request with the config.
        await streamingCall.WriteAsync(
            new StreamingRecognizeRequest()
            {
                StreamingConfig = new StreamingRecognitionConfig()
                {
                    Config = new RecognitionConfig()
                    {
                        Encoding =
                        RecognitionConfig.Types.AudioEncoding.Mulaw,
                        SampleRateHertz = 8000,
                        LanguageCode = "en",

                    },
                    InterimResults = true,
                    SingleUtterance = true
                }
            }); ;
        // Print responses as they arrive.
        Task printResponses = Task.Run(async () =>
        {
            Console.WriteLine("Print Responses hit...");
            var responseStream = streamingCall.GetResponseStream();

            while (await responseStream.MoveNextAsync())
            {
                StreamingRecognizeResponse response = responseStream.Current;
                Console.WriteLine("Response stream moveNextAsync Hit...");
                foreach (StreamingRecognitionResult result in response.Results)
                {
                    foreach (SpeechRecognitionAlternative alternative in result.Alternatives)
                    {
                        Console.WriteLine("Google transcript " + alternative.Transcript);
                    }
                }
            }
        });
        //using (MemoryStream memStream = new MemoryStream(audioBytes))
        //{
        //    var buffer = new byte[32 * 1024];
        //    int bytesRead;
        //    while ((bytesRead = await memStream.ReadAsync(audioBytes, 0, audioBytes.Length)) > 0)
        //    {
        //        await streamingCall.WriteAsync(
        //            new StreamingRecognizeRequest()
        //            {
        //                AudioContent = Google.Protobuf.ByteString
        //                .CopyFrom(buffer, 0, bytesRead),
        //            });
        //    }
        //}

        await streamingCall.WriteAsync(
                   new StreamingRecognizeRequest()
                   {
                       AudioContent = Google.Protobuf.ByteString
                       .CopyFrom(audioBytes),
                   });
        await streamingCall.WriteCompleteAsync();
        await printResponses;
        return 0;
    }

经过这一切,我发现这段代码工作正常,只需要分解并在 Twilio 流生命周期的不同事件中调用。 配置部分需要在连接事件期间放置。 打印消息任务需要放在媒体事件中。 然后,当从 Twilio 关闭 websocket 时,需要将 WriteCompleteAsync 置于停止事件中。

另一个需要考虑的重要项目是发送到 Google STT 的请求数量,以确保太多请求不会使配额超载(目前)似乎是 300 个请求/分钟。