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 个请求/分钟。
我需要使用 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 个请求/分钟。