Поделиться через


Краткое руководство. Потоковая передача аудио на стороне сервера

Внимание

Функции, описанные в этой статье, в настоящее время находятся в общедоступной предварительной версии. Эта предварительная версия предоставляется без соглашения об уровне обслуживания. Ее не следует использовать для производственных рабочих нагрузок. Некоторые функции могут не поддерживаться или их возможности могут быть ограничены. Дополнительные сведения см. в статье Дополнительные условия использования Предварительных версий Microsoft Azure.

Начало работы с использованием аудиопотоков с помощью API потоковой передачи звука Службы коммуникации Azure. В этом кратком руководстве предполагается, что вы уже знакомы с API автоматизации вызовов для создания решения автоматической маршрутизации вызовов.

Функции, описанные в этом кратком руководстве, в настоящее время находятся в общедоступной предварительной версии.

Необходимые компоненты

  • Учетная запись Azure с активной подпиской см. в статье "Создание учетной записи бесплатно".
  • Ресурс Служб коммуникации Azure. См. статью "Создание ресурса Службы коммуникации Azure".
  • Новое приложение веб-службы, созданное с помощью пакета SDK службы автоматизации вызовов.
  • Последняя библиотека .NET для операционной системы.
  • Сервер websocket, который может получать потоки мультимедиа.

Настройка сервера websocket

Службы коммуникации Azure требует, чтобы серверное приложение настроит сервер WebSocket для потоковой передачи звука в режиме реального времени. WebSocket — это стандартизованный протокол, предоставляющий полно дуплексный канал связи по одному TCP-подключению. При необходимости можно использовать службы Azure WebApps, позволяющие создать приложение для получения аудиопотоков через подключение websocket. Следуйте инструкциям из этого краткого руководства.

Установка вызова

Установка вызова и предоставление сведений о потоковой передаче

MediaStreamingOptions mediaStreamingOptions = new MediaStreamingOptions( 
    new Uri("<WEBSOCKET URL>"), 
    MediaStreamingContent.Audio, 
    MediaStreamingAudioChannel.Mixed, 
    MediaStreamingTransport.Websocket, 
    false); 

 var createCallOptions = new CreateCallOptions(callInvite, callbackUri) 
 { 
     CallIntelligenceOptions = new CallIntelligenceOptions() { CognitiveServicesEndpoint = new Uri(cognitiveServiceEndpoint) }, 
     MediaStreamingOptions = mediaStreamingOptions, 
 }; 

 CreateCallResult createCallResult = await callAutomationClient.CreateCallAsync(createCallOptions); 

Запуск потоковой передачи звука

Как начать потоковую передачу звука:

StartMediaStreamingOptions options = new StartMediaStreamingOptions() 
    { 
        OperationCallbackUri = new Uri(callbackUriHost), 
        OperationContext = "startMediaStreamingContext" 
    };
    await callMedia.StartMediaStreamingAsync(options); 

Когда Службы коммуникации Azure получает URL-адрес сервера WebSocket, он создает подключение к нему. После успешного подключения Службы коммуникации Azure к серверу WebSocket и потоковой передаче он будет отправляться через первый пакет данных, содержащий метаданные о входящих пакетах мультимедиа.

Пакет метаданных будет выглядеть следующим образом:

{ 
    "kind": <string> // What kind of data this is, e.g. AudioMetadata, AudioData. 
    "audioMetadata": { 
        "subscriptionId": <string>, // unique identifier for a subscription request 
        "encoding":<string>, // PCM only supported 
        "sampleRate": <int>, // 16000 default 
        "channels": <int>, // 1 default 
        "length": <int> // 640 default 
    } 
} 

Остановка потоковой передачи звука

Как остановить потоковую передачу звука

StopMediaStreamingOptions stopOptions = new StopMediaStreamingOptions() 
    { 
        OperationCallbackUri = new Uri(callbackUriHost) 
    }; 
    await callMedia.StopMediaStreamingAsync(stopOptions); 

Обработка аудиопотоков на сервере Websocket

В приведенном ниже примере показано, как прослушивать аудиопотоки с помощью сервера websocket.

HttpListener httpListener = new HttpListener(); 
httpListener.Prefixes.Add("http://localhost:80/"); 
httpListener.Start(); 

while (true) 
{ 
    HttpListenerContext httpListenerContext = await httpListener.GetContextAsync(); 
    if (httpListenerContext.Request.IsWebSocketRequest) 
    { 
        WebSocketContext websocketContext; 
        try 
        { 
            websocketContext = await httpListenerContext.AcceptWebSocketAsync(subProtocol: null); 
        } 
        catch (Exception ex) 
        { 
            return; 
        } 
        WebSocket webSocket = websocketContext.WebSocket; 
        try 
        { 
            while (webSocket.State == WebSocketState.Open || webSocket.State == WebSocketState.CloseSent) 
            { 
                byte[] receiveBuffer = new byte[2048]; 
                var cancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(60)).Token; 
                WebSocketReceiveResult receiveResult = await webSocket.ReceiveAsync(new ArraySegment<byte>(receiveBuffer), cancellationToken); 
                if (receiveResult.MessageType != WebSocketMessageType.Close) 
                { 
                    var data = Encoding.UTF8.GetString(receiveBuffer).TrimEnd('\0'); 
                    try 
                    { 
                        var eventData = JsonConvert.DeserializeObject<AudioBaseClass>(data); 
                        if (eventData != null) 
                        { 
                            if(eventData.kind == "AudioMetadata") 
                            { 
                                //Process audio metadata 
                            } 
                            else if(eventData.kind == "AudioData")  
                            { 
                                //Process audio data 
                                var byteArray = eventData.audioData.data; 
                               //use audio byteArray as you want 
                            } 
                        } 
                    } 
                    catch { } 
                } 
            } 
        } 
        catch (Exception ex) { } 
    } 
} 

Необходимые компоненты

Настройка сервера websocket

Службы коммуникации Azure требует, чтобы серверное приложение настроит сервер WebSocket для потоковой передачи звука в режиме реального времени. WebSocket — это стандартизованный протокол, предоставляющий полно дуплексный канал связи по одному TCP-подключению. При необходимости можно использовать службы Azure WebApps, позволяющие создать приложение для получения аудиопотоков через подключение websocket. Следуйте инструкциям из этого краткого руководства.

Установка вызова

Установка вызова и предоставление сведений о потоковой передаче

CallInvite callInvite = new CallInvite(target, caller);  
              
            CallIntelligenceOptions callIntelligenceOptions = new CallIntelligenceOptions().setCognitiveServicesEndpoint(appConfig.getCognitiveServiceEndpoint());  
            MediaStreamingOptions mediaStreamingOptions = new MediaStreamingOptions(appConfig.getWebSocketUrl(), MediaStreamingTransport.WEBSOCKET, MediaStreamingContentType.AUDIO, MediaStreamingAudioChannel.UNMIXED);  
            mediaStreamingOptions.setStartMediaStreaming(false);  
          
            CreateCallOptions createCallOptions = new CreateCallOptions(callInvite, appConfig.getCallBackUri());  
            createCallOptions.setCallIntelligenceOptions(callIntelligenceOptions);  
            createCallOptions.setMediaStreamingOptions(mediaStreamingOptions);  
  
            Response<CreateCallResult> result = client.createCallWithResponse(createCallOptions, Context.NONE);  
            return result.getValue().getCallConnectionProperties().getCallConnectionId();  

Запуск потоковой передачи звука

Как начать потоковую передачу звука:

StartMediaStreamingOptions startOptions = new StartMediaStreamingOptions()  
                                                        .setOperationContext("startMediaStreamingContext")  
                                                        .setOperationCallbackUrl(appConfig.getBasecallbackuri());  
         client.getCallConnection(callConnectionId)  
                     .getCallMedia()  
                     .startMediaStreamingWithResponse(startOptions, Context.NONE);      

Когда Службы коммуникации Azure получает URL-адрес сервера WebSocket, он создает подключение к нему. После успешного подключения Службы коммуникации Azure к серверу WebSocket и потоковой передаче он будет отправляться через первый пакет данных, содержащий метаданные о входящих пакетах мультимедиа.

Пакет метаданных будет выглядеть следующим образом:

{ 
    "kind": <string> // What kind of data this is, e.g. AudioMetadata, AudioData. 
    "audioMetadata": { 
        "subscriptionId": <string>, // unique identifier for a subscription request 
        "encoding":<string>, // PCM only supported 
        "sampleRate": <int>, // 16000 default 
        "channels": <int>, // 1 default 
        "length": <int> // 640 default 
    } 
} 

Остановка потоковой передачи звука

Как остановить потоковую передачу звука

StopMediaStreamingOptions stopOptions = new StopMediaStreamingOptions()  
                                                        .setOperationCallbackUrl(appConfig.getBasecallbackuri());  
         client.getCallConnection(callConnectionId)  
                     .getCallMedia()  
                     .stopMediaStreamingWithResponse(stopOptions, Context.NONE);

Обработка потоков мультимедиа на сервере websocket

В приведенном ниже примере показано, как прослушивать поток мультимедиа с помощью сервера websocket. Необходимо выполнить два файла: App.java и WebSocketServer.java

package com.example;

import org.glassfish.tyrus.server.Server;

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class App {
    public static void main(String[] args) {

        Server server = new Server("localhost", 8081, "/ws", null, WebSocketServer.class);

        try {
            server.start();
            System.out.println("Web socket running on port 8081...");
            System.out.println("wss://localhost:8081/ws/server");
            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
            reader.readLine();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            server.stop();
        }
    }
}
package com.example;

import javax.websocket.OnMessage;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

import com.azure.communication.callautomation.models.streaming.StreamingData;
import com.azure.communication.callautomation.models.streaming.StreamingDataParser;
import com.azure.communication.callautomation.models.streaming.media.AudioData;
import com.azure.communication.callautomation.models.streaming.media.AudioMetadata;

@ServerEndpoint("/server")
public class WebSocketServer {
    @OnMessage
    public void onMessage(String message, Session session) {

        // System.out.println("Received message: " + message);

        StreamingData data = StreamingDataParser.parse(message);

        if (data instanceof AudioMetadata) {
            AudioMetadata audioMetaData = (AudioMetadata) data;
            System.out.println("----------------------------------------------------------------");
            System.out.println("SUBSCRIPTION ID:-->" + audioMetaData.getMediaSubscriptionId());
            System.out.println("ENCODING:-->" + audioMetaData.getEncoding());
            System.out.println("SAMPLE RATE:-->" + audioMetaData.getSampleRate());
            System.out.println("CHANNELS:-->" + audioMetaData.getChannels());
            System.out.println("LENGTH:-->" + audioMetaData.getLength());
            System.out.println("----------------------------------------------------------------");
        }
        if (data instanceof AudioData) {
            System.out.println("----------------------------------------------------------------");
            AudioData audioData = (AudioData) data;
            System.out.println("DATA:-->" + audioData.getData());
            System.out.println("TIMESTAMP:-->" + audioData.getTimestamp());
            // System.out.println("PARTICIPANT:-->" + audioData.getParticipant().getRawId()
            // != null
            // ? audioData.getParticipant().getRawId()
            // : "");
            System.out.println("IS SILENT:-->" + audioData.isSilent());
            System.out.println("----------------------------------------------------------------");
        }
    }
}

Необходимые компоненты

  • Учетная запись Azure с активной подпиской см. в статье "Создание учетной записи бесплатно".
  • Ресурс Служб коммуникации Azure. См. статью "Создание ресурса Службы коммуникации Azure".
  • Новое приложение веб-службы, созданное с помощью пакета SDK службы автоматизации вызовов.
  • установка Node.js LTS
  • Сервер websocket, который может получать потоки мультимедиа.

Настройка сервера websocket

Службы коммуникации Azure требует, чтобы серверное приложение настроит сервер WebSocket для потоковой передачи звука в режиме реального времени. WebSocket — это стандартизованный протокол, предоставляющий полно дуплексный канал связи по одному TCP-подключению. При необходимости можно использовать службы Azure WebApps, позволяющие создать приложение для получения аудиопотоков через подключение websocket. Следуйте инструкциям из этого краткого руководства.

Установка вызова

Установка вызова и предоставление сведений о потоковой передаче

const mediaStreamingOptions: MediaStreamingOptions = { 
          transportUrl: "<WEBSOCKET URL>", 
          transportType: "websocket", 
          contentType: "audio", 
          audioChannelType: "unmixed", 
          startMediaStreaming: false 
} 
const options: CreateCallOptions = { 
          callIntelligenceOptions: { cognitiveServicesEndpoint: process.env.COGNITIVE_SERVICES_ENDPOINT }, 
          mediaStreamingOptions: mediaStreamingOptions 
}; 

Запуск потоковой передачи звука

Как начать потоковую передачу звука:

const streamingOptions: StartMediaStreamingOptions = { 
        operationContext: "startMediaStreamingContext", 
        operationCallbackUrl: process.env.CALLBACK_URI + "/api/callbacks" 
    } 
await callMedia.startMediaStreaming(streamingOptions); 

Когда Службы коммуникации Azure получает URL-адрес сервера WebSocket, он создает подключение к нему. После успешного подключения Службы коммуникации Azure к серверу WebSocket и потоковой передаче он будет отправляться через первый пакет данных, содержащий метаданные о входящих пакетах мультимедиа.

Пакет метаданных будет выглядеть следующим образом:

{ 
    "kind": <string> // What kind of data this is, e.g. AudioMetadata, AudioData. 
    "audioMetadata": { 
        "subscriptionId": <string>, // unique identifier for a subscription request 
        "encoding":<string>, // PCM only supported 
        "sampleRate": <int>, // 16000 default 
        "channels": <int>, // 1 default 
        "length": <int> // 640 default 
    } 
} 

Остановка потоковой передачи звука

Как остановить потоковую передачу звука

const stopMediaStreamingOptions: StopMediaStreamingOptions = { 
        operationCallbackUrl: process.env.CALLBACK_URI + "/api/callbacks" 
        } 
await callMedia.stopMediaStreaming(stopMediaStreamingOptions); 

Обработка аудиопотоков на сервере Websocket

В приведенном ниже примере показано, как прослушивать аудиопотоки с помощью сервера websocket.

import WebSocket from 'ws'; 
import { streamingData } from '@azure/communication-call-automation/src/utli/streamingDataParser' 
const wss = new WebSocket.Server({ port: 8081 }); 

wss.on('connection', (ws: WebSocket) => { 
    console.log('Client connected'); 
    ws.on('message', (packetData: ArrayBuffer) => { 
        const decoder = new TextDecoder(); 
        const stringJson = decoder.decode(packetData); 
        console.log("STRING JSON=>--" + stringJson) 

        //var response = streamingData(stringJson); 

        var response = streamingData(packetData); 
        if ('locale' in response) { 
            console.log("Transcription Metadata") 
            console.log(response.callConnectionId); 
            console.log(response.correlationId); 
            console.log(response.locale); 
            console.log(response.subscriptionId); 
        } 
        if ('text' in response) { 
            console.log("Transcription Data") 
            console.log(response.text); 
            console.log(response.format); 
            console.log(response.confidence); 
            console.log(response.offset); 
            console.log(response.duration); 
            console.log(response.resultStatus); 
            if ('phoneNumber' in response.participant) { 
                console.log(response.participant.phoneNumber); 
            } 
            response.words.forEach(element => { 
                console.log(element.text) 
                console.log(element.duration) 
                console.log(element.offset) 
            }); 
        } 
    }); 

    ws.on('close', () => { 
        console.log('Client disconnected'); 
    }); 
}); 

// function processData(data: ArrayBuffer) { 
//  const byteArray = new Uint8Array(data); 
// } 

console.log('WebSocket server running on port 8081'); 

Необходимые компоненты

Настройка сервера websocket

Службы коммуникации Azure требует, чтобы серверное приложение настроит сервер WebSocket для потоковой передачи звука в режиме реального времени. WebSocket — это стандартизованный протокол, предоставляющий полно дуплексный канал связи по одному TCP-подключению. При необходимости можно использовать службы Azure WebApps, позволяющие создать приложение для получения аудиопотоков через подключение websocket. Следуйте инструкциям из этого краткого руководства.

Установка вызова

Установка вызова и предоставление сведений о потоковой передаче

media_streaming_options = MediaStreamingOptions( 
         transport_url="wss://e063-2409-40c2-4004-eced-9487-4dfb-b0e4-10fb.ngrok-free.app", 
         transport_type=MediaStreamingTransportType.WEBSOCKET, 
         content_type=MediaStreamingContentType.AUDIO, 
         audio_channel_type=MediaStreamingAudioChannelType.UNMIXED, 
         start_media_streaming=False 
         ) 

call_connection_properties = call_automation_client.create_call(target_participant,  
                                                                    CALLBACK_EVENTS_URI, 
                                                                    cognitive_services_endpoint=COGNITIVE_SERVICES_ENDPOINT, 
                                                                    source_caller_id_number=source_caller, 
                                                                    media_streaming=media_streaming_options
) 

Запуск потоковой передачи звука

Как начать потоковую передачу звука:

call_connection_client.start_media_streaming() 

Когда Службы коммуникации Azure получает URL-адрес сервера WebSocket, он создает подключение к нему. После успешного подключения Службы коммуникации Azure к серверу WebSocket и потоковой передаче он будет отправляться через первый пакет данных, содержащий метаданные о входящих пакетах мультимедиа.

Пакет метаданных будет выглядеть следующим образом:

{ 
    "kind": <string> // What kind of data this is, e.g. AudioMetadata, AudioData. 
    "audioMetadata": { 
        "subscriptionId": <string>, // unique identifier for a subscription request 
        "encoding":<string>, // PCM only supported 
        "sampleRate": <int>, // 16000 default 
        "channels": <int>, // 1 default 
        "length": <int> // 640 default 
    } 
} 

Остановка потоковой передачи звука

Как остановить потоковую передачу звука

call_connection_client.stop_media_streaming() 

Обработка аудиопотоков на сервере Websocket

В приведенном ниже примере показано, как прослушивать аудиопотоки с помощью сервера websocket.

import asyncio 
import json 
import websockets 

async def handle_client(websocket, path): 
    print("Client connected") 
    try: 
        async for message in websocket: 
            print(message) 
            packet_data = json.loads(message) 
            packet_data = message.encode('utf-8') 
            print("Packet DATA:-->",packet_data) 

    except websockets.exceptions.ConnectionClosedOK: 
        print("Client disconnected") 

start_server = websockets.serve(handle_client, "localhost", 8081) 

print('WebSocket server running on port 8081') 

asyncio.get_event_loop().run_until_complete(start_server) 
asyncio.get_event_loop().run_forever() 

Схема потоковой передачи звука

После отправки через пакет метаданных Службы коммуникации Azure начнет потоковую передачу звуковых носителей на сервер WebSocket. Ниже приведен пример того, как будет выглядеть объект мультимедиа, который будет получать сервер.

{
    "kind": <string>, // What kind of data this is, e.g. AudioMetadata, AudioData.
    "audioData":{
        "data": <string>, // Base64 Encoded audio buffer data
        "timestamp": <string>, // In ISO 8601 format (yyyy-mm-ddThh:mm:ssZ) 
        "participantRawID": <string>, 
        "silent": <boolean> // Indicates if the received audio buffer contains only silence.
    }
}

Очистка ресурсов

Если вы хотите отменить и удалить подписку на Службы коммуникации, можно удалить ресурс или группу ресурсов. При удалении группы ресурсов также удаляются все связанные с ней ресурсы. См. сведения об очистке ресурсов.

Следующие шаги