Я пытаюсь внедрить API-интерфейс Voice Nexmo с веб-сокетами в веб-API .Net Core 2.
Этот API-интерфейс должен:
- получать звук от телефонного звонка через Nexmo
- использование Microsoft Cognitive речь в текст api
- отправка текста боту
- использование Microsoft Cognitive текст в речь по ответу бота
- отправьте обратно речь nexmo через их голосовой веб-сокет API
На данный момент я обхожу шаги бота, как я сначала пытаюсьподключиться к веб-сокету.При попытке использования метода эха (отправить обратно в веб-сокет полученное аудио), он работает без каких-либо проблем.Но когда я пытаюсь отправить речь из текста Microsoft в речь, телефонный звонок заканчивается.
Я не нахожу никакой документации, реализующей что-то отличное от просто эхо.
Методы TextToSpeech и SpeechToTextработать как положено при использовании вне веб-сокета.
Вот веб-сокет с преобразованием речи в текст:
public static async Task Echo(HttpContext context, WebSocket webSocket)
{
var buffer = new byte[1024 * 4];
WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
while (!result.CloseStatus.HasValue)
{
while(!result.EndOfMessage)
{
result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
}
var text = SpeechToText.RecognizeSpeechFromBytesAsync(buffer).Result;
Console.WriteLine(text);
}
await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
}
А вот веб-сокет с преобразованием текста в речь:
public static async Task Echo(HttpContext context, WebSocket webSocket)
{
var buffer = new byte[1024 * 4];
WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
while (!result.CloseStatus.HasValue)
{
var ttsAudio = await TextToSpeech.TransformTextToSpeechAsync("Hello, this is a test", "en-US");
await webSocket.SendAsync(new ArraySegment<byte>(ttsAudio, 0, ttsAudio.Length), WebSocketMessageType.Binary, true, CancellationToken.None);
result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
}
await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
}
Обновление 1 марта 2019
в ответ на комментарий Сэм Мачин Я попытался разбить массив на куски по 640 байткаждый (я использую частоту дискретизации 16000 кГц), но nexmo все еще зависает, и я все еще ничего не слышу.
public static async Task NexmoTextToSpeech(HttpContext context, WebSocket webSocket)
{
var ttsAudio = await TextToSpeech.TransformTextToSpeechAsync("This is a test", "en-US");
var buffer = new byte[1024 * 4];
WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
while (!result.CloseStatus.HasValue)
{
await SendSpeech(context, webSocket, ttsAudio);
result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
}
await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing Socket", CancellationToken.None);
}
private static async Task SendSpeech(HttpContext context, WebSocket webSocket, byte[] ttsAudio)
{
const int chunkSize = 640;
var chunkCount = 1;
var offset = 0;
var lastFullChunck = ttsAudio.Length < (offset + chunkSize);
try
{
while(!lastFullChunck)
{
await webSocket.SendAsync(new ArraySegment<byte>(ttsAudio, offset, chunkSize), WebSocketMessageType.Binary, false, CancellationToken.None);
offset = chunkSize * chunkCount;
lastFullChunck = ttsAudio.Length < (offset + chunkSize);
chunkCount++;
}
var lastMessageSize = ttsAudio.Length - offset;
await webSocket.SendAsync(new ArraySegment<byte>(ttsAudio, offset, lastMessageSize), WebSocketMessageType.Binary, true, CancellationToken.None);
}
catch (Exception ex)
{
}
}
Вот исключение, которое иногда появляется в журналах:
System.Net.WebSockets.WebSocketException (0x80004005): удаленная сторона закрыла соединение WebSocket без завершения закрытиярукопожатие.