介绍
在 Azure 通信服务 (ACS) 会议室通话期间,可以使用通话 SDK 或通话自动化 SDK 或两者来管理通话。 在会议室通话中,可以使用分配给参与者的角色和会议室中配置的属性来控制通话中操作。 参与者的角色控制按参与者允许使用的功能,而会议室属性则适用于这个会议室的通话。
通话 SDK
通话 SDK 是一个客户端通话库,它支持会议室通话中的参与者执行多个通话中操作,例如屏幕共享、打开/关闭视频、静音/取消静音等。 有关功能的完整列表,请参阅通话 SDK 概述。
你可以根据分配给通话参与者的角色控制功能。 例如,只有演示者才能进行屏幕共享。 有关参与者角色和权限,请参阅会议室概念。
通话自动化 SDK
通话自动化 SDK 是一个服务器端库,它支持管理员在中央和控制环境中管理正在进行的会议室通话。 与通话 SDK 不同,通话自动化 SDK 操作与角色无关。 因此,通话管理员可以代表会议室通话参与者执行多个通话中操作。
以下列表描述了会议室通话中可用的常见通话中操作。
连接到会议室通话
在执行任何通话中操作之前,通话自动化必须连接到现有会议室通话。 CallConnected
或 ConnectFailed
事件是使用回叫机制引发的,分别用于指示连接操作是已成功还是失败。
Uri callbackUri = new Uri("https://<myendpoint>/Events"); //the callback endpoint where you want to receive subsequent events
CallLocator roomCallLocator = new RoomCallLocator("<RoomId>");
ConnectCallResult response = await client.ConnectAsync(roomCallLocator, callbackUri);
String callbackUri = "https://<myendpoint>/Events"; //the callback endpoint where you want to receive subsequent events
CallLocator roomCallLocator = new RoomCallLocator("<RoomId>");
ConnectCallResult response = client.connectCall(roomCallLocator, callbackUri).block();
const roomCallLocator = { kind: "roomCallLocator", id: "<RoomId>" };
const callbackUri = "https://<myendpoint>/Events"; // the callback endpoint where you want to receive subsequent events
const response = await client.connectCall(roomCallLocator, callbackUri);
callback_uri = "https://<myendpoint>/Events" # the callback endpoint where you want to receive subsequent events
room_call_locator = RoomCallLocator("<room_id>")
call_connection_properties = client.connect_call(call_locator=room_call_locator, callback_url=callback_uri)
成功连接到会议室通话后,将会通过回叫 URI 来通知 CallConnect
事件。 可根据需要使用 callConnectionId
来检索会议室通话上的通话连接。 以下示例代码片段使用 callConnectionId
来演示此函数。
添加 PSTN 参与者
使用通话自动化,可以拨出到 PSTN 号码,并将参与者添加到会议室通话中。 但必须设置一个会议室才能启用 PSTN 拨出选项(将 EnabledPSTNDialout
设置为 true
),并且 Azure 通信服务资源必须预配有效的电话号码。
有关详细信息,请参阅会议室快速入门。
var callerIdNumber = new PhoneNumberIdentifier("+16044561234"); // This is the ACS-provisioned phone number for the caller
var callThisPerson = new CallInvite(new PhoneNumberIdentifier("+16041234567"), callerIdNumber); // The target phone number to dial out to
CreateCallResult response = await client.GetCallConnection(callConnectionId).AddParticipantAsync(callThisPerson);
PhoneNumberIdentifier callerIdNumber = new PhoneNumberIdentifier("+16044561234"); // This is the ACS-provisioned phone number for the caller
CallInvite callInvite = new CallInvite(new PhoneNumberIdentifier("+16041234567"), callerIdNumber); // The phone number participant to dial out to
AddParticipantOptions addParticipantOptions = new AddParticipantOptions(callInvite);
Response<AddParticipantResult> addParticipantResultResponse = client.getCallConnectionAsync(callConnectionId)
.addParticipantWithResponse(addParticipantOptions).block();
const callInvite = {
targetParticipant: { phoneNumber: "+18008008800" }, // The phone number participant to dial out to
sourceCallIdNumber: { phoneNumber: "+18888888888" } // This is the ACS-provisioned phone number for the caller
};
const response = await client.getCallConnection(callConnectionId).addParticipant(callInvite);
caller_id_number = PhoneNumberIdentifier(
"+18888888888"
) # TThis is the ACS-provisioned phone number for the caller
target = PhoneNumberIdentifier("+18008008800"), # The phone number participant to dial out to
call_connection_client = call_automation_client.get_call_connection(
"call_connection_id"
)
result = call_connection_client.add_participant(
target,
operation_context="Your context",
operationCallbackUrl="<url_endpoint>"
)
移除 PSTN 参与者
var removeThisUser = new PhoneNumberIdentifier("+16044561234");
// Remove a participant from the call with optional parameters
var removeParticipantOptions = new RemoveParticipantOptions(removeThisUser)
{
OperationContext = "operationContext",
OperationCallbackUri = new Uri("uri_endpoint"); // Sending event to a non-default endpoint
}
RemoveParticipantsResult result = await client.GetCallConnection(callConnectionId).RemoveParticipantAsync(removeParticipantOptions);
CommunicationIdentifier removeThisUser = new PhoneNumberIdentifier("+16044561234");
RemoveParticipantOptions removeParticipantOptions = new RemoveParticipantOptions(removeThisUser)
.setOperationContext("<operation_context>")
.setOperationCallbackUrl("<url_endpoint>");
Response<RemoveParticipantResult> removeParticipantResultResponse = client.getCallConnectionAsync(callConnectionId)
.removeParticipantWithResponse(removeParticipantOptions);
const removeThisUser = { phoneNumber: "+16044561234" };
const removeParticipantResult = await client.getCallConnection(callConnectionId).removeParticipant(removeThisUser);
remove_this_user = PhoneNumberIdentifier("+16044561234")
call_connection_client = call_automation_client.get_call_connection(
"call_connection_id"
)
result = call_connection_client.remove_participant(remove_this_user, operation_context="Your context", operationCallbackUrl="<url_endpoint>")
发送 DTMF
向外部参与者发送 DTMF 音调列表。
var tones = new DtmfTone[] { DtmfTone.One, DtmfTone.Two, DtmfTone.Three, DtmfTone.Pound };
var sendDtmfTonesOptions = new SendDtmfTonesOptions(tones, new PhoneNumberIdentifier(calleePhonenumber))
{
OperationContext = "dtmfs-to-ivr"
};
var sendDtmfAsyncResult = await callAutomationClient.GetCallConnection(callConnectionId).GetCallMedia().SendDtmfTonesAsync(sendDtmfTonesOptions);
List<DtmfTone> tones = Arrays.asList(DtmfTone.ONE, DtmfTone.TWO, DtmfTone.THREE, DtmfTone.POUND);
SendDtmfTonesOptions options = new SendDtmfTonesOptions(tones, new PhoneNumberIdentifier(c2Target));
options.setOperationContext("dtmfs-to-ivr");
client.getCallConnectionAsync(callConnectionId)
.getCallMediaAsync()
.sendDtmfTonesWithResponse(options)
.block();
const tones = [DtmfTone.One, DtmfTone.Two, DtmfTone.Three];
const sendDtmfTonesOptions: SendDtmfTonesOptions = {
operationContext: "dtmfs-to-ivr"
};
const result: SendDtmfTonesResult = await client.getCallConnection(callConnectionId)
.getCallMedia()
.sendDtmfTones(tones, {
phoneNumber: c2Target
}, sendDtmfTonesOptions);
console.log("sendDtmfTones, result=%s", result);
tones = [DtmfTone.ONE, DtmfTone.TWO, DtmfTone.THREE]
call_connection_client = call_automation_client.get_call_connection(
"call_connection_id"
)
result = call_connection_client.send_dtmf_tones(
tones = tones,
target_participant = PhoneNumberIdentifier(c2_target),
operation_context = "dtmfs-to-ivr")
通话记录
Azure 通信服务会议室支持通话自动化提供的录制功能,包括 start
、stop
、pause
、resume
等。 请参阅以下代码片段,以在会议室通话中启动/停止/暂停/继续录制。 有关操作的完整列表,请参阅通话自动化录制。
// Start recording
StartRecordingOptions recordingOptions = new StartRecordingOptions(new ServerCallLocator("<ServerCallId>"))
{
RecordingContent = RecordingContent.Audio,
RecordingChannel = RecordingChannel.Unmixed,
RecordingFormat = RecordingFormat.Wav,
RecordingStateCallbackUri = new Uri("<CallbackUri>"),
RecordingStorage = RecordingStorage.CreateAzureBlobContainerRecordingStorage(new Uri("<YOUR_STORAGE_CONTAINER_URL>"))
};
Response<RecordingStateResult> response = await callAutomationClient.GetCallRecording()
.StartAsync(recordingOptions);
// Pause recording using recordingId received in response of start recording.
var pauseRecording = await callAutomationClient.GetCallRecording ().PauseAsync(recordingId);
// Resume recording using recordingId received in response of start recording.
var resumeRecording = await callAutomationClient.GetCallRecording().ResumeAsync(recordingId);
// Stop recording using recordingId received in response of start recording.
var stopRecording = await callAutomationClient.GetCallRecording().StopAsync(recordingId);
// Start recording
StartRecordingOptions recordingOptions = new StartRecordingOptions(new ServerCallLocator("<serverCallId>"))
.setRecordingChannel(RecordingChannel.UNMIXED)
.setRecordingFormat(RecordingFormat.WAV)
.setRecordingContent(RecordingContent.AUDIO)
.setRecordingStateCallbackUrl("<recordingStateCallbackUrl>");
Response<RecordingStateResult> response = callAutomationClient.getCallRecording()
.startWithResponse(recordingOptions, null);
// Pause recording using recordingId received in response of start recording
Response<Void> response = callAutomationClient.getCallRecording()
.pauseWithResponse(recordingId, null);
// Resume recording using recordingId received in response of start recording
Response<Void> response = callAutomationClient.getCallRecording()
.resumeWithResponse(recordingId, null);
// Stop recording using recordingId received in response of start recording
Response<Void> response = callAutomationClient.getCallRecording()
.stopWithResponse(recordingId, null);
// Start recording
var locator: CallLocator = { id: "<ServerCallId>", kind: "serverCallLocator" };
var options: StartRecordingOptions =
{
callLocator: locator,
recordingContent: "audio",
recordingChannel:"unmixed",
recordingFormat: "wav",
recordingStateCallbackEndpointUrl: "<CallbackUri>"
};
var response = await callAutomationClient.getCallRecording().start(options);
// Pause recording using recordingId received in response of start recording
var pauseRecording = await callAutomationClient.getCallRecording().pause(recordingId);
// Resume recording using recordingId received in response of start recording.
var resumeRecording = await callAutomationClient.getCallRecording().resume(recordingId);
// Stop recording using recordingId received in response of start recording
var stopRecording = await callAutomationClient.getCallRecording().stop(recordingId);
# Start recording
response = call_automation_client.start_recording(call_locator=ServerCallLocator(server_call_id),
recording_content_type = RecordingContent.Audio,
recording_channel_type = RecordingChannel.Unmixed,
recording_format_type = RecordingFormat.Wav,
recording_state_callback_url = "<CallbackUri>")
# Pause recording using recording_id received in response of start recording
pause_recording = call_automation_client.pause_recording(recording_id = recording_id)
# Resume recording using recording_id received in response of start recording
resume_recording = call_automation_client.resume_recording(recording_id = recording_id)
# Stop recording using recording_id received in response of start recording
stop_recording = call_automation_client.stop_recording(recording_id = recording_id)
终止通话
可以使用通话自动化 SDK 挂断操作来终止通话。 挂断操作完成后,SDK 将发布事件 CallDisconnected
。
_ = await client.GetCallConnection(callConnectionId).HangUpAsync(forEveryone: true);
Response<Void> response = client.getCallConnectionAsync(callConnectionId).hangUpWithResponse(true).block();
await callConnection.hangUp(true);
call_connection_client = call_automation_client.get_call_connection(
"call_connection_id"
)
call_connection_client.hang_up(is_for_everyone=True)
其他操作
会议室通话也支持以下通话内操作。
- 添加参与者(ACS 标识符)
- 移除参与者(ACS 标识符)
- 取消添加参与者(ACS 标识符和 PSTN 号码)
- 挂断通话
- 获取参与者(ACS 标识符和 PSTN 号码)
- 获取多个参与者(ACS 标识符和 PSTN 号码)
- 获取有关通话的最新信息
- 播放音频文件和文本
- 播放所有音频文件和文本
- 识别 DTMF 和语音
- 识别连续 DTMF
有关详细信息,请参阅通话操作和媒体操作。
后续步骤
在本部分,你已了解如何执行以下操作:
- 从应用程序加入会议室通话
- 使用通话 SDK 将通话内操作添加到会议室通话中
- 使用通话自动化 SDK 将通话内操作添加到会议室通话中
你可能还想要: