0

我需要使用 Google 语音到文本 api 从 twilio 电话中进行一些实时转录,并且我遵循了一些演示应用程序来展示如何设置它。我的应用程序位于 .net core 3.1 中,并且我正在使用带有 Twilio 定义的回调方法的 webhook。通过回调从 Twilio 检索媒体后,它作为原始音频以 base64 编码传递,如您在此处看到的。

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

在 Live Transcribe 上引用了这个演示并试图模仿 c# 中的 case 语句。一切都正确连接,媒体和有效负载从 Twilio 很好地传递到我的应用程序中。

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

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

我正在关注基于 Google 文档的示例,这些文档要么从文件流式传输,要么从音频输入(例如麦克风)流式传输。我的用例不同的是,我已经拥有每个音频块的字节。我引用的例子可以在这里看到。从流输入转录音频

下面是我对后者的实现,尽管使用了原始音频字节。当 Twilio websocket 连接命中媒体事件时,会命中下面的此任务。我将有效载荷直接传递给它。从我的控制台日志中,我得到了 Print Responses hit... 控制台日志,但它不会进入while (await responseStream.MoveNextAsync())块并将脚本记录到控制台。我没有收到任何错误(这会破坏应用程序。)这有可能吗?我还尝试将字节加载到内存流对象中,并将它们传递给 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;
    }
4

1 回答 1

0

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

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

于 2020-04-24T21:57:35.510 回答