Как я могу отправить аудио на Nexmo Voice через websocket - PullRequest
0 голосов
/ 27 февраля 2019

Я пытаюсь внедрить 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 без завершения закрытиярукопожатие.

1 Ответ

0 голосов
/ 28 февраля 2019

Похоже, что вы записываете весь аудиоклип в веб-сокет, интерфейс Nexmo требует, чтобы звук был в кадрах 20 мс по одному на сообщение, это означает, что вам нужно разбить клип на 320 или 640 байт (в зависимости отесли вы используете блоки по 8 кГц или 16 кГц) и запишите каждый в сокет.Если вы попытаетесь записать слишком большой файл в сокет, он закроется, как вы видите.

Подробнее см. https://developer.nexmo.com/voice/voice-api/guides/websockets#writing-audio-to-the-websocket.

...