你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
从 Twilio Video 迁移到 Azure 通信服务
本文介绍如何将现有的 Twilio Video 实现迁移到 Azure 通信服务呼叫 SDK。 Twilio Video 和 Azure 通信服务呼叫 SDK 都是基于云的平台,可让开发人员将语音和视频通话功能添加到其 Web 应用程序。
但它们之间存在一些主要差异,可能会影响你对平台的选择,或者如果你决定迁移,则需要对现有代码进行一些更改。 在本文中,我们将比较这两个平台的主要特性和功能,并提供有关如何将现有 Twilio Video 实现迁移到 Azure 通信服务呼叫 SDK 的一些指导。
Azure 通信服务呼叫 SDK 中提供的主要功能
功能 | Web (JavaScript) | iOS | Android | 平台中立 |
---|---|---|---|---|
安装 | ✔️ | ✔️ | ✔️ | |
导入 | ✔️ | ✔️ | ✔️ | |
身份验证 | ✔️ | |||
Join | ✔️ | ✔️ | ✔️ | |
启动音频/扬声器 | ✔️ | ✔️ | ✔️ | |
静音 | ✔️ | ✔️ | ✔️ | |
取消静音 | ✔️ | ✔️ | ✔️ | |
启动视频 | ✔️ | ✔️ | ✔️ | |
停止视频 | ✔️ | ✔️ | ✔️ | |
虚拟背景 | ✔️ | ✔️ | ✔️ | |
呈现用户视频 | ✔️ | ✔️ | ✔️ | |
录制 | ✔️ | |||
网络带宽管理 | ✔️ | ✔️ | ✔️ | |
服务质量 | ✔️ | |||
数据中心选择 | ✔️ | |||
预览 | ✔️ | ✔️ | ✔️ | |
安全性 | ✔️ | |||
联网 | ✔️ | |||
屏幕共享 | ✔️ | |||
Rest API | ✔️ | |||
Webhook | ✔️ | |||
原始数据 | ✔️ | ✔️ | ✔️ | |
编解码器 | ✔️ | |||
WebView | ✔️ | ✔️ | ||
视频设备 | ✔️ | ✔️ | ✔️ | |
扬声器设备 | ✔️ | ✔️ | ✔️ | |
麦克风设备 | ✔️ | ✔️ | ✔️ | |
数据通道 API | ✔️ | ✔️ | ✔️ | |
分析/视频见解 | ✔️ | |||
诊断工具 | ✔️ | |||
报表 | ✔️ | |||
CallKit(仅限 iOS) | ✔️ | |||
画中画 | ✔️ | ✔️ |
先决条件
- Azure 帐户: 确保 Azure 帐户处于活动状态。 新用户可以在 Microsoft Azure 创建免费帐户。
- Node.js 18:确保系统上安装了 Node.js 18。 从 Node.js 下载。
- 通信服务资源:通过 Azure 门户设置通信服务资源并记下连接字符串。
- Azure CLI:按照说明在 Windows.上安装 Azure CLI。
- 用户访问令牌:生成用户访问令牌以实例化呼叫客户端。 可以使用 Azure CLI 创建一个,如下所示:
az communication identity token issue --scope voip --connection-string "yourConnectionString"
有关详细信息,请参阅使用 Azure CLI 创建和管理访问令牌。
对于 Teams 用户的视频通话:
- 还可以使用 Teams 标识。 若要为 Teams 用户生成访问令牌,请参阅管理团队标识。
- 使用 Graph Explorer,为呼叫操作获取 Teams 线程 ID。 有关创建线程 ID 的信息,请参阅创建聊天 - Microsoft Graph v1.0> 示例 2:创建群聊。
UI 库
Azure 通信服务 UI 库简化了使用 Azure 通信服务创建现代通信用户界面的过程。 它提供一系列现成的 UI 组件,可轻松集成到应用程序中。
此开源预建控件集可让你使用 Fluent UI SDK 组件创建美观的设计,并开发高质量的音频/视频通信体验。 有关详细信息,请查看 Azure 通信服务 UI 库概述。 概述包括有关 Web 和移动平台的全面信息。
安装
安装 Azure 通信服务呼叫 SDK
使用 npm install
命令安装适用于 JavaScript 的 Azure 通信服务通话 SDK。
npm install @azure/communication-common npm install @azure/communication-calling
从项目中删除 Twilio SDK
可以通过卸载包从项目中删除 Twilio SDK。
npm uninstall twilio-video
对象模型
以下类和接口用于处理 Azure 通信服务通话 SDK 的某些主要功能:
Name | 描述 |
---|---|
CallClient | 通话 SDK 的主入口点。 |
AzureCommunicationTokenCredential | 实现用于实例化 CallAgent 的 CommunicationTokenCredential 接口。 |
CallAgent | 启动和管理呼叫。 |
设备管理器 | 管理媒体设备。 |
调用 | 表示呼叫。 |
LocalVideoStream | 为本地系统上的相机设备创建本地视频流。 |
RemoteParticipant | 表示通话中的远程参与者。 |
RemoteVideoStream | 表示来自远程参与者的远程视频流。 |
LocalAudioStream | 表示本地麦克风设备的本地音频流。 |
AudioOptions | 发出传出呼叫或加入组呼叫时提供给参与者的音频选项。 |
AudioIssue | 表示呼叫调查音频问题的结束。 示例响应可能是 NoLocalAudio -其他参与者无法听到我,或 LowVolume - 呼叫音频音量太低。 |
在 Teams 通话中使用 ACS 呼叫时,存在一些差异:
- 不使用
CallAgent
- 而使用TeamsCallAgent
启动和管理 Teams 呼叫。 - 不使用
Call
- 而使用TeamsCall
来表示 Teams 通话。
初始化呼叫 SDK (CallClient/CallAgent)
使用 CallClient
初始化 CallAgent
实例。 createCallAgent
方法使用 CommunicationTokenCredential 作为参数。 它接受用户访问令牌。
设备管理器
Twilio
Twilio 没有设备管理器模拟。 轨道是使用系统的默认设备创建的。 若要自定义设备,请通过以下方式获取所需的源轨道:
navigator.mediaDevices.getUserMedia()
并将其传递给轨道创建方法。
Azure 通信服务
const { CallClient } = require('@azure/communication-calling');
const { AzureCommunicationTokenCredential} = require('@azure/communication-common');
const userToken = '<USER_TOKEN>';
const tokenCredential = new AzureCommunicationTokenCredential(userToken);
callClient = new CallClient();
const callAgent = await callClient.createCallAgent(tokenCredential, {displayName: 'optional user name'});
可在 CallClient
实例上使用 getDeviceManager
方法来访问 deviceManager
。
const deviceManager = await callClient.getDeviceManager();
// Get a list of available video devices for use.
const localCameras = await deviceManager.getCameras();
// Get a list of available microphone devices for use.
const localMicrophones = await deviceManager.getMicrophones();
// Get a list of available speaker devices for use.
const localSpeakers = await deviceManager.getSpeakers();
获取设备权限
Twilio
Twilio Video 要求对轨道创建具有设备权限。
Azure 通信服务
提示用户授予相机和/或麦克风权限:
const result = await deviceManager.askDevicePermission({audio: true, video: true});
输出将返回,其中包含指示是否授予音频和视频权限的对象:
console.log(result.audio); console.log(result.video);
启动通话
Twilio
import * as TwilioVideo from 'twilio-video';
const twilioVideo = TwilioVideo;
let twilioRoom;
twilioRoom = await twilioVideo.connect('token', { name: 'roomName', audio: false, video: false });
Azure 通信服务
若要创建并启动通话,请使用其中一个 callAgent
API,并提供你通过通信服务标识 SDK 创建的用户。
创建和发起呼叫的操作是同步的。 使用 call
实例可以订阅通话事件。 订阅 stateChanged
事件以获取值更改。
call.on('stateChanged', async () =\> { console.log(\`Call state changed: \${call.state}\`) });
1:1 呼叫
若要呼叫另一个 Azure 通信服务用户,请在 callAgent
上使用 startCall
方法,并传递你使用通信服务管理库创建的接收人的 CommunicationUserIdentifier
。
const userCallee = { communicationUserId: '\<Azure_Communication_Services_USER_ID\>' };
const oneToOneCall = callAgent.startCall([userCallee]);
聊天室通话
若要加入 Room
通话,可以将具有 roomId
属性的上下文对象实例化为聊天室标识符。 若要加入通话,请使用 join
方法并传递上下文实例。
const context = { roomId: '\<RoomId\>' };
const call = callAgent.join(context);
通过聊天室,应用程序开发人员可以更好地控制谁可以加入通话、何时见面以及如何协作。 若要了解有关聊天室的详细信息,请参阅聊天室概述,或参阅快速入门:加入聊天室通话。
群组呼叫
若要发起新的群组通话或加入正在进行的群组通话,请使用 join
方法并传递带有 groupId
属性的对象。 groupId
值必须是 GUID。
const context = { groupId: '\<GUID\>'};
const call = callAgent.join(context);
Teams 呼叫
使用 teamsCallAgent
上的 startCall
API 启动同步一对一或组通话。 可以提供 MicrosoftTeamsUserIdentifier
或 PhoneNumberIdentifier
作为参数来定义呼叫的目标。 此方法返回可以订阅通话事件的 TeamsCall
实例。
const userCallee = { microsoftTeamsUserId: '\<MICROSOFT_TEAMS_USER_ID\>' };
const oneToOneCall = teamsCallAgent.startCall(userCallee);
接受和加入通话
Twilio
使用 Twilio 视频 SDK 时,参与者在加入聊天室后创建;它没有任何关于其他聊天室的信息。
Azure 通信服务
Azure 通信服务具有 CallAgent
实例,该实例在登录标识收到传入呼叫时发出 incomingCall
事件。
callAgent.on('incomingCall', async (call) =\>{
// Incoming call
});
incomingCall
事件包括你可以接受或拒绝的一个 incomingCall
实例。
在视频开启时启动、加入或接受呼叫,如果指定的视频相机设备正由另一个进程使用,或者系统中禁用了相机,则呼叫将在视频关闭时开始,并返回 cameraStartFailed: true
呼叫诊断。
const incomingCallHandler = async (args: { incomingCall: IncomingCall }) => {
const incomingCall = args.incomingCall;
// Get incoming call ID
var incomingCallId = incomingCall.id
// Get information about this Call.
var callInfo = incomingCall.info;
// Get information about caller
var callerInfo = incomingCall.callerInfo
// Accept the call
var call = await incomingCall.accept();
// Reject the call
incomingCall.reject();
// Subscribe to callEnded event and get the call end reason
incomingCall.on('callEnded', args =>
{ console.log(args.callEndReason);
});
// callEndReason is also a property of IncomingCall
var callEndReason = incomingCall.callEndReason;
};
callAgentInstance.on('incomingCall', incomingCallHandler);
启动呼叫、加入呼叫或接受呼叫后,还可以使用 callAgent
callsUpdated
事件接收新 Call
对象的通知并开始订阅该事件。
callAgent.on('callsUpdated', (event) => {
event.added.forEach((call) => {
// User joined call
});
event.removed.forEach((call) => {
// User left call
});
});
有关 Azure 通信服务 Teams 实现,请参阅如何接收 Teams 传入呼叫。
添加和删除通话参与者
Twilio
参与者无法从 Twilio 聊天室添加或删除,他们需要加入聊天室或与聊天室本身断开连接。
可以通过以下方式访问 Twilio 聊天室中的本地参与者:
let localParticipant = twilioRoom.localParticipant;
Twilio 聊天室中的远程参与者通过以唯一参与者 SID 作为键的地图来表示:
twilioRoom.participants;
Azure 通信服务
所有远程参与者均以 RemoteParticipant
类型表示,可通过通话实例上的 remoteParticipants
集合获得。
remoteParticipants
集合返回通话中远程参与者的列表:
call.remoteParticipants; // [remoteParticipant, remoteParticipant....]
添加参与者:
若要将参与者添加到通话中,可以使用 addParticipant
。 提供一种标识符类型。 它将同步返回 remoteParticipant
实例。
当参与者成功添加到通话中时,通话中将引发 remoteParticipantsUpdated
事件。
const userIdentifier = { communicationUserId: '<Azure_Communication_Services_USER_ID>' };
const remoteParticipant = call.addParticipant(userIdentifier);
删除参与者:
若要从通话中删除参与者,请使用 removeParticipant
。 需要传递其中一种标识符类型。 从通话中删除参与者后,此方法异步进行解析。 还将从 remoteParticipants
集合中删除该参与者。
const userIdentifier = { communicationUserId: '<Azure_Communication_Services_USER_ID>' };
await call.removeParticipant(userIdentifier);
订阅通话的 remoteParticipantsUpdated
事件,以在将新参与者添加到通话或从通话中删除时收到通知。
call.on('remoteParticipantsUpdated', e => {
e.added.forEach(remoteParticipant => {
// Subscribe to new remote participants that are added to the call
});
e.removed.forEach(remoteParticipant => {
// Unsubscribe from participants that are removed from the call
})
});
订阅远程参与者的 stateChanged
事件以获取值更改。
remoteParticipant.on('stateChanged', () => {
console.log(`Remote participants state changed: ${remoteParticipant.state}`)
});
视频通话
启动和停止视频
Twilio
const videoTrack = await twilioVideo.createLocalVideoTrack({ constraints });
const videoTrackPublication = await localParticipant.publishTrack(videoTrack, { options });
默认情况下,相机处于启用状态。 如有必要,可以禁用和启用它:
videoTrack.disable();
或:
videoTrack.enable();
如果有稍后创建的视频轨道,请在本地附加它:
const videoElement = videoTrack.attach();
const localVideoContainer = document.getElementById( localVideoContainerId );
localVideoContainer.appendChild(videoElement);
Twilio 轨道依赖于默认输入设备,并反映默认值的更改。 若要更改输入设备,需要取消发布上一个视频轨道:
localParticipant.unpublishTrack(videoTrack);
然后,使用正确的约束创建新的视频轨道。
Azure 通信服务
若要在通话时开始视频,需要在 deviceManager
对象上使用 getCameras
方法来枚举相机。 接下来使用所需相机创建一个新的 LocalVideoStream
实例,然后将 LocalVideoStream
对象传递给现有通话对象的 startVideo
方法:
const deviceManager = await callClient.getDeviceManager();
const cameras = await deviceManager.getCameras();
const camera = cameras[0]
const localVideoStream = new LocalVideoStream(camera);
await call.startVideo(localVideoStream);
成功开始发送视频后,系统会将一个视频类型的 LocalVideoStream
实例添加到通话实例上的 localVideoStreams
集合。
const localVideoStream = call.localVideoStreams.find( (stream) =\> { return stream.mediaStreamType === 'Video'} );
若要在通话时停止本地视频,请传递用于视频的 localVideoStream
实例:
await call.stopVideo(localVideoStream);
对 localVideoStream
实例呼叫 switchSource
来发送视频时,可切换到不同的相机设备:
const cameras = await callClient.getDeviceManager().getCameras();
const camera = cameras[1];
localVideoStream.switchSource(camera);
如果指定的视频设备被另一个进程占用或在系统中被禁用:
- 在通话中,如果视频已关闭并且使用
call.startVideo()
启动视频,则此方法将返回SourceUnavailableError
并且cameraStartFailed
设置为 true。 - 调用
localVideoStream.switchSource()
方法将导致cameraStartFailed
设置为 true。 有关如何诊断呼叫相关问题的详细信息,请参阅呼叫诊断指南。
要验证本地视频是开启还是关闭,可以使用返回 true 或 false 的 isLocalVideoStarted
API:
call.isLocalVideoStarted;
要侦听本地视频的更改,可以订阅和取消订阅 isLocalVideoStartedChanged
事件:
// Subscribe to local video event
call.on('isLocalVideoStartedChanged', () => {
// Callback();
});
// Unsubscribe from local video event
call.off('isLocalVideoStartedChanged', () => {
// Callback();
});
呈现远程用户的视频
Twilio
只要远程参与者发布视频轨道,便需要附加。 聊天室或远程参与者的 trackSubscribed
事件可用于检测何时可以附加轨道:
twilioRoom.on('participantConneted', (participant) => {
participant.on('trackSubscribed', (track) => {
const remoteVideoElement = track.attach();
const remoteVideoContainer = document.getElementById(remoteVideoContainerId + participant.identity);
remoteVideoContainer.appendChild(remoteVideoElement);
});
});
或
twilioRoom..on('trackSubscribed', (track, publication, participant) => {
const remoteVideoElement = track.attach();
const remoteVideoContainer = document.getElementById(remoteVideoContainerId + participant.identity);
remoteVideoContainer.appendChild(remoteVideoElement);
});
});
Azure 通信服务
若要列出远程参与者的视频流和屏幕共享流,请检查 videoStreams
集合:
const remoteVideoStream: RemoteVideoStream = call.remoteParticipants[0].videoStreams[0];
const streamType: MediaStreamType = remoteVideoStream.mediaStreamType;
要呈现 RemoteVideoStream
,必须订阅其 isAvailableChanged
事件。 如果 isAvailable
属性更改为 true,则表示远程参与者正在发送流。 发生该情况后,请创建一个新的 VideoStreamRenderer
实例,然后使用异步 createView
方法创建一个新的 VideoStreamRendererView
实例。 然后,可以将 view.target
附加到任何 UI 元素。
只要远程流的可用性发生更改,就可以销毁整个 VideoStreamRenderer
或特定 VideoStreamRendererView
。 如果决定保留它们,则会显示空白视频帧。
// Reference to the html's div where we would display a grid of all remote video streams from all participants.
let remoteVideosGallery = document.getElementById('remoteVideosGallery');
subscribeToRemoteVideoStream = async (remoteVideoStream) => {
let renderer = new VideoStreamRenderer(remoteVideoStream);
let view;
let remoteVideoContainer = document.createElement('div');
remoteVideoContainer.className = 'remote-video-container';
let loadingSpinner = document.createElement('div');
// See the css example below for styling the loading spinner.
loadingSpinner.className = 'loading-spinner';
remoteVideoStream.on('isReceivingChanged', () => {
try {
if (remoteVideoStream.isAvailable) {
const isReceiving = remoteVideoStream.isReceiving;
const isLoadingSpinnerActive = remoteVideoContainer.contains(loadingSpinner);
if (!isReceiving && !isLoadingSpinnerActive) {
remoteVideoContainer.appendChild(loadingSpinner);
} else if (isReceiving && isLoadingSpinnerActive) {
remoteVideoContainer.removeChild(loadingSpinner);
}
}
} catch (e) {
console.error(e);
}
});
const createView = async () => {
// Create a renderer view for the remote video stream.
view = await renderer.createView();
// Attach the renderer view to the UI.
remoteVideoContainer.appendChild(view.target);
remoteVideosGallery.appendChild(remoteVideoContainer);
}
// Remote participant has switched video on/off
remoteVideoStream.on('isAvailableChanged', async () => {
try {
if (remoteVideoStream.isAvailable) {
await createView();
} else {
view.dispose();
remoteVideosGallery.removeChild(remoteVideoContainer);
}
} catch (e) {
console.error(e);
}
});
// Remote participant has video on initially.
if (remoteVideoStream.isAvailable) {
try {
await createView();
} catch (e) {
console.error(e);
}
}
console.log(`Initial stream size: height: ${remoteVideoStream.size.height}, width: ${remoteVideoStream.size.width}`);
remoteVideoStream.on('sizeChanged', () => {
console.log(`Remote video stream size changed: new height: ${remoteVideoStream.size.height}, new width: ${remoteVideoStream.size.width}`);
});
}
订阅远程参与者的 videoStreamsUpdated
事件,以在远程参与者新增视频流并删除视频流时收到通知。
remoteParticipant.on('videoStreamsUpdated', e => {
e.added.forEach(remoteVideoStream => {
// Subscribe to new remote participant's video streams
});
e.removed.forEach(remoteVideoStream => {
// Unsubscribe from remote participant's video streams
});
});
虚拟背景
Twilio
要使用虚拟背景,请安装 Twilio 帮助程序库:
npm install @twilio/video-processors
创建并加载新的 Processor
实例:
import { GaussianBlurBackgroundProcessor } from '@twilio/video-processors';
const blurProcessor = new GaussianBlurBackgroundProcessor({ assetsPath: virtualBackgroundAssets });
await blurProcessor.loadModel();
只要加载了模型,便可使用 addProcessor
方法将背景添加到视频轨道:
videoTrack.addProcessor(processor, { inputFrameBufferType: 'video', outputFrameBufferContextType: 'webgl2' });
Azure 通信服务
使用 npm install 命令安装适用于 JavaScript 的 Azure 通信服务效果 SDK。
npm install @azure/communication-calling-effects --save
注意
要将视频效果与 Azure 通信呼叫 SDK 配合使用,在创建 LocalVideoStream 后,需要获取 LocalVideoStream 的 VideoEffects 功能 API 来启动/停止视频效果:
import * as AzureCommunicationCallingSDK from '@azure/communication-calling';
import { BackgroundBlurEffect, BackgroundReplacementEffect } from '@azure/communication-calling-effects';
// Get the video effects feature API on the LocalVideoStream
// (here, localVideoStream is the LocalVideoStream object you created while setting up video calling)
const videoEffectsFeatureApi = localVideoStream.feature(AzureCommunicationCallingSDK.Features.VideoEffects);
// Subscribe to useful events
videoEffectsFeatureApi.on(‘effectsStarted’, () => {
// Effects started
});
videoEffectsFeatureApi.on(‘effectsStopped’, () => {
// Effects stopped
});
videoEffectsFeatureApi.on(‘effectsError’, (error) => {
// Effects error
});
模糊背景:
// Create the effect instance
const backgroundBlurEffect = new BackgroundBlurEffect();
// Recommended: Check support
const backgroundBlurSupported = await backgroundBlurEffect.isSupported();
if (backgroundBlurSupported) {
// Use the video effects feature API we created to start effects
await videoEffectsFeatureApi.startEffects(backgroundBlurEffect);
}
要对图像使用自定义背景替换,需要提供所需的 URL 作为此效果背景的图像。 支持的图像格式包括:PNG、JPG、JPEG、TIFF 和 BMP。 支持的纵横比为 16:9。
const backgroundImage = 'https://linkToImageFile';
// Create the effect instance
const backgroundReplacementEffect = new BackgroundReplacementEffect({
backgroundImageUrl: backgroundImage
});
// Recommended: Check support
const backgroundReplacementSupported = await backgroundReplacementEffect.isSupported();
if (backgroundReplacementSupported) {
// Use the video effects feature API as before to start/stop effects
await videoEffectsFeatureApi.startEffects(backgroundReplacementEffect);
}
通过以下配置方法传递图像来更改此效果的图像:
const newBackgroundImage = 'https://linkToNewImageFile';
await backgroundReplacementEffect.configure({
backgroundImageUrl: newBackgroundImage
});
要切换效果,在视频效果功能 API 上使用相同的方法:
// Switch to background blur
await videoEffectsFeatureApi.startEffects(backgroundBlurEffect);
// Switch to background replacement
await videoEffectsFeatureApi.startEffects(backgroundReplacementEffect);
如果想要检查哪些效果处于活动状态,可以随时使用 activeEffects
属性。 属性 activeEffects
返回具有当前活动效果名称的数组,如果没有活动效果,则返回空数组。
// Using the video effects feature api
const currentActiveEffects = videoEffectsFeatureApi.activeEffects;
停止效果:
await videoEffectsFeatureApi.stopEffects();
音频
启动和停止音频
Twilio
const audioTrack = await twilioVideo.createLocalAudioTrack({ constraints });
const audioTrackPublication = await localParticipant.publishTrack(audioTrack, { options });
默认情况下,麦克风处于启用状态。 可以根据需要禁用和启用它:
audioTrack.disable();
或
audioTrack.enable();
本地参与者应以与视频轨道相同的方式附加任何已创建的音频轨道:
const audioElement = audioTrack.attach();
const localAudioContainer = document.getElementById(localAudioContainerId);
localAudioContainer.appendChild(audioElement);
由远程参与者:
twilioRoom.on('participantConneted', (participant) => {
participant.on('trackSubscribed', (track) => {
const remoteAudioElement = track.attach();
const remoteAudioContainer = document.getElementById(remoteAudioContainerId + participant.identity);
remoteAudioContainer.appendChild(remoteAudioElement);
});
});
或:
twilioRoom..on('trackSubscribed', (track, publication, participant) => {
const remoteAudioElement = track.attach();
const remoteAudioContainer = document.getElementById(remoteAudioContainerId + participant.identity);
remoteVideoContainer.appendChild(remoteAudioElement);
});
});
无法在 Twilio 视频 SDK 中将传入的音频静音。
Azure 通信服务
await call.startAudio();
若要将本地终结点设置为静音或取消静音,可以使用静音和取消静音异步 API:
//mute local device (microphone / sent audio)
await call.mute();
//unmute local device (microphone / sent audio)
await call.unmute();
如果将传入的音频设置为静音,这会将通话音量设置为 0。 若要将传入的音频设置为静音或取消静音,可使用 muteIncomingAudio
和 unmuteIncomingAudio
异步 API:
//mute local device (speaker)
await call.muteIncomingAudio();
//unmute local device (speaker)
await call.unmuteIncomingAudio();
检测主导发言人
Twilio
若要检测会议室中最响亮的参与者,请使用主导发言人 API。 加入至少有 2 个参与者的组聊天室时,可以在连接选项中启用它:
twilioRoom = await twilioVideo.connect('token', {
name: 'roomName',
audio: false,
video: false,
dominantSpeaker: true
});
当聊天室中最响亮的发言人发生改变时,发出 dominantSpeakerChanged
事件:
twilioRoom.on('dominantSpeakerChanged', (participant) => {
// Highlighting the loudest speaker
});
Azure 通信服务
通话的主导发言人是核心通话 API 的扩展功能。 它可让你在通话中获取活跃的发言人的列表。 主导发言人列表是排名列表,列表中的第一个元素表示通话中最后一个活跃的发言人,依此类推。
为获取通话中的主导说话人,首先需获取通话主导说话人功能 API 对象:
const callDominantSpeakersApi = call.feature(Features.CallDominantSpeakers);
接下来,通过调用 dominantSpeakers
获取主导发言人列表。 其类型为 DominantSpeakersInfo
,具有以下成员:
speakersList
包含通话中已排名的主导说话人列表。 这些由其参与者 ID 表示。timestamp
是通话中的主导发言人的最新更新时间。
let dominantSpeakers: DominantSpeakersInfo = callDominantSpeakersApi.dominantSpeakers;
还可以订阅 dominantSpeakersChanged
事件,了解主导发言人列表何时发生更改。
const dominantSpeakersChangedHandler = () => {
// Get the most up-to-date list of dominant speakers
let dominantSpeakers = callDominantSpeakersApi.dominantSpeakers;
};
callDominantSpeakersApi.on('dominantSpeakersChanged', dominantSpeakersChangedHandler);
启用屏幕共享
Twilio
若要在 Twilio 视频中共享屏幕,请通过 navigator.mediaDevices
获取源轨道:
基于 Chromium 的浏览器:
const stream = await navigator.mediaDevices.getDisplayMedia({
audio: false,
video: true
});
const track = stream.getTracks()[0];
Firefox 和 Safari:
const stream = await navigator.mediaDevices.getUserMedia({ mediaSource: 'screen' });
const track = stream.getTracks()[0];
获取屏幕共享轨道,然后你可以采用与休闲视频轨道相同的方式发布和管理它(请参阅“视频”部分)。
Azure 通信服务
若要在通话时启动屏幕共享,可以使用异步 API startScreenSharing
:
await call.startScreenSharing();
成功开始发送屏幕共享后,ScreenSharing
类型的 LocalVideoStream
实例将会创建并添加到通话实例上的 localVideoStreams
集合。
const localVideoStream = call.localVideoStreams.find( (stream) => { return stream.mediaStreamType === 'ScreenSharing'} );
若要在通话时停止屏幕共享,可以使用异步 API stopScreenSharing
:
await call.stopScreenSharing();
若要验证屏幕共享是开启还是关闭,可以使用返回 true 或 false 的 isScreenSharingOn
API:
call.isScreenSharingOn;
若要侦听屏幕共享的更改,可订阅和取消订阅 isScreenSharingOnChanged
事件:
// Subscribe to screen share event
call.on('isScreenSharingOnChanged', () => {
// Callback();
});
// Unsubscribe from screen share event
call.off('isScreenSharingOnChanged', () => {
// Callback();
});
媒体质量统计信息
Twilio
若要收集实时媒体统计信息,请使用“getStats”方法。
const stats = twilioRoom.getStats();
Azure 通信服务
媒体质量统计信息是核心通话 API 的扩展功能。 首先需要获取 mediaStatsFeature
API 对象:
const mediaStatsFeature = call.feature(Features.MediaStats);
若要接收媒体统计信息数据,可以订阅 sampleReported
事件或 summmaryReported
事件:
sampleReported
事件每秒触发一次。 适合用作 UI 显示或你自己的数据管道的数据源。summmaryReported
事件包含间隔内数据的聚合值。 当你只需要摘要时非常有用。
如果要控制 summmaryReported
事件的间隔,则需要定义 MediaStatsCollectorOptions
类型的 mediaStatsCollectorOptions
。 否则,SDK 使用默认值。
const mediaStatsCollectorOptions: SDK.MediaStatsCollectorOptions = {
aggregationInterval: 10,
dataPointsPerAggregation: 6
};
const mediaStatsCollector = mediaStatsFeature.createCollector(mediaStatsSubscriptionOptions);
mediaStatsCollector.on('sampleReported', (sample) => {
console.log('media stats sample', sample);
});
mediaStatsCollector.on('summaryReported', (summary) => {
console.log('media stats summary', summary);
});
如果不需要使用媒体统计信息收集器,则可以调用 mediaStatsCollector
的处理方法。
mediaStatsCollector.dispose();
无需在每次调用结束时调用 mediaStatsCollector
的处理方法。 调用结束时,收集器将在内部回收。
有关详细信息,请参阅 媒体质量统计信息。
诊断
Twilio
为了测试连接性,Twilio 提供预检 API。 这是一个测试调用,用于识别信令和媒体连接问题。
启动测试需要访问令牌:
const preflightTest = twilioVideo.runPreflight(token);
// Emits when particular call step completes
preflightTest.on('progress', (progress) => {
console.log(`Preflight progress: ${progress}`);
});
// Emits if the test has failed and returns error and partial test results
preflightTest.on('failed', (error, report) => {
console.error(`Preflight error: ${error}`);
console.log(`Partial preflight test report: ${report}`);
});
// Emits when the test has been completed successfully and returns the report
preflightTest.on('completed', (report) => {
console.log(`Preflight test report: ${report}`);
});
在调用期间识别网络问题的另一种方法是使用网络质量 API 来监视参与者的网络并提供质量指标。 当参与者加入组聊天室时,可以在连接选项中启用它:
twilioRoom = await twilioVideo.connect('token', {
name: 'roomName',
audio: false,
video: false,
networkQuality: {
local: 3, // Local Participant's Network Quality verbosity
remote: 1 // Remote Participants' Network Quality verbosity
}
});
当参与者的网络质量发生更改时,它会生成 networkQualityLevelChanged
事件:
participant.on(networkQualityLevelChanged, (networkQualityLevel, networkQualityStats) => {
// Processing Network Quality stats
});
Azure 通信服务
Azure 通信服务提供一项称为 "User Facing Diagnostics" (UFD)
的功能,可用于检查调用的各种属性来识别问题。 面向用户的诊断事件可能是由一些基础问题(网络不佳、用户麦克风静音)引起的,这可能导致用户通话体验不佳。
面向用户的诊断是核心调用 API 的扩展功能,可用于诊断活动呼叫。
const userFacingDiagnostics = call.feature(Features.UserFacingDiagnostics);
订阅“diagnosticChanged”事件,以监视何时发生任何面向用户的诊断更改:
/**
* Each diagnostic has the following data:
* - diagnostic is the type of diagnostic, e.g. NetworkSendQuality, DeviceSpeakWhileMuted
* - value is DiagnosticQuality or DiagnosticFlag:
* - DiagnosticQuality = enum { Good = 1, Poor = 2, Bad = 3 }.
* - DiagnosticFlag = true | false.
* - valueType = 'DiagnosticQuality' | 'DiagnosticFlag'
*/
const diagnosticChangedListener = (diagnosticInfo: NetworkDiagnosticChangedEventArgs | MediaDiagnosticChangedEventArgs) => {
console.log(`Diagnostic changed: ` +
`Diagnostic: ${diagnosticInfo.diagnostic}` +
`Value: ${diagnosticInfo.value}` +
`Value type: ${diagnosticInfo.valueType}`);
if (diagnosticInfo.valueType === 'DiagnosticQuality') {
if (diagnosticInfo.value === DiagnosticQuality.Bad) {
console.error(`${diagnosticInfo.diagnostic} is bad quality`);
} else if (diagnosticInfo.value === DiagnosticQuality.Poor) {
console.error(`${diagnosticInfo.diagnostic} is poor quality`);
}
} else if (diagnosticInfo.valueType === 'DiagnosticFlag') {
if (diagnosticInfo.value === true) {
console.error(`${diagnosticInfo.diagnostic}`);
}
}
};
userFacingDiagnostics.network.on('diagnosticChanged', diagnosticChangedListener);
userFacingDiagnostics.media.on('diagnosticChanged', diagnosticChangedListener);
若要详细了解面向用户的诊断和可用的不同诊断值,请参阅面向用户的诊断。
Azure 通信服务还提供调用前诊断 API。 若要访问调用前 API,需要初始化 callClient
并预配一个 Azure 通信服务访问令牌。 然后,可以访问 PreCallDiagnostics
功能和 startTest
方法。
import { CallClient, Features} from "@azure/communication-calling";
import { AzureCommunicationTokenCredential } from '@azure/communication-common';
const callClient = new CallClient();
const tokenCredential = new AzureCommunicationTokenCredential("INSERT ACCESS TOKEN");
const preCallDiagnosticsResult = await callClient.feature(Features.PreCallDiagnostics).startTest(tokenCredential);
呼叫前 API 返回设备的完整诊断信息,包括设备权限、可用性和兼容性、呼叫质量统计信息和呼叫中诊断等详细信息。 结果作为 PreCallDiagnosticsResult
对象返回。
export declare type PreCallDiagnosticsResult = {
deviceAccess: Promise<DeviceAccess>;
deviceEnumeration: Promise<DeviceEnumeration>;
inCallDiagnostics: Promise<InCallDiagnostics>;
browserSupport?: Promise<DeviceCompatibility>;
id: string;
callMediaStatistics?: Promise<MediaStatsCallFeature>;
};
可以在调用前诊断中详细了解如何确保调用前就绪。
事件侦听器
Twilio
twilioRoom.on('participantConneted', (participant) => {
// Participant connected
});
twilioRoom.on('participantDisconneted', (participant) => {
// Participant Disconnected
});
Azure 通信服务
JavaScript 呼叫 SDK 中的每个对象都有属性和集合。 其值在对象的整个生存期内都会更改。 使用 on()
方法订阅对象的事件,使用 off()
方法取消订阅对象的事件。
属性
- 必须检查其初始值,并订阅
'\<property\>Changed'
事件,以便未来对值进行更新。
集合
- 必须检查其初始值,并订阅
'\<collection\>Updated'
事件,以便未来对值进行更新。 '\<collection\>Updated'
事件的负载具有added
数组,其中包含添加到集合的值。'\<collection\>Updated'
事件的负载还具有已移除的数组,其中包含从集合中移除的值。
离开和结束会话
Twilio
twilioVideo.disconnect();
Azure 通信服务
call.hangUp();
// Set the 'forEveryone' property to true to end call for all participants
call.hangUp({ forEveryone: true });
清理
如果想要清理并删除通信服务订阅,可以删除资源或资源组。
先决条件
- Azure 帐户: 确保 Azure 帐户处于活动状态。 新用户可以在 Microsoft Azure 创建免费帐户。
- 通信服务资源:通过 Azure 门户设置通信服务资源并记下连接字符串。
- Azure CLI:按照说明在 Windows.上安装 Azure CLI。
- 用户访问令牌:生成用户访问令牌以实例化呼叫客户端。 可以使用 Azure CLI 创建一个,如下所示:
az communication identity token issue --scope voip --connection-string "yourConnectionString"
有关详细信息,请参阅使用 Azure CLI 创建和管理访问令牌。
对于 Teams 用户的视频通话:
- 还可以使用 Teams 标识。 若要为 Teams 用户生成访问令牌,请参阅管理团队标识。
- 使用 Graph Explorer,为呼叫操作获取 Teams 线程 ID。 有关创建线程 ID 的信息,请参阅创建聊天 - Microsoft Graph v1.0> 示例 2:创建群聊。
UI 库
Azure 通信服务 UI 库简化了使用 Azure 通信服务呼叫创建现代通信用户界面的过程。 它提供一系列现成的 UI 组件,可轻松集成到应用程序中。
此开源预建控件集可让你使用 Fluent UI SDK 组件创建美观的设计,并开发高质量的音频/视频通信体验。 有关详细信息,请查看 Azure 通信服务 UI 库概述。 概述包括有关 Web 和移动平台的全面信息。
安装
若要开始从 Twilio Video 迁移,第一步是将适用于 iOS 的 Azure 通信服务呼叫 SDK 安装到项目中。 可以使用Cocoapods
配置这些参数。
- 若要为应用程序创建 Podfile,请打开终端并导航到项目文件夹,然后运行:
pod init
- 将以下代码添加到 Podfile 并保存(确保“目标对象”与项目名称匹配):
platform :ios, '13.0'
use_frameworks!
target 'AzureCommunicationCallingSample' do
pod 'AzureCommunicationCalling', '~> 2.6.0'
end
- 设置
.xcworkspace
项目
pod install
- 使用 Xcode 打开 pod install 创建的
.xcworkspace
。
向 SDK 进行身份验证
为了能够使用 Azure 通信服务呼叫 SDK,需要使用访问令牌进行身份验证。
Twilio
以下代码片段假定 Twilio 服务的有效访问令牌的可用性。
在 Twilio Video 中,访问令牌用于连接到聊天室。 通过将令牌传递给 ConnectOptions
,可以创建用于创建或连接聊天室的选项。
let connectOptions = ConnectOptions(token: accessToken) {
// Twilio Connect options goes here
}
let room = TwilioVideoSDK.connect(
options: connectOptions,
delegate: // The Room Delegate
)
Azure 通信服务
以下代码片段需要有效的访问令牌来启动 CallClient
。
需要有效的令牌。 有关详细信息,请参阅创建和管理访问令牌。
// Create an instance of CallClient
let callClient = CallClient()
// A reference to the call agent, it will be initialized later
var callAgent: CallAgent?
// Embed the token in a CommunicationTokenCredential object
let userCredential = try? CommunicationTokenCredential(token: "<USER_TOKEN>")
// Create a CallAgent that will be used later to initiate or receive calls
callClient.createCallAgent(userCredential: userCredential) { callAgent, error in
if error != nil {
// Raise the error to the user and return
}
self.callAgent = callAgent
}
类引用
类名 | 说明 |
---|---|
CallClient | 表示调用 SDK 入口点的主类。 |
CommunicationTokenCredential | Azure 通信服务用户令牌凭据 |
CallAgent | 负责代表经过身份验证的用户管理调用的类 |
发起传出呼叫
Twilio
Twilio Video 有 Room
的概念,如果用户 Bob 想要与客户端 Alice Bob 进行呼叫,可以创建聊天室,Alice 必须通过实现推送通知等功能来连接到聊天室。
连接到聊天室
当用户 Bob 或用户 Alice 想要创建或连接到聊天室时,并且他们具有有效的访问令牌时。 他们可以传递要创建或作为 ConnectOptions
参数进行连接的聊天室名称。
let connectOptions = ConnectOptions(token: accessToken) { builder in
builder.roomName = "the-room"
}
room = TwilioVideoSDK.connect(options: connectOptions, delegate: self)
Azure 通信服务
连接到呼叫
CommunicationUserIdentifier
表示使用标识 SDK 或 REST API 创建的用户标识。 如果应用程序不使用 Microsoft Teams 互操作性或电话功能,则它是唯一使用的标识符。
使用 Azure 通信服务呼叫 SDK 发起呼叫包括以下步骤:
- 创建
StartCallOptions
对象 - 创建
CommunicationUserIdentifier
数组 - 对之前创建的
CallAgent
调用startCall
方法
let startCallOptions = StartCallOptions() // 1
let callees = [CommunicationUserIdentifier(“<USER_ID>”)] // 2
callAgent?.startCall(participants: callees, options: startCallOptions) { call, error in
// Check for error if no Error and the call object isn't nil then the call is being established
}
连接到 Teams 的通话
使用外部标识
连接到团队通话与连接到单人通话几乎相同。 客户端应用程序需要将 JoinCallOptions
与 TeamsMeeting locator
一起使用,而不是使用 StartCallOptions
。
可以使用图形 API 来检索 Teams 会议链接。 可以在 Graph 文档中详细了解 Graph API。
let joinCallOptions = JoinCallOptions()
let teamsMeetingLinkLocator = TeamsMeetingLinkLocator(meetingLink: meetingLink)
callAgent?.join(with: teamsMeetingLinkLocator, joinCallOptions: joinCallOptions) { call, error in
// Handle error or set a CallDelegate delegate on the call if no error
}
接受和加入通话
Twilio
Twilio Video 使用 Room
的概念。 不同的客户端可以通过加入同一聊天室来建立通信。 因此,接受和加入通话不是直接的替代方法。
Azure 通信服务
接收传入呼叫
若要接受呼叫,必须先将应用程序配置为接收传入呼叫。
注册推送通知并处理传入的推送通知
通话客户端可以选择接收推送通知以接收传入呼叫。 本指南介绍如何为 Azure 通信服务呼叫设置 APNS。
设置 CallAgentDelegate
Azure 通信服务呼叫 SDK 有 CallAgentDelegate
,后者具有在传入呼叫期间调用的方法。
class ApplicationCallAgentDelegate: NSObject, CallAgentDelegate {
func callAgent(_ callAgent: CallAgent, didUpdateCalls args: CallsUpdatedEventArgs) {}
func callAgent(_ callAgent: CallAgent, didRecieveIncomingCall incomingCall: IncomingCall) {
// This is called when the application receives an incoming call
// An application could use this callback to display an incoming call banner
// or report an incoming call to CallKit
}
}
若要接收传入呼叫,应用程序需要向其 CallAgent
添加 CallAgentDelegate
。
let callAgentDelegate = ApplicationCallAgentDelegate()
callClient.createCallAgent(userCredential: userCredential) { callAgent, error in
if error != nil {
// Raise the error to the user and return
}
self.callAgent = callAgent
self.callAgent?.delegate = callAgentDelegate
}
在 CallAgentDelegate
就位并与 CallAgent
实例关联后,应用程序应该能够接收传入呼叫。
接听来电
func acceptCall(incomingCall: IncomingCall) {
let options = AcceptCallOptions()
incomingCall.accept(options: options) {(call, error) in
if error != nil {
// Raise the error to the user and return
}
// The call is established clients can speak/view each other
}
}
类引用
类名 | 说明 |
---|---|
CallAgentDelegate | 定义 ACSCallAgent 在响应重要事件时调用的一组方法。 |
IncomingCall | 描述传入呼叫 |
视频流
启动和停止视频
Twilio
访问相机
使用 Twilio Video 时,向通话添加视频包括两个步骤:
- 访问相机
- 将视频轨道添加到
LocalVideoTrack
列表
let options = CameraSourceOptions { (builder) in
// Set the CameraSource options here
}
camera = CameraSource(options: options, delegate: aCameraDelegate)
创建 LocalVideoTrack
CameraSource 在创建后,便可关联到 LocalVideoTrack
。
localVideoTrack = LocalVideoTrack(source: camera!, enabled: true, name: "Camera")
将 LocalVideoTrack 添加到呼叫
在连接时。 在呼叫连接时,可以通过将本地视频轨道传递给可使用 ConnectOptions`` 设置的 localVideo
轨道列表,从而将本地视频轨道添加到呼叫中。
let connectOptions = ConnectOptions(token: accessToken) { builder in
builder.videoTracks = [localVideoTrack!]
}
在现有聊天室中。 本地参与者可以通过 publishVideoTrack(_ : LocalVideoTrack)
方法发布本地视频轨道。
room.localParticipant.publishVideoTrack(localVideoTrack)
Azure 通信服务
访问相机
通过 DeviceManager
完成访问相机。 可以使用以下代码获取 DeviceManager
的实例。
self.callClient.getDeviceManager { (deviceManager, error) in
if (error != nil) {
// Display an error message to the user and exit the closure
return
}
self.deviceManager = deviceManager
}
创建 LocalVideoStream
deviceManager
提供对可用于创建 LocalVideoStream
实例的相机的访问权限。
LocalVideoStream(camera: deviceManager.cameras.first!)
添加 LocalVideoStream
连接时
localVideoStream
可以通过 StartCallOptions
的 OutgoingVideoOptions
添加到流。
var callOptions = StartCallOptions()
let outgoingVideoOptions = OutgoingVideoOptions()
outgoingVideoOptions.streams = [localVideoStream]
在通话中
可以通过调用以 LocalVideoStream 作为参数的 startVideo 方法启动视频流。
call.startVideo(stream: localVideoStream) { error in
if error != ni {
// Report the error to the user and return
}
}
类引用
类名 | 说明 |
---|---|
DeviceManager | 促进与设备的交互 |
LocalVideoStream | 本地视频流信息 |
VideoDeviceInfo | 有关视频设备的信息 |
调用 | 描述呼叫 |
呈现视频
Twilio
若要使用 Twilio Video 呈现视频,可将符合 VideoRenderer
协议的对象添加到 VideoTrack
。 SDK 提供了可随时使用的 VideoRenderer
,名为 VideoView
,它是 UIView
的一个子类。
let videoView = VideoView(frame: CGRect.zero, delegate: nil)
创建 VideoView
的实例后,VideoTrack
(本地或远程)有一种方法 addVideoRenderer
,该方法可用于添加创建为呈现器的 videoView
。
localVideoTrack = LocalVideoTrack(source: camera, enabled: true, name: "Camera")
// Add renderer to video track for local preview
localVideoTrack!.addRenderer(videoView)
Azure 通信服务
若要使用 Azure 通信服务呼叫呈现视频,请创建 VideoStreamRenderer
并将 LocalVideoStream
或 RemoteVideoStream
作为参数传递。
let previewRenderer = try VideoStreamRenderer(localVideoStream: localVideoStream)
创建的 VideoStreamRenderer
可用于创建 VideoStreamRendererView
,后者呈现传递给 VideoStreamRenderer
的视频流。
let scalingMode = ScalingMode.fit
let options = CreateViewOptions(scalingMode:scalingMode)
let previewView = try previewRenderer.createView(withOptions:options)
类引用
类名 | 说明 |
---|---|
ScalingMode | 本地和远程视频缩放模式的枚举 |
CreateViewOptions | 呈现视频时传递的选项 |
VideoStreamRenderer | 用于视频呈现的呈现器 |
OutgoingVideoOptions | 文档尚不可用 |
VideoStreamRendererView | 用于呈现视频的视图 |
音频流
切换麦克风
Twilio
通过与麦克风关联的 LocalAudioTrack
对麦克风进行静音和取消静音。
麦克风静音
self.localAudioTrack.isEnabled = false
麦克风取消静音
self.localAudioTrack.isEnabled = true
Azure 通信服务
通过对 Call
对象调用 muteOutgoingAudio
和 unmuteoutgoingAudio
可以实现静音和取消静音。
麦克风静音
'call': call.muteOutgoingAudio() { error in
if error == nil {
isMuted = true
} else {
// Display an error to the user
}
}
麦克风取消静音
callBase.unmuteOutgoingAudio() { error in
if error == nil {
isMuted = true
} else {
// Display an error to the user
}
}
事件侦听器
Twilio Video 和 Azure 通信服务呼叫 SDK 提出各种委托来侦听呼叫事件。
聊天室/呼叫事件
Twilio
RoomDelegate
允许客户端侦听与聊天室相关的事件。 它具有可针对以下事件调用的方法:
- 客户端已连接或无法连接到聊天室
- 客户端正在重新连接到聊天室或已重新连接
- 远程参与者已连接、断开连接、重新连接到聊天室
- 聊天室录制已开始或停止
- 主导发言人更改
Azure 通信服务
Azure 通信服务呼叫 SDK 使 Call
对象能够合并各种事件侦听器,从而在调用属性发生更改时通知它们。 应单独订阅每个事件类型。 若要了解有关事件处理的详细信息,请参阅事件教程。
- 呼叫状态已更改。 这是报告连接事件的位置
- 远程参与者列表已更新
- 本地视频流已更新
- 静音状态已改变
本地参与者事件
Twilio
Twilio 具有 LocalParticpant
委托,允许客户端接收有关以下事件的更新:
- 本地参与者已发布或未能发布媒体轨道(音频、视频、数据)
- 本地参与者的网络质量级别已更改
Azure 通信服务
Azure 通信服务呼叫 SDK 具有 CallAgent
委托,允许客户端侦听呼叫代理相关事件。 它在以下情况下收到通知:
- 在传入呼叫或现有呼叫断开连接的情况下更新或创建呼叫时
- 收到传入呼叫时
远程参与者事件
这两个 SDK 都提出一个远程参与者委托,允许客户端收到有关每个远程参与者发生的情况的通知。
Twilio
RemoteParticipantDelegate
处理以下事件。
- 远程参与者已发布或取消发布媒体轨道(视频、音频、数据)
- 本地参与者已订阅、无法订阅或取消订阅远程媒体轨道(视频、音频、数据)
- 远程参与者网络质量已更改
- 远程参与者更改了轨道发布的优先级
- 远程参与者已打开/关闭其视频轨道
Azure 通信服务
RemoteParticipantDelegate
处理以下事件。
- 远程参与者状态已更改
- 远程参与者已静音或未静音
- 远程参与者正在讲话
- 远程参与者显示名称已更改
- 远程参与者已添加或删除视频流
相机事件
Twilio
Twilio 提议 CameraSourceDelegate
向客户端通知与相机相关的以下事件:
- 相机源已中断或已恢复(例如,将应用置于背景中时)
- 相机源失败
- 相机源报告系统压力
Azure 通信服务
Azure 通信服务通话建议 DeviceManagerDelegate
。 它包含单个方法,在当前 DeviceManager
上添加或删除视频设备时通知客户端。
类引用
类名 | 说明 |
---|---|
CallDelegate | 通过调用 SDK 来响应重要事件而调用的一组方法。 |
CallAgentDelegate | ACSCallAgent 在响应重要事件时调用的一组方法。 |
RemoteParticipantDelegate | ACSRemoteParticipant 在响应重要事件时调用的一组方法。 |
DeviceManagerDelegate | ACSDeviceManager 在响应重要事件时调用的一组方法。 |
结束呼叫
Twilio
结束呼叫(从聊天室断开连接)通过 room.disconnect()
方法完成。
Azure 通信服务
挂起呼叫通过 Call
对象的 hangUp
方法完成。
call.hangUp(options: HangUpOptions()) { error in
if error != nil {
print("ERROR: It was not possible to hang up the call.")
}
self.call = nil
}
类引用
类名 | 说明 |
---|---|
调用 | ACSCall 在响应重要事件时调用的一组方法。 |
HangUp 选项 | 用于挂断呼叫的属性包类 |
Azure 通信服务呼叫的主要功能
主导发言人
注册主导发言人更新的第一步是从 Call
对象获取主导发言人功能的实例。 在该教程中了解有关主导发言人配置的详细信息。
let dominantSpeakersFeature = call.feature(Features.dominantSpeakers)
获取主导发言人功能的实例后,DominantSpeakersCallFeatureDelegate
可以附加到其中。
dominantSpeakersFeature.delegate = DominantSpeakersDelegate()
public class DominantSpeakersDelegate : DominantSpeakersCallFeatureDelegate {
public func dominantSpeakersCallFeature(_ dominantSpeakersCallFeature: DominantSpeakersCallFeature, didChangeDominantSpeakers args: PropertyChangedEventArgs) {
// When the list changes, get the timestamp of the last change and the current list of Dominant Speakers
let dominantSpeakersInfo = dominantSpeakersCallFeature.dominantSpeakersInfo
let timestamp = dominantSpeakersInfo.lastUpdatedAt
let dominantSpeakersList = dominantSpeakersInfo.speakers
}
}
媒体质量统计信息
为了帮助你了解通话期间的媒体质量,Azure 通信服务 SDK 提供媒体质量统计信息。 使用它可检查传入和传出呼叫指标的低级别音频、视频和屏幕共享质量指标。有关详细信息,请参阅媒体质量统计信息指南。
面向用户的诊断
Azure 通信服务呼叫 SDK 提供一项称为“面向用户的诊断 (UFD)”的功能,可让客户端仔细检查呼叫的各种属性,以确定潜在问题。 若要了解有关面向用户的诊断的详细信息,请参阅面向用户的诊断。
重要
以下列表中所述的 Azure 通信服务呼叫 SDK 的某些功能在 Twilio Video SDK 中没有等效项。
举手
举手功能允许呼叫参与者举手或取消举手。
视频背景
添加视频背景 允许用户模糊视频流中的背景。
视频聚焦
聚焦 允许用户固定和取消固定视频。
先决条件
- Azure 帐户: 确保 Azure 帐户处于活动状态。 新用户可以在 Microsoft Azure 创建免费帐户。
- 通信服务资源:通过 Azure 门户设置通信服务资源并记下连接字符串。
- Azure CLI:按照说明在 Windows.上安装 Azure CLI。
- 用户访问令牌:生成用户访问令牌以实例化呼叫客户端。 可以使用 Azure CLI 创建一个,如下所示:
az communication identity token issue --scope voip --connection-string "yourConnectionString"
有关详细信息,请参阅使用 Azure CLI 创建和管理访问令牌。
对于 Teams 用户的视频通话:
- 还可以使用 Teams 标识。 若要为 Teams 用户生成访问令牌,请参阅管理团队标识。
- 使用 Graph Explorer,为呼叫操作获取 Teams 线程 ID。 有关创建线程 ID 的信息,请参阅创建聊天 - Microsoft Graph v1.0> 示例 2:创建群聊。
UI 库
Azure 通信服务 UI 库简化了使用 Azure 通信服务创建现代通信用户界面的过程。 它提供一系列现成的 UI 组件,可轻松集成到应用程序中。
此开源预建控件集可让你使用 Fluent UI SDK 组件创建美观的设计,并开发高质量的音频/视频通信体验。 有关详细信息,请查看 Azure 通信服务 UI 库概述。 概述包括有关 Web 和移动平台的全面信息。
安装
若要开始从 Twilio Video 迁移,第一步是将适用于 Android 的 Azure 通信服务呼叫 SDK 安装到项目中。 Azure 通信服务呼叫 SDK 可以集成为 gradle
依赖项。
- 添加 azure-communication-calling 包
dependencies {
...
implementation "com.azure.android:azure-communication-calling:<version>"
}
- 在应用程序清单中检查权限
确保应用程序的清单文件包含必要的权限,并做出所需的调整。
<manifest >
<uses-feature android:name="android.hardware.camera" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
</manifest>
向 SDK 进行身份验证
为了能够使用 Azure 通信服务呼叫 SDK,需要使用访问令牌进行身份验证。
Twilio
以下代码片段假定 Twilio 服务的有效访问令牌的可用性。
在 Twilio Video 中,访问令牌用于连接到聊天室。 通过将令牌传递给 ConnectOptions
,可以创建用于创建或连接聊天室的选项。
ConnectOptions connectOptions = new ConnectOptions.Builder(accessToken).build();
room = Video.connect(context, connectOptions, roomListener);
Azure 通信服务
以下代码片段需要有效的访问令牌来启动 CallClient
。
需要有效的令牌。 有关详细信息,请参阅创建和管理访问令牌。
String userToken = "<USER_TOKEN>";
CommunicationTokenCredential tokenCredential = new CommunicationTokenCredential(accessToken);
CallClient callClient = new CallClient();
callAgent = callClient.createCallAgent(getApplicationContext(), tokenCredential).get();
类引用
类名 | 说明 |
---|---|
CallClient | 用作呼叫 SDK 入口点的类。 |
CommunicationTokenCredential | Azure 通信服务用户令牌凭据 |
CallAgent | 负责代表经过身份验证的用户管理呼叫的类 |
发起传出呼叫
Twilio
Twilio Video 有 Room
的概念,如果用户 Bob 想要与客户端 Alice Bob 进行呼叫,可以创建聊天室,Alice 必须通过实现推送通知等功能来连接到聊天室。
当用户 Bob 或用户 Alice 想要创建或连接到聊天室时,并且他们具有有效的访问令牌时。 他们可以传递要创建或作为 ConnectOptions
参数进行连接的聊天室名称。
ConnectOptions connectOptions = new ConnectOptions.Builder(accessToken)
.roomName(roomName)
.build()
room = Video.connect(context, connectOptions, roomListener);
Azure 通信服务
连接到呼叫
使用 Azure 通信服务呼叫 SDK 发起呼叫包括以下步骤:
CommunicationUserIdentifier
表示使用标识 SDK 或 REST API 创建的用户标识。 如果应用程序不使用 Microsoft Teams 互操作性或电话功能,则它是唯一使用的标识符。
- 创建
CommunicationUserIdentifier
数组 - 对之前创建的
CallAgent
调用startCall
方法
ArrayList<CommunicationIdentifier> userCallee = new ArrayList<>();
participants.add(new CommunicationUserIdentifier(“<USER_ID>”));
Call call = callAgent.startCall(context, userCallee);
连接到 Teams 通话
使用外部标识
连接到 Teams 呼叫与连接到单人呼叫几乎完全相同。 客户端应用程序不使用 StartCallOptions
,而是将 JoinCallOptions
与 TeamsMeetingLocator
一起使用。
可以使用图形 API 来检索 Teams 会议链接。 图形文档中详细介绍了检索过程。
JoinCallOptions options = new JoinCallOptions();
TeamsMeetingLinkLocator teamsMeetingLinkLocator = new TeamsMeetingLinkLocator(meetingLink);
Call call = callAgent.join(getApplicationContext(), teamsMeetingLinkLocator, joinCallOptions);
接受和加入通话
Twilio
Twilio Video 使用 Room
的概念。 不同的客户端可以通过加入同一聊天室来建立通信。 因此,接受和加入通话不是直接的替代方法。
Azure 通信服务
接收传入呼叫
若要接受呼叫,必须先将应用程序配置为接收传入呼叫。
注册推送通知并处理传入的推送通知
通话客户端可以选择接收推送通知以接收传入呼叫。 本指南介绍如何为 Azure 通信服务呼叫设置 APNS。
设置 CallAgentListener
Azure 通信服务呼叫 SDK 包括 IncomingCallListener
。 在 CallAgent
实例上设置了 IncomingCallListener
。 此侦听器定义 onIncomingCall(IncomingCall incomingCall)
方法,在传入呼叫到达时触发。
callAgent.addOnIncomingCallListener((incomingCall) -> {
this.incomingCall = incomingCall;
// Get incoming call ID
incomingCall.getId();
// Get information about caller
incomingCall.getCallerInfo();
// CallEndReason is also a property of IncomingCall
CallEndReason callEndReason = incomingCall.getCallEndReason();
});
通过实现 CallAgentListener
并将其与 CallAgent
实例关联,应用程序即可接收传入呼叫。
接受传入呼叫
类引用
类名 | 说明 |
---|---|
IncomingCallListener | 传入呼叫的功能接口。 |
IncomingCall | 描述传入呼叫 |
视频流
启动和停止视频
Twilio
访问相机
使用 Twilio Video 时,向通话添加视频包括两个步骤:
- 访问相机
- 将视频轨道添加到
LocalVideoTrack
列表
// Access the camera
CameraCapturer cameraCapturer = new Camera2Capturer(context, frontCameraId);
// Create a video track
LocalVideoTrack videoTrack = LocalVideoTrack.create(context, true, cameraCapturer, LOCAL_VIDEO_TRACK_NAME);
// The VideoTrack is enabled by default. It can be enabled or disabled if necessary
videoTrack.enable(true|false);
添加 LocalVideoTrack
在连接时。 通过将 LocalVideoTrack
传递给通过 ConnectOptions
设置的 LocalVideoTrack
列表来完成添加本地视频轨道。
ConnectOptions connectOptions = new ConnectOptions.Builder(accessToken)
.roomName(roomName)
.videoTracks(localVideoTracks)
}
在现有聊天室中,本地参与者可以通过 publishTrack(LocalVideoTrack localVideoTrack)
方法发布本地视频轨道。
Azure 通信服务
访问相机
通过 DeviceManager
完成访问相机。 使用以下代码片段获取 DeviceManager
的实例。
DeviceManager deviceManager = callClient.getDeviceManager(getApplicationContext()).get();
deviceManager.getCameras();
创建 LocalVideoStream
DeviceManager
提供对允许创建 LocalVideoStream
实例的相机对象的访问权限。
VideoDeviceInfo camera = deviceManager.getCameras().get(0);
LocalVideoStream videoStream = new LocalVideoStream(camera, context);
添加 LocalVideoStream
在连接时。 LocalVideoStream
通过 StartCallOptions
的 OutgoingVideoOptions 添加到流中。
StartCallOptions options = new StartCallOptions();
LocalVideoStream[] videoStreams = new LocalVideoStream[1];
videoStreams[0] = videoStream;
VideoOptions videoOptions = new VideoOptions(videoStreams);
options.setVideoOptions(videoOptions);
在通话中。 通过调用 startVideo
方法来启动视频流,该方法接受 LocalVideoStream
作为其参数。
类引用
类名 | 说明 |
---|---|
DeviceManager | 促进与设备的交互 |
LocalVideoStream | 本地视频流信息 |
VideoDeviceInfo | 有关视频设备的信息 |
VideoOptions | 视频选项的属性包类 |
调用 | 描述呼叫 |
呈现视频
Twilio
若要使用 Twilio Video 呈现视频,可将符合 VideoSink
的对象添加到 VideoTrack
。 SDK 提供名为 VideoView
的预生成 VideoSink
,它将 android.view.View
作为子类。
Azure 通信服务
若要使用 Azure 通信服务呼叫呈现视频,请实例化 VideoStreamRenderer
并将 LocalVideoStream
或 RemoteVideoStream
作为参数传递给其构造函数。
VideoStreamRenderer previewRenderer = new VideoStreamRenderer(remoteStream, context);
VideoStreamRendererView preview = previewRenderer.createView(new CreateViewOptions(ScalingMode.FIT));
类引用
类名 | 说明 |
---|---|
ScalingMode | 本地和远程视频缩放模式的枚举 |
CreateViewOptions | 呈现视频时传递的选项 |
VideoStreamRenderer | 用于视频呈现的呈现器 |
VideoStreamRendererView | 用于呈现视频的视图 |
音频流
切换麦克风
Twilio
在 Twilio 视频 SDK 上,通过启用或禁用与麦克风关联的 LocalAudioTrack 来实现麦克风静音和取消静音。
Azure 通信服务
Call
对象提出用于静音和取消静音麦克风的方法。
call.muteOutgoingAudio(context).get();
call.unmuteOutgoingAudio(context).get();
// Mute incoming audio sets the call volume to 0. To mute or unmute the incoming audio, use the muteIncomingAudio and unmuteIncomingAudio asynchronous APIs
call.muteIncomingAudio(context).get();
call.unmuteIncomingAudio(context).get();
事件侦听器
Twilio Video 和 Azure 通信服务呼叫 SDK 提出各种侦听器来侦听呼叫事件。
聊天室/呼叫事件
Twilio
Room.Listener
允许客户端侦听与 Room
对象相关的事件。 Room.Listener
包括为以下事件触发的方法:
- 客户端已连接或无法连接到聊天室
- 客户端正在重新连接到聊天室或已重新连接
- 远程参与者已连接、断开连接、重新连接到聊天室
- 聊天室录制已开始或停止
- 主导发言人已改变
Azure 通信服务
Azure 通信服务呼叫 SDK 使 Call
对象能够合并各种 PropertyChangedListener
,从而在调用属性发生更改时通知它们。 应单独订阅每个事件类型。 若要了解有关事件处理的详细信息,请参阅事件教程。
可分配给呼叫的各种 PropertyChangedListeners
包含 Twilio Room.Listener
涵盖的某些事件,对以下事件采用方法:
- 呼叫状态已更改
- 远程参与者列表已更新
- 本地视频流已更新
- 静音状态已改变
本地参与者事件
Twilio
Twilio 具有 LocalParticipant.Listener
,允许客户端接收有关以下事件的更新:
- 本地参与者已发布或未能发布媒体轨道(音频、视频、数据)。
- 本地参与者的网络质量级别已更改。
Azure 通信服务
CallAgent
通过两个侦听器(CallsUpdatedListener
和 IncomingCallListener
)接收有关呼叫的更新。 以下事件分别触发这些侦听器:
- 调用已更新。 创建新的呼叫或现有呼叫断开连接。
- 收到传入呼叫。
远程参与者事件
这两个 SDK 都提供了用于处理来自远程参与者的更新的机制。
Twilio
RemoteParticipant.Listener
处理以下事件。
- 远程参与者已发布或取消发布媒体轨道(视频、音频、数据)
- 本地参与者已订阅、无法订阅或取消订阅远程媒体轨道(视频、音频、数据)
- 远程参与者网络质量已更改
- 远程参与者更改了轨道发布的优先级
- 远程参与者已打开/关闭其视频轨道
Azure 通信服务
将 PropertyChangedListener
添加到 RemoteParticipant
对象,以接收以下事件的更新:
- 远程参与者状态已更改
- 远程参与者已静音或未静音
- 远程参与者正在讲话
- 远程参与者显示名称已更改
- 远程参与者已添加或删除视频流
相机事件
Twilio
Twilio 提议 CameraCapturer.Listener
向客户端通知与相机相关的以下事件:
- 相机源已切换
- 相机源失败
- 第一帧已从相机捕获
Azure 通信服务
Azure 通信服务呼叫 SDK 提出 VideoDevicesUpdatedListener
。 它定义在当前 DeviceManager
上添加或删除视频设备时通知客户端的单个方法。
类引用
类名 | 说明 |
---|---|
PropertyChangedListener | 告知库呼叫状态已更改 |
CallsUpdatedListener | 在呼叫更新时告知库 |
IncomingCallListener | 向库告知传入呼叫 |
VideoDevicesUpdatedListener | 告知库已在当前库中添加或删除新视频设备 |
结束呼叫
Twilio
结束呼叫(从聊天室断开连接)通过 room.disconnect()
方法完成。
Azure 通信服务
挂起呼叫通过 Call
对象的 hangUp
方法完成。
call.hangUp().get();
// Set the 'forEveryone' property to true to end call for all participants
HangUpOptions options = new HangUpOptions();
options.setForEveryone(true);
call.hangUp(options).get();
类引用
类名 | 说明 |
---|---|
HangUp 选项 | 用于挂断呼叫的属性包类 |
Azure 通信服务呼叫的主要功能
主导发言人
若要注册有关主导发言人的更新,请实例化 Call
对象中的 DominantSpeakersCallFeature
。 在该教程中了解有关主导发言人配置的详细信息。
DominantSpeakersCallFeature dominantSpeakersFeature = call.feature(Features.DOMINANT_SPEAKERS);
// Subscribe to the dominant speaker change event to receive updates about the dominant speaker.
dominantSpeakersFeature.addOnDominantSpeakersChangedListener(event -> {
dominantSpeakersFeature.getDominantSpeakersInfo();
});
媒体质量统计信息
为了帮助你了解通话期间的媒体质量,Azure 通信服务 SDK 提供媒体质量统计信息。 使用它可检查传入和传出呼叫指标的低级别音频、视频和屏幕共享质量指标。有关详细信息,请参阅媒体质量统计信息指南。
面向用户的诊断
Azure 通信服务呼叫 SDK 提供一项称为“面向用户的诊断 (UFD)”的功能,可让客户端仔细检查呼叫的各种属性,以确定潜在问题。 若要了解有关面向用户的诊断的详细信息,请参阅面向用户的诊断。
重要
以下列表中所述的 Azure 通信服务呼叫 SDK 的某些功能在 Twilio Video SDK 中没有等效项。
举手
举手功能允许呼叫参与者举手或取消举手。
视频背景
添加视频背景 允许用户模糊视频流中的背景。
视频聚焦
聚焦 允许用户固定和取消固定视频。
反馈
https://aka.ms/ContentUserFeedback。
即将发布:在整个 2024 年,我们将逐步淘汰作为内容反馈机制的“GitHub 问题”,并将其取代为新的反馈系统。 有关详细信息,请参阅:提交和查看相关反馈