你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
使用通信服务呼叫 SDK 管理 Teams 用户的呼叫
了解如何使用 Azure 通信服务 SDK 管理通话。 我们将了解如何发起通话,如何管理其参与者和属性。
先决条件
- 具有活动订阅的 Azure 帐户。 免费创建帐户。
- 已部署的通信服务资源。 创建通信服务资源。
- 用于启用呼叫客户端的
User Access Token
。 详细了解如何获取User Access Token
- 可选:完成开始向应用程序添加视频呼叫功能快速入门
安装 SDK
使用 npm install
命令安装适用于 JavaScript 的 Azure 通信服务通话 SDK 和通用 SDK。
npm install @azure/communication-common --save
npm install @azure/communication-calling --save
初始化所需的对象
创建实例 CallClient
以启动呼叫堆栈。 可以使用实例 AzureLogger
和方法 setLogLevel
来配置呼叫 SDK 的日志记录。 可以使用方法 getDeviceManager
访问操作系统的 deviceManager
。
然后使用方法 createTeamsCallAgent
异步创建一个 TeamsCallAgent
实例,该实例将管理 Teams 用户的传入和传出呼叫。 该方法采用 CommunicationTokenCredential
作为表示 Teams 用户访问令牌的参数。
const { CallClient } = require('@azure/communication-calling');
const { AzureCommunicationTokenCredential} = require('@azure/communication-common');
const { AzureLogger, setLogLevel } = require("@azure/logger");
// Set the logger's log level
setLogLevel('verbose');
// Redirect log output to wherever desired. To console, file, buffer, REST API, etc...
AzureLogger.log = (...args) => {
console.log(...args); // Redirect log output to console
};
const userToken = '<USER_TOKEN>';
callClient = new CallClient();
const tokenCredential = new AzureCommunicationTokenCredential(userToken);
const teamsCallAgent = await callClient.createTeamsCallAgent(tokenCredential);
const deviceManager = await callClient.getDeviceManager();
拨打电话
启动具有 teamsCallAgent
上 startCall
API 的同步一对一或组呼叫。 可以提供 MicrosoftTeamsUserIdentifier
或 PhoneNumberIdentifier
作为参数来定义呼叫的目标。 此方法返回可以订阅通话事件的 TeamsCall
实例。
注意
在调用 startCall
方法时,启动与 teamsCallAgent
的组呼叫需要聊天的 threadId
。 创建的 TeamsCall
实例具有捕获此线程的属性 threadId
。 通信服务呼叫 SDK 不会使参与者保持聊天和呼叫名单同步。Microsft 鼓励开发人员保持名单同步,以获得最佳用户体验。 了解如何管理聊天线程。
启动一对一 IP 语音 (VoIP) 呼叫 Teams 用户:
const userCallee = { microsoftTeamsUserId: '<MICROSOFT_TEAMS_USER_ID>' };
const oneToOneCall = teamsCallAgent.startCall(userCallee);
启动一对一电话呼叫 E.164 电话号码:
const phoneCallee = { phoneNumber: '<PHONE_NUMBER_E164_FORMAT>' }
const oneToOneCall = teamsCallAgent.startCall(phoneCallee );
使用 IP 语音 (VoIP) 和电话号码启动对 Teams 用户的组呼叫:
const userCallee = { microsoftTeamsUserId: '<MICROSOFT_TEAMS_USER_ID>' }
const phoneCallee = { phoneNumber: '<PHONE_NUMBER_E164_FORMAT>'};
const groupCall = teamsCallAgent.startCall([userCallee, phoneCallee], { threadId: '<THREAD_ID>' });
加入通话
加入 Teams 会议
可以使用 teamsCallAgent
实例上的方法 join
加入 Teams 会议。 Teams 用户可以通过提供 TeamsMeetingLinkLocator
、TeamsMeetingCoordinatesLocator
或 TeamsMeetingIdLocator
来加入 Teams 会议。
使用会议 URL 加入 Teams 会议:
const meetingCall = teamsCallAgent.join({ meetingLink: '<MEETING_LINK>' });
结合使用线程 ID、组织者 ID、租户 ID 和消息 ID 加入 Teams 会议:
const meetingCall = teamsCallAgent.join({ threadId: '<THREAD_ID>', organizerId: '<ORGANIZER_ID>', tenantId: '<TENANT_ID>', messageId: '<MESSAGE_ID>' });
使用会议代码和密码加入 Teams 会议:
const meetingCall = teamsCallAgent.join({ meetingId: '<MEETING_CODE>', passcode: '<PASSCODE>'});
使用会议 ID 和密码加入 Teams 会议:
开发人员可以通过多种方式将参与者连接到 Teams 会议。 一种方式是使用会议 ID 和密码,这样用户能够从设备或应用程序加入他们受邀加入的 Teams 会议。 始终需要提供会议 ID 和密码才能加入会议。 密码区分大小写。
会议 ID 和密码的格式:
- 会议 ID:12 位数字。
- 密码:6 个字符
需要多久刷新一次会议 ID 和密码?
- 会议 ID 和密码一经创建,就不会更改。 开发人员无需刷新其中任何一项。
- Teams 会议组织者无法重新生成会议 ID 和密码。
用户通过 URL 或会议 ID 和密码加入的 Teams 会议体验有什么区别吗?
- 没有,如果参与者使用 Teams 会议 URL 或会议 ID 和密码加入 Teams 会议,那么他们的体验是相同的。
开发人员应如何存储和管理密码?
- 会议 ID 和密码是加入会议的坐标。 开发人员应将密码视为机密,对其进行加密,如果要存储,则应确保其处于访问受控制的环境中。
- 如果公开了坐标,任何人都可以加入会议,会破坏每个参会者的体验。
如何获取会议 ID 和密码?
- 图形 API:使用图形 API 检索有关
onlineMeeting
资源的信息并检查属性joinMeetingIdSettings
中的对象。 - Teams:在 Teams 应用程序中,转到“
Calendar
”应用并打开会议的详细信息。 在线会议的会议定义中有会议 ID 和密码。 - Outlook:可以在日历事件或电子邮件会议邀请中找到会议 ID 和密码。
- 开发人员无法通过调用 SDK 检索会议 ID 和密码,也无法从详细控制台日志中检索它。
- 图形 API:使用图形 API 检索有关
如何验证会议 ID 和密码是否正确?
- 可以通过以下方式完成 MeetingId 和密码验证:https://www.microsoft.com/en-us/microsoft-teams/join-a-meeting。
接听 Teams 来电
可以订阅 incomingCall
实例上的 teamsCallAgent
事件,以向 Teams 用户注册传入呼叫。 该事件具有一个有 TeamsIncomingCall
实例的 teamsIncomingCall
属性,允许你 accept
或 reject
传入呼叫。
const incomingCallHandler = async (args: { teamsIncomingCall: TeamsIncomingCall }) => {
const incomingCall = args.teamsIncomingCall;
// Get Teams incoming call ID
const incomingCallId = incomingCall.id;
// Get information about this Call. This API is provided as a preview for developers
// and may change based on feedback that we receive. Do not use this API in a production environment.
// To use this API please use 'beta' release of Azure Communication Services Calling Web SDK
const callInfo = incomingCall.info;
// Get information about caller
const callerInfo = incomingCall.callerInfo
// Accept the call
const teamsCall = 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;
};
teamsCallAgent.on('incomingCall', incomingCallHandler);
启用和禁用视频
可以从 TeamsCall
实例中的 localVideoStreams
属性获取本地视频流集合。 如果启用,则集合包含屏幕共享流和相机视频源。 可以通过检查属性 TeamsCall
来获取远程参与者的视频流。remoteParticipants
其中,每个参与者都有属性 videoStreams
中的视频流集合。
静音和取消静音
可以在 TeamsCall
实例上使用 mute
和 unmute
异步 API,在本地对 Teams 用户进行静音或取消静音操作。 本地静音可防止把音频发送给其他参与者。
//mute local device
await call.mute();
//unmute local device
await call.unmute();
将其他参与者设为静音
若要将所有其他参与者静音或将特定参与者静音,可以对通话使用异步 API muteAllRemoteParticipants
,对远程参与者使用 mute
:
//mute all participants except yourself
await call.muteAllRemoteParticipants();
//mute a specific participant
await call.remoteParticipants[0].mute();
注意
此 API 以预览状态提供给开发者,可能根据我们收到的反馈更改。 请勿在生产环境中使用此 API。 若要使用此 API,请使用 Azure 通信服务呼叫 Web SDK 的 beta 版本。
管理远程参与者
其他呼叫参与者可在属性 remoteParticipants
下的 TeamsCall
实例中使用。 这是 RemoteParticipant
对象的集合。 你可以列出、添加和删除通话中的其他参与者。
注意
添加参与者方法需要聊天的 threadId
。 通信服务呼叫 SDK 不会使参与者保持聊天和呼叫名单同步。Microsft 鼓励开发人员保持名单同步,以获得最佳用户体验。 了解如何管理聊天线程。
可以通过对对象 TeamsCall
调用方法 addParticipant
向 Teams 呼叫或 Teams 会议添加新的 Teams 用户或电话号码。 该方法接受标识符 MicrosoftTeamsUserIdentifier
或 PhoneNumberIdentifier
作为输入,同步返回 TeamsCall
实例上的 RemoteParticipant
实例并触发事件 remoteParticipantsUpdated
。
可以通过异步调用 TeamsCall
实例上的 removeParticipant
方法,从 Teams 呼叫或 Teams 会议中删除参与者。 该方法接受标识符 MicrosoftTeamsUserIdentifier
或 PhoneNumberIdentifier
作为输入。 从 remoteParticipants
集合中删除 RemoteParticipant
时,会解析该方法,并触发 TeamsCall
实例上的 remoteParticipantsUpdated
事件。
列出其他呼叫参与者:
const participants = call.remoteParticipants; // [remoteParticipant, remoteParticipant....]
将 Teams 用户和电话号码添加到 Teams 呼叫或 Teams 会议:
const teamsUser = { microsoftTeamsUserId: '<MICROSOFT_TEAMS_USER_ID>' };
const phoneUser = { phoneNumber: '<PHONE_NUMBER_E164_FORMAT>' }
const remoteParticipant = call.addParticipant(teamsUser , { threadId: '<THREAD_ID>' });
const remoteParticipant2 = call.addParticipant(phoneUser , { threadId: '<THREAD_ID>' });
将 Teams 用户和电话号码从 Teams 呼叫或 Teams 会议中删除:
const teamsUser = { microsoftTeamsUserId: '<MICROSOFT_TEAMS_USER_ID>' };
const phoneUser = { phoneNumber: '<PHONE_NUMBER_E164_FORMAT>' }
await call.removeParticipant(teamsUser);
await call.removeParticipant(phoneUser);
远程参与者
远程参与者表示已连接到正在进行的 Teams 呼叫或 Teams 会议的终结点。 类 remoteParticipant
具有以下一组属性和集合:
identifier
:返回以下标识符之一:CommunicationUserIdentifier
、MicrosoftTeamsUserIdentifier
、PhoneNumberIdentifier
或UnknownIdentifier
。
const identifier = remoteParticipant.identifier;
state
:返回的string
表示远程参与者状态。 状态可以是下列值之一:
状态值 | When | 说明 |
---|---|---|
Idle |
初始状态 | 这是参与者的第一种状态 |
Connecting |
Idle 之后 |
参与者正在连接到通话时的过渡状态。 |
Ringing |
Connecting 之后 |
参与者收到 incomingCall 通知或 Teams 客户端响铃 |
Connected |
Ringing 、Connecting 、EarlyMedia 或 InLobby 之后 |
参与者接受了呼叫邀请或加入了呼叫。 媒体流向参与者。 |
Hold |
Connected 之后 |
通话中的参与者处于保持状态。 |
EarlyMedia |
Connecting 之后 |
在参与者连接到呼叫之前播放媒体 |
InLobby |
Ringing 、Connecting 、或 EarlyMedia 之后 |
参与者位于 Teams 会议大厅中。 |
Disconnected |
最终状态 | 参与者已断开通话连接。 如果远程参与者断开了其网络连接,则两分钟后其状态将变为 Disconnected 。 |
一对一呼叫或组呼叫中远程参与者的状态:
Teams 会议中远程参与者的状态:
const state = remoteParticipant.state;
callEndReason
:返回一个对象,其中包含有关呼叫结束原因的其他信息。 属性code
返回与原因关联的数字,subCode
返回与代码和原因关联的数字。 有关错误代码的详细信息,请参阅对通话结束响应代码进行故障排除。
const callEndReason = remoteParticipant.callEndReason;
const callEndReasonCode = callEndReason.code
const callEndReasonSubCode = callEndReason.subCode
isMuted
:返回的Boolean
值表示本地静音状态。
const isMuted = remoteParticipant.isMuted;
isSpeaking
:返回Boolean
值,表示发送的非空音频的状态。
const isSpeaking = remoteParticipant.isSpeaking;
videoStreams
:返回参与者发送的RemoteVideoStream
对象集合。
const videoStreams = remoteParticipant.videoStreams; // [RemoteVideoStream, ...]
displayName
:返回的string
表示显示名称。 通信服务通话 SDK 不会为 Teams 用户设置此值。
const displayName = remoteParticipant.displayName;
调用
id
:返回表示唯一调用标识符的字符串。
const callId = call.id;
• info
:返回有关呼叫的信息:
注意
此 API 以预览状态提供给开发者,可能根据我们收到的反馈更改。 请勿在生产环境中使用此 API。 若要使用此 API,请使用 Azure 通信服务呼叫 Web SDK 的 beta 版本
• info
:返回包含呼叫有关信息的对象。 属性 threadId
是表示 Teams 客户端中显示的聊天线程 ID 的字符串。
const callInfo = call.info;
const threadId = call.info.threadId;
• remoteParticipants
:返回的 remoteParticipant
对象集合表示 Teams 呼叫或 Teams 会议中其他参与者。
const remoteParticipants = call.remoteParticipants;
• callerInfo
:返回传入呼叫的 CallerInfo
对象。 属性 identifier
可以是下列的对象 CommunicationUserIdentifier
、MicrosoftTeamsUserIdentifier
、PhoneNumberIdentifier
或 UnknownIdentifier
之一。 属性 displayName
是一个字符串,表示在设置时要显示的名称。
const callerIdentity = call.callerInfo.identifier;
const callerIdentity = call.callerInfo.displayName;
• state
:返回表示呼叫状态的字符串。 该属性可以具有下列值之一:
状态值 | When | 说明 |
---|---|---|
None |
初始状态 | 呼叫的初始状态。 |
Connecting |
None 之后 |
发出、加入或接受 Teams 呼叫或 Teams 会议时的状态。 |
Ringing |
Connecting 之后 |
远程参与者收到 incomingCall 事件或 Teams 客户端响铃。 |
EarlyMedia |
Ringing 、或 Connecting 之后 |
在呼叫连接之前播放媒体。 |
Connected |
Ringing 、EarlyMedia 、InLobby 、LocalHold 和 RemoteHold 之后 |
呼叫已连接。 本地终结点与远程参与者之间有媒体流动。 |
LocalHold |
Connected 之后 |
通话被本地参与者暂停。 本地终结点与远程参与者之间没有媒体流动。 |
RemoteHold |
Connected 之后 |
通话被远程参与者暂停。 本地终结点与远程参与者之间没有媒体流动。 |
InLobby |
Ringing 、或 Connecting 之后 |
远程参与者位于 Teams 会议大厅中。 本地终结点与远程参与者之间没有媒体流动。 |
Disconnecting |
在任何状态之后 | 在通话进入 Disconnected 状态之前的过渡状态。 |
Disconnected |
最终状态 | 呼叫的最终状态。 如果网络连接断开,则两分钟后状态将变为 Disconnected 。 |
一对一或组呼叫的状态:
Teams 会议的状态:
const callState = call.state;
• callEndReason
:返回对象 CallEndReason
,其中包含有关呼叫结束的其他信息。 属性 code
返回与原因关联的数字,subCode
返回与代码和原因关联的数字。 有关错误代码的详细信息,请参阅对通话结束响应代码进行故障排除。
const callEndReason = call.callEndReason;
const callEndReasonCode = callEndReason.code
const callEndReasonSubCode = callEndReason.subCode
• direction
:返回一个表示呼叫方向的 string
。 该属性可以具有下列值之一:“Incoming”或 Outgoing
。
const isIncoming = call.direction == 'Incoming';
const isOutgoing = call.direction == 'Outgoing';
• isMuted
:返回的 Boolean
值表示本地静音状态。
const muted = call.isMuted;
• isScreenSharingOn
:如果向其他参与者发送屏幕共享流,则 Boolean
值返回为 true。
const isScreenSharingOn = call.isScreenSharingOn;
• localVideoStreams
:返回 LocalVideoStream
对象集合,表示要发送到远程参与者的视频流。
const localVideoStreams = call.localVideoStreams;
管理聊天线程
重要
可选的聊天 ID 仅在适用于 JavaScript 的通话 SDK 1.29.1 或更高版本中可用。 如果使用的是更早的版本,请务必以手动方式提供唯一的聊天 ID。
要拨打群组电话以及将参与者添加到现有通话,可以选择性地提供聊天 ID。 关联的聊天和通话具有单独的参与者列表。 在将参与者添加到通话之前,请将用户添加到聊天中,以提供最佳用户体验并满足信息屏障要求。 如果设置了信息屏障,在不将用户添加到聊天的情况下将用户添加到通话可能会导致异常。
考虑以下场景:Alice 给 Bob 拨打电话,然后 Alice 添加 Charlie,3 分钟后,Alice 将 Charlie 从通话中删除。
- 在 Alice、Bob 和 Charlie 之间创建一个聊天线程。 请保留聊天
threadId
供以后使用。 - Alice 在
TeamsCallAgent
实例上使用startCall
方法呼叫 Bob 和 Charlie。 - 使用聊天图形 API 添加成员,将 Dan 添加到具有
threadId
的聊天线程 - Alice 使用
call
上的addParticipant
方法将 Dan 添加到通话并指定threadId
- Alice 使用
call
上的removeParticipant
方法从通话中删除 Dan 并指定threadId
- 使用聊天图形 API 删除成员,从具有
threadId
的聊天线程中删除 Dan
如果 Teams 用户停止通话记录,则记录将放入与线程关联的聊天中。 提供的聊天 ID 会影响 Teams 用户在 Teams 客户端中的体验。
对聊天 ID 的管理建议:
- 通过添加另一个通话参与者来升级 1:1 电话呼叫:
- 通过方法
addParticipant
,可以提供可选参数聊天 ID。 如果未提供该参数,则会创建新的群组聊天,并将所有参与者添加到通话和聊天参与者列表中。 如果提供该参数,则 Teams 用户可以在 Teams 应用中查看与此群组聊天关联的正在进行的通话。 可以通过图形 API 创建新的群组聊天。addParticipant(participant: MicrosoftTeamsUserIdentifier | PhoneNumberIdentifier | MicrosoftTeamsAppIdentifier | UnknownIdentifier)
- 通过方法
- 与单个 Microsoft 365 用户和多个通话参与者发起群组通话:
- 使用方法
startCall
API,可以发起与多个参与者的群组通话,并且可以选择提供聊天 ID。 如果未提供该参数,则会创建新的群组聊天,并将所有 Microsoft 365 参与者添加到通话和聊天参与者列表中。 如果提供该参数,则 Teams 用户可以在 Teams 应用中查看与此群组聊天关联的正在进行的通话。 可以通过图形 API 创建新的群组聊天。startCall(MicrosoftTeamsUserIdentifier | PhoneNumberIdentifier | MicrosoftTeamsAppIdentifier | UnknownIdentifier)[])
- 使用图形 API 获取身为参与者的 Teams 用户的现有聊天 ID,或者与参与者建立新的群组聊天:Teams 用户 ID 和“00000000-0000-0000-0000-000000000000”。
- 使用方法
- 与 2 名以上的 Microsoft 365 用户发起群组通话:
- (可选方式)使用 ACS 通话 SDK 与 2 个以上的 Microsoft 365 用户进行群组通话时,SDK 默认会自动创建线程。
startCall(MicrosoftTeamsUserIdentifier | PhoneNumberIdentifier | MicrosoftTeamsAppIdentifier | UnknownIdentifier)[])
- 如果需要,开发人员可以提供唯一的聊天 ID 来发起群组通话或添加参与者。 在这种情况下,ACS 通话 SDK 将使用给定的聊天 ID 创建群组通话。 为 Teams 用户创建聊天线程,此线程将关联到 Teams 应用中用户的群组通话。 这样,他们便可以在通话期间聊天。 聊天线程管理可以通过图形 API 进行
- (可选方式)使用 ACS 通话 SDK 与 2 个以上的 Microsoft 365 用户进行群组通话时,SDK 默认会自动创建线程。