你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
快速入门:服务器端音频流式处理
重要
本文中所述的功能目前以公共预览版提供。 此预览版在提供时没有附带服务级别协议,我们不建议将其用于生产工作负荷。 某些功能可能不受支持或者受限。 有关详细信息,请参阅 Microsoft Azure 预览版补充使用条款。
通过 Azure 通信服务音频流式处理 API 开始使用音频流。 此快速入门假设你已经熟悉通话自动化 API,以构建自动呼叫路由解决方案。
本快速入门中所述的功能目前处于公共预览状态。
先决条件
- 包含活动订阅的 Azure 帐户,有关详细信息,请参阅免费创建帐户。
- 一个 Azure 通信服务资源。 请参阅创建 Azure 通信服务资源。
- 使用通话自动化 SDK 创建的新的 Web 服务应用程序。
- 适用于操作系统的最新 .NET 库。
- 可以接收媒体流的 WebSocket 服务器。
设置 WebSocket 服务器
Azure 通信服务要求你的服务器应用程序设置 WebSocket 服务器,从而实时流式传输音频。 WebSocket 是一种标准化协议,可通过单个 TCP 连接提供全双工通信通道。 你可以选择使用 Azure 服务 Azure Web Apps,它允许你创建一个应用程序来通过 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 通信服务收到 WebSocket 服务器的 URL 后,它将创建与该服务器的连接。 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) { }
}
}
先决条件
- 具有有效订阅的 Azure 帐户,有关详细信息,请参阅免费创建帐户。
- 一个 Azure 通信服务资源。 请参阅创建 Azure 通信服务资源。
- 使用通话自动化 SDK 创建的新的 Web 服务应用程序。
- Java 开发工具包版本 8 或更高版本。
- Apache Maven。
设置 WebSocket 服务器
Azure 通信服务要求你的服务器应用程序设置 WebSocket 服务器,从而实时流式传输音频。 WebSocket 是一种标准化协议,可通过单个 TCP 连接提供全双工通信通道。 你可以选择使用 Azure 服务 Azure Web Apps,它允许你创建一个应用程序来通过 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 通信服务收到 WebSocket 服务器的 URL 后,它将创建与该服务器的连接。 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 创建的新的 Web 服务应用程序。
- Node.js LTS 安装
- 可以接收媒体流的 WebSocket 服务器。
设置 WebSocket 服务器
Azure 通信服务要求你的服务器应用程序设置 WebSocket 服务器,从而实时流式传输音频。 WebSocket 是一种标准化协议,可通过单个 TCP 连接提供全双工通信通道。 你可以选择使用 Azure 服务 Azure Web Apps,它允许你创建一个应用程序来通过 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 通信服务收到 WebSocket 服务器的 URL 后,它将创建与该服务器的连接。 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');
先决条件
- 具有有效订阅的 Azure 帐户,有关详细信息,请参阅免费创建帐户。
- 一个 Azure 通信服务资源。 请参阅创建 Azure 通信服务资源。
- 使用通话自动化 SDK 创建的新的 Web 服务应用程序。
- Python 3.7+。
- 可以接收媒体流的 WebSocket 服务器。
设置 WebSocket 服务器
Azure 通信服务要求你的服务器应用程序设置 WebSocket 服务器,从而实时流式传输音频。 WebSocket 是一种标准化协议,可通过单个 TCP 连接提供全双工通信通道。 你可以选择使用 Azure 服务 Azure Web Apps,它允许你创建一个应用程序来通过 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 通信服务收到 WebSocket 服务器的 URL 后,它将创建与该服务器的连接。 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.
}
}
清理资源
如果想要清理并删除通信服务订阅,可以删除资源或资源组。 删除资源组同时也会删除与之相关联的任何其他资源。 了解有关清理资源的详细信息。