共用方式為


使用通訊服務通話 SDK 來管理 Teams 使用者的通話

了解如何使用 Azure 通訊服務 SDK 來管理通話。 我們將了解如何撥打電話,如何管理其參與者和屬性。

必要條件

安裝 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,撥打同步一對一或群組通話。 您可以提供 MicrosoftTeamsUserIdentifierPhoneNumberIdentifier 作為參數,藉此定義通話的目標。 方法會傳回 TeamsCall 執行個體,可讓您訂閱通話事件。

注意

當呼叫 startCall 方法時,使用 teamsCallAgent 來撥打群組通話需要聊天的 threadId。 已建立的 TeamsCall 執行個體,具有可擷取此對話的屬性 threadId。 通訊服務通話 SDK 不會將聊天和通話名冊中的參與者保持同步。Microsft 鼓勵開發人員同步名冊內容,以提供最佳使用者體驗。 了解如何管理聊天對話

向 Teams 使用者撥打一對一的 IP 語音傳輸 (VoIP) 通話:

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 使用者可以藉由提供 TeamsMeetingLinkLocatorTeamsMeetingCoordinatesLocatorTeamsMeetingIdLocator 來加入 Teams 會議。

使用會議 URL 加入 Teams 會議:

const meetingCall = teamsCallAgent.join({ meetingLink: '<MEETING_LINK>' });

使用對話識別碼、召集人識別碼、租用戶識別碼,以及訊息識別碼的組合來加入 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>'});

使用會議識別碼和密碼加入 Teams 會議:

開發人員可以使用多種方式加入 Teams 會議。 其中之一是會議識別碼和密碼,可讓人員從裝置或應用程式加入其受邀參加的 Teams 會議。 一律需同時提供會議識別碼和密碼,才能加入會議。 密碼區分大小寫。

  • 會議識別碼和密碼的格式為:

    • 會議識別碼:12 位數字。
    • 密碼:6 個字元
  • 會議識別碼和密碼多久需更新一次?

    • 會議識別碼和密碼在建立後即不會變更。 兩者皆無需由開發人員更新及變更。
    • Teams 會議召集人無法重新產生會議識別碼和密碼。
  • 使用者透過 URL 或會議識別碼和密碼加入 Teams 會議,在體驗上是否有任何差異?

    • 否。 使用者無論透過 Teams 會議 URL 還是會議識別碼和密碼加入 Teams 會議,使用者體驗均相同。
  • 開發人員應如何儲存及管理密碼?

    • 會議識別碼和密碼是加入會議的座標。 開發人員應將其視為秘密而予以加密,且若要儲存應施加存取控制。
    • 如果公開座標,任何人都可以加入會議,這會破壞每個與會者的體驗。
  • 如何取得會議識別碼和密碼?

    1. 圖形 API:使用圖形 API 擷取 onlineMeeting 資源的相關資訊,並檢查屬性 joinMeetingIdSettings 中的物件。
    2. Teams:在您的 Teams 應用程式中,移至 Calendar 應用程式並開啟會議的詳細資料。 線上會議在會議定義中具有會議識別碼和密碼。
    3. Outlook:您可以在行事曆活動或電子郵件會議邀請中找到會議識別碼和密碼。
    4. 開發人員無法透過通話 SDK 來擷取會議識別碼和密碼,或是從詳細資訊控制台記錄擷取。
  • 如何確認會議識別碼和密碼是否正確?

接收 Teams 來電

您可以訂閱 teamsCallAgent 執行個體上的 incomingCall 事件,來向 Teams 使用者註冊來電。 事件具有 teamsIncomingCall 屬性以及 TeamsIncomingCall 執行個體,可讓您 acceptreject 來電。

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 執行個體上使用 muteunmute 非同步 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 會議。 方法接受識別碼 MicrosoftTeamsUserIdentifierPhoneNumberIdentifier 作為輸入,並以同步方式傳回 RemoteParticipant 的執行個體,且觸發 TeamsCall 執行個體的 remoteParticipantsUpdated

您可以透過非同步的方式叫用 TeamsCall 執行個體上的 removeParticipant 方法,將參與者從 Teams 通話或 Teams 會議中移除。 方法接受識別碼 MicrosoftTeamsUserIdentifierPhoneNumberIdentifier 作為輸入。 當 RemoteParticipantremoteParticipants 集合移除時,系統會解析方法,並觸發 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:傳回下列其中一個識別碼:CommunicationUserIdentifierMicrosoftTeamsUserIdentifierPhoneNumberIdentifierUnknownIdentifier
const identifier = remoteParticipant.identifier;
  • state:傳回 string,代表遠端參與者的狀態。 狀態可以具有下列其中一個值:
狀態值 時機 描述
Idle 初始狀態 這是參與者的第一個狀態
Connecting Idle 之後 參與者連線至通話時的過渡狀態。
Ringing Connecting 之後 參與者收到 incomingCall 通知,或 Teams 用戶端發出鈴聲
Connected RingingConnectingEarlyMediaInLobby 之後 參與者已接受通話邀請或加入通話。 媒體會傳輸給參與者。
Hold Connected 之後 保留通話中的參與者。
EarlyMedia Connecting 之後 媒體會在參與者連線到通話之前播放
InLobby RingingConnectingEarlyMedia 之後 參與者位於 Teams 會議大廳。
Disconnected 最終狀態 參與者已中斷通話連線。 如果遠端參與者失去其網路連線能力,其狀態將在兩分鐘後變更為 Disconnected

一對一或群組通話中的遠端參與者狀態:Diagram of remote participant's call states for one-to-one or group calls.

Teams 會議中的遠端參與者狀態:Diagram of remote participant's call states for Teams meetings.

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 用戶端中顯示的聊天對話識別碼。

const callInfo = call.info;
const threadId = call.info.threadId;

remoteParticipants:傳回 remoteParticipant 物件集合,代表 Teams 通話或 Teams 會議中的其他參與者。

const remoteParticipants = call.remoteParticipants;

callerInfo:如果這是來電,則會傳回 CallerInfo 物件。 屬性 identifier 可以是下列其中一個物件 CommunicationUserIdentifierMicrosoftTeamsUserIdentifierPhoneNumberIdentifierUnknownIdentifier。 屬性 displayName 是字串,代表顯示名稱 (若經過設定)。

const callerIdentity = call.callerInfo.identifier;
const callerIdentity = call.callerInfo.displayName;

state:傳回字串,該字串代表通話狀態。 屬性可以有下列其中一個值:

狀態值 時機 描述
None 初始狀態 通話的初始狀態。
Connecting None 之後 當使用者建立、加入或接受 Teams 通話或 Teams 會議時的狀態。
Ringing Connecting 之後 遠端參與者收到 incomingCall 事件,或 Teams 用戶端發出鈴聲。
EarlyMedia RingingConnecting 之後 媒體會在通話連線之前播放。
Connected RingingEarlyMediaInLobbyLocalHoldRemoteHold 通話已連線。 媒體在本機端點與遠端參與者之間傳輸。
LocalHold Connected 之後 本機參與者已保留通話。 本機端點與遠端參與者之間沒有媒體傳輸。
RemoteHold Connected 之後 遠端參與者已保留通話。 本機端點與遠端參與者之間沒有媒體傳輸。
InLobby RingingConnecting 之後 遠端參與者位於 Teams 會議大廳。 本機端點與遠端參與者之間沒有媒體傳輸。
Disconnecting 在任何狀態之後 通話進入 Disconnected 狀態之前的過渡狀態。
Disconnected 最終狀態 通話的最終狀態。 如果網路連線中斷,狀態會在兩分鐘後變更為 Disconnected

一對一或群組通話的狀態:Diagram with call's states for one-to-one or group calls.

Teams 會議的狀態:Diagram with call's states for Teams meetings.

const callState = call.state;

callEndReason:傳回 CallEndReason 物件,其中包含通話結束的其他資訊。 屬性 code 會傳回與原因相關聯的數字,且 subCode 會傳回與程式碼和原因相關聯的數字。 如需更多詳細資訊,請參閱錯誤程式碼

const callEndReason = call.callEndReason;
const callEndReasonCode = callEndReason.code
const callEndReasonSubCode = callEndReason.subCode

direction:傳回 string,代表通話的方向。 屬性可以有下列其中一個值:「連入」或 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;

管理聊天對話

若要建立群組通話,或將參與者新增至現有通話,必須提供聊天識別碼。 相關聯的聊天和通話有個別的參與者清單。 將參與者新增至通話之前,請將使用者新增至聊天,以提供最佳使用者體驗,並滿足資訊屏障需求。 若未將使用者新增至聊天就將使用者新增至通話,在設定了資訊屏障時,可能會引發例外狀況。

請參閱下列案例,其中 Alice 撥打電話給 Bob,接著 Alice 會新增 Charlie,3 分鐘之後,Alice 會從通話中移除 Charlie。

  1. 建立 Alice、Bob 和 Charlie 之間的聊天對話。 請保留聊天的 threadId,以供稍後使用。
  2. Alice 使用 TeamsCallAgent 執行個體上的 startCall 方法,來撥打電話給 Bob 和 Charlie。
  3. 若要透過 threadId 來將 Dan 新增至聊天對話,請使用聊天圖形 API 以新增成員
  4. Alice 使用 call 上的 addParticipant 方法來將 Dan 新增至通話,並指定 threadId
  5. Alice 使用 call 上的 removeParticipant 方法來將 Dan 從通話中移除,並指定 threadId
  6. 若要透過 threadId 來將 Dan 從聊天對話中移除,請使用聊天圖形 API 以移除成員

如果 Teams 使用者停止通話錄音,錄製內容會存入與對話相關聯的聊天中。 提供的聊天識別碼會影響 Teams 用戶端中 Teams 使用者的體驗。

管理聊天識別碼的建議:

  • 新增另一位電話參與者,來增加 1:1 電話通話對象:使用圖形 API 來取得現有聊天識別碼,其中僅限作為參與者的 Teams 使用者;或者和參與者建立新的群組聊天:Teams 使用者識別碼和「00000000-0000-0000-0000-000000000000」
  • 與單一 Teams 使用者和多個電話參與者進行群組通話:使用圖形 API 取得現有聊天識別碼;或者和參與者建立新的群組聊天:Teams 使用者識別碼和「00000000-0000-0000-0000-000000000000」
  • 與超過 2 位 Teams 使用者進行群組通話:使用圖形 API 來取得現有聊天識別碼;或者與 Teams 使用者建立群組聊天