Skip to content

Commit 27d10dc

Browse files
authored
Merge pull request #280574 from mikehang-msft/mhang/ManageRoomsCallQuickstart
Add Manage Rooms Call Quickstart Readme
2 parents a25ba81 + 440c9df commit 27d10dc

File tree

1 file changed

+377
-0
lines changed

1 file changed

+377
-0
lines changed
Lines changed: 377 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,377 @@
1+
---
2+
title: Quickstart - Manage a room call
3+
titleSuffix: An Azure Communication Services Quickstart
4+
description: In this quickstart, you learn how to manage a room call using Calling SDKs and Call Automation SDKs
5+
services: azure-communication-services
6+
author: mikehang
7+
manager: alexokun
8+
9+
ms.author: mikehang
10+
ms.date: 07/10/2024
11+
ms.topic: quickstart
12+
ms.service: azure-communication-services
13+
ms.custom: mode-other
14+
---
15+
16+
# Quickstart: Manage a room call
17+
18+
## Introduction
19+
During an Azure Communication Services (ACS) room call, you can manage the call using Calling SDKs or Call Automation SDKs or both. In a room call, you can control in-call actions using both the roles assigned to participants and properties configured in the room. The participant's roles control capabilities permitted per participant, while room properties apply to the room call as a whole.
20+
21+
## Calling SDKs
22+
Calling SDK is a client-side calling library enabling participants in a room call to perform several in-call operations, such as screen share, turn on/off video, mute/unmute, and so on. For the full list of capabilities, see [Calling SDK Overview](../../concepts/voice-video-calling/calling-sdk-features.md#detailed-capabilities).
23+
24+
You control the capabilities based on roles assigned to participants in the call. For example, only the presenter can screen share. For participant roles and permissions, see [Rooms concepts](../../concepts/rooms/room-concept.md#predefined-participant-roles-and-permissions).
25+
26+
## Call Automation SDKs
27+
Call Automation SDK is a server-side library enabling administrators to manage an ongoing room call in a central and controlled environment. Unlike Calling SDK, Call Automation SDK operations are roles agnostic. Therefore, a call administrator can perform several in-call operations on behalf of the room call participants.
28+
29+
The following lists describe common in-call actions available in a room call.
30+
31+
### Connect to a room call
32+
Call Automation must connect to an existing room call before performing any in-call operations. The `CallConnected` or `ConnectFailed` events are raised using callback mechanisms to indicate if a connect operation was successful or failed respectively.
33+
34+
### [csharp](#tab/csharp)
35+
36+
```csharp
37+
Uri callbackUri = new Uri("https://<myendpoint>/Events"); //the callback endpoint where you want to receive subsequent events
38+
CallLocator roomCallLocator = new RoomCallLocator("<RoomId>");
39+
ConnectCallResult response = await client.ConnectAsync(roomCallLocator, callbackUri);
40+
```
41+
42+
### [Java](#tab/java)
43+
44+
```java
45+
String callbackUri = "https://<myendpoint>/Events"; //the callback endpoint where you want to receive subsequent events
46+
CallLocator roomCallLocator = new RoomCallLocator("<RoomId>");
47+
ConnectCallResult response = client.connectCall(roomCallLocator, callbackUri).block();
48+
```
49+
50+
### [JavaScript](#tab/javascript)
51+
52+
```javascript
53+
const roomCallLocator = { kind: "roomCallLocator", id: "<RoomId>" };
54+
const callbackUri = "https://<myendpoint>/Events"; // the callback endpoint where you want to receive subsequent events
55+
const response = await client.connectCall(roomCallLocator, callbackUri);
56+
```
57+
58+
### [Python](#tab/python)
59+
60+
```python
61+
callback_uri = "https://<myendpoint>/Events" # the callback endpoint where you want to receive subsequent events
62+
room_call_locator = RoomCallLocator("<room_id>")
63+
call_connection_properties = client.connect_call(call_locator=room_call_locator, callback_url=callback_uri)
64+
```
65+
-----
66+
67+
Once successfully connected to a room call, a `CallConnect` event is notified via Callback URI. You can use `callConnectionId` to retrieve a call connection on the room call as needed. The following sample code snippets use the `callConnectionId` to demonstrate this function.
68+
69+
70+
### Add PSTN Participant
71+
Using Call Automation you can dial out to a PSTN number and add the participant into a room call. You must, however, set up a room to enable PSTN dial-out option (`EnabledPSTNDialout` set to `true`) and the Azure Communication Services resource must have a valid phone number provisioned.
72+
73+
For more information, see [Rooms quickstart](../../quickstarts//rooms/get-started-rooms.md?tabs=windows&pivots=platform-azcli#enable-pstn-dial-out-capability-for-a-room).
74+
75+
76+
### [csharp](#tab/csharp)
77+
78+
```csharp
79+
var callerIdNumber = new PhoneNumberIdentifier("+16044561234"); // This is the ACS-provisioned phone number for the caller
80+
var callThisPerson = new CallInvite(new PhoneNumberIdentifier("+16041234567"), callerIdNumber); // The target phone number to dial out to
81+
CreateCallResult response = await client.GetCallConnection(callConnectionId).AddParticipantAsync(callThisPerson);
82+
```
83+
84+
### [Java](#tab/java)
85+
86+
```java
87+
PhoneNumberIdentifier callerIdNumber = new PhoneNumberIdentifier("+16044561234"); // This is the ACS-provisioned phone number for the caller
88+
CallInvite callInvite = new CallInvite(new PhoneNumberIdentifier("+16041234567"), callerIdNumber); // The phone number participant to dial out to
89+
AddParticipantOptions addParticipantOptions = new AddParticipantOptions(callInvite);
90+
Response<AddParticipantResult> addParticipantResultResponse = client.getCallConnectionAsync(callConnectionId)
91+
.addParticipantWithResponse(addParticipantOptions).block();
92+
```
93+
94+
### [JavaScript](#tab/javascript)
95+
96+
```javascript
97+
const callInvite = {
98+
targetParticipant: { phoneNumber: "+18008008800" }, // The phone number participant to dial out to
99+
sourceCallIdNumber: { phoneNumber: "+18888888888" } // This is the ACS-provisioned phone number for the caller
100+
};
101+
const response = await client.getCallConnection(callConnectionId).addParticipant(callInvite);
102+
```
103+
104+
### [Python](#tab/python)
105+
106+
```python
107+
caller_id_number = PhoneNumberIdentifier(
108+
"+18888888888"
109+
) # TThis is the ACS-provisioned phone number for the caller
110+
target = PhoneNumberIdentifier("+18008008800"), # The phone number participant to dial out to
111+
112+
call_connection_client = call_automation_client.get_call_connection(
113+
"call_connection_id"
114+
)
115+
result = call_connection_client.add_participant(
116+
target,
117+
opration_context="Your context",
118+
operationCallbackUrl="<url_endpoint>"
119+
)
120+
```
121+
-----
122+
123+
### Remove PSTN Participant
124+
125+
### [csharp](#tab/csharp)
126+
127+
```csharp
128+
129+
var removeThisUser = new PhoneNumberIdentifier("+16044561234");
130+
131+
// Remove a participant from the call with optional parameters
132+
var removeParticipantOptions = new RemoveParticipantOptions(removeThisUser)
133+
{
134+
OperationContext = "operationContext",
135+
OperationCallbackUri = new Uri("uri_endpoint"); // Sending event to a non-default endpoint
136+
}
137+
138+
RemoveParticipantsResult result = await client.GetCallConnection(callConnectionId).RemoveParticipantAsync(removeParticipantOptions);
139+
```
140+
141+
### [Java](#tab/java)
142+
143+
```java
144+
CommunicationIdentifier removeThisUser = new PhoneNumberIdentifier("+16044561234");
145+
RemoveParticipantOptions removeParticipantOptions = new RemoveParticipantOptions(removeThisUser)
146+
.setOperationContext("<operation_context>")
147+
.setOperationCallbackUrl("<url_endpoint>");
148+
Response<RemoveParticipantResult> removeParticipantResultResponse = client.getCallConnectionAsync(callConnectionId)
149+
.removeParticipantWithResponse(removeParticipantOptions);
150+
```
151+
152+
### [JavaScript](#tab/javascript)
153+
154+
```javascript
155+
const removeThisUser = { phoneNumber: "+16044561234" };
156+
const removeParticipantResult = await client.getCallConnection(callConnectionId).removeParticipant(removeThisUser);
157+
```
158+
159+
### [Python](#tab/python)
160+
161+
```python
162+
remove_this_user = PhoneNumberIdentifier("+16044561234")
163+
call_connection_client = call_automation_client.get_call_connection(
164+
"call_connection_id"
165+
)
166+
result = call_connection_client.remove_participant(remove_this_user, opration_context="Your context", operationCallbackUrl="<url_endpoint>")
167+
```
168+
-----
169+
170+
### Send DTMF
171+
Send a list of DTMF tones to an external participant.
172+
173+
### [csharp](#tab/csharp)
174+
```csharp
175+
vartones=newDtmfTone[] { DtmfTone.One, DtmfTone.Two, DtmfTone.Three, DtmfTone.Pound };
176+
varsendDtmfTonesOptions=newSendDtmfTonesOptions(tones, newPhoneNumberIdentifier(calleePhonenumber))
177+
{
178+
OperationContext="dtmfs-to-ivr"
179+
};
180+
181+
varsendDtmfAsyncResult=awaitcallAutomationClient.GetCallConnection(callConnectionId).GetCallMedia().SendDtmfTonesAsync(sendDtmfTonesOptions);
182+
183+
```
184+
### [Java](#tab/java)
185+
```java
186+
List<DtmfTone> tones = Arrays.asList(DtmfTone.ONE, DtmfTone.TWO, DtmfTone.THREE, DtmfTone.POUND);
187+
SendDtmfTonesOptions options =new SendDtmfTonesOptions(tones, new PhoneNumberIdentifier(c2Target));
188+
options.setOperationContext("dtmfs-to-ivr");
189+
client.getCallConnectionAsync(callConnectionId)
190+
.getCallMediaAsync()
191+
.sendDtmfTonesWithResponse(options)
192+
.block();
193+
```
194+
### [JavaScript](#tab/javascript)
195+
```javascript
196+
const tones = [DtmfTone.One, DtmfTone.Two, DtmfTone.Three];
197+
const sendDtmfTonesOptions: SendDtmfTonesOptions = {
198+
operationContext: "dtmfs-to-ivr"
199+
};
200+
const result: SendDtmfTonesResult = await client.getCallConnection(callConnectionId)
201+
.getCallMedia()
202+
.sendDtmfTones(tones, {
203+
phoneNumber: c2Target
204+
}, sendDtmfTonesOptions);
205+
console.log("sendDtmfTones, result=%s", result);
206+
```
207+
### [Python](#tab/python)
208+
```python
209+
tones = [DtmfTone.ONE, DtmfTone.TWO, DtmfTone.THREE]
210+
call_connection_client = call_automation_client.get_call_connection(
211+
"call_connection_id"
212+
)
213+
214+
result = call_connection_client.send_dtmf_tones(
215+
tones = tones,
216+
target_participant = PhoneNumberIdentifier(c2_target),
217+
operation_context = "dtmfs-to-ivr")
218+
```
219+
-----
220+
221+
### Call Recording
222+
Azure Communication Services rooms support recording capabilities including `start`, `stop`, `pause`, `resume`, and so on, provided by Call Automation. See the following code snippets to start/stop/pause/resume a recording in a room call. For a complete list of actions, see [Call Automation recording](../../concepts/voice-video-calling/call-recording.md#get-full-control-over-your-recordings-with-our-call-recording-apis).
223+
224+
### [csharp](#tab/csharp)
225+
```csharp
226+
// Start recording
227+
StartRecordingOptions recordingOptions = new StartRecordingOptions(new ServerCallLocator("<ServerCallId>"))
228+
{
229+
RecordingContent = RecordingContent.Audio,
230+
RecordingChannel = RecordingChannel.Unmixed,
231+
RecordingFormat = RecordingFormat.Wav,
232+
RecordingStateCallbackUri = new Uri("<CallbackUri>"),
233+
RecordingStorage = RecordingStorage.CreateAzureBlobContainerRecordingStorage(new Uri("<YOUR_STORAGE_CONTAINER_URL>"))
234+
};
235+
Response<RecordingStateResult> response = await callAutomationClient.GetCallRecording()
236+
.StartAsync(recordingOptions);
237+
238+
// Pause recording using recordingId received in response of start recording.
239+
var pauseRecording = await callAutomationClient.GetCallRecording ().PauseAsync(recordingId);
240+
241+
// Resume recording using recordingId received in response of start recording.
242+
var resumeRecording = await callAutomationClient.GetCallRecording().ResumeAsync(recordingId);
243+
244+
// Stop recording using recordingId received in response of start recording.
245+
var stopRecording = await callAutomationClient.GetCallRecording().StopAsync(recordingId);
246+
247+
```
248+
### [Java](#tab/java)
249+
```java
250+
// Start recording
251+
StartRecordingOptions recordingOptions = new StartRecordingOptions(new ServerCallLocator("<serverCallId>"))
252+
.setRecordingChannel(RecordingChannel.UNMIXED)
253+
.setRecordingFormat(RecordingFormat.WAV)
254+
.setRecordingContent(RecordingContent.AUDIO)
255+
.setRecordingStateCallbackUrl("<recordingStateCallbackUrl>");
256+
257+
Response<RecordingStateResult> response = callAutomationClient.getCallRecording()
258+
.startWithResponse(recordingOptions, null);
259+
260+
// Pause recording using recordingId received in response of start recording
261+
Response<Void> response = callAutomationClient.getCallRecording()
262+
.pauseWithResponse(recordingId, null);
263+
264+
// Resume recording using recordingId received in response of start recording
265+
Response<Void> response = callAutomationClient.getCallRecording()
266+
.resumeWithResponse(recordingId, null);
267+
268+
// Stop recording using recordingId received in response of start recording
269+
Response<Void> response = callAutomationClient.getCallRecording()
270+
.stopWithResponse(recordingId, null);
271+
272+
```
273+
### [JavaScript](#tab/javascript)
274+
```javascript
275+
// Start recording
276+
var locator: CallLocator = { id: "<ServerCallId>", kind: "serverCallLocator" };
277+
278+
var options: StartRecordingOptions =
279+
{
280+
callLocator: locator,
281+
recordingContent: "audio",
282+
recordingChannel:"unmixed",
283+
recordingFormat: "wav",
284+
recordingStateCallbackEndpointUrl: "<CallbackUri>"
285+
};
286+
var response = await callAutomationClient.getCallRecording().start(options);
287+
288+
// Pause recording using recordingId received in response of start recording
289+
var pauseRecording = await callAutomationClient.getCallRecording().pause(recordingId);
290+
291+
// Resume recording using recordingId received in response of start recording.
292+
var resumeRecording = await callAutomationClient.getCallRecording().resume(recordingId);
293+
294+
// Stop recording using recordingId received in response of start recording
295+
var stopRecording = await callAutomationClient.getCallRecording().stop(recordingId);
296+
297+
```
298+
### [Python](#tab/python)
299+
```python
300+
# Start recording
301+
response = call_automation_client.start_recording(call_locator=ServerCallLocator(server_call_id),
302+
recording_content_type = RecordingContent.Audio,
303+
recording_channel_type = RecordingChannel.Unmixed,
304+
recording_format_type = RecordingFormat.Wav,
305+
recording_state_callback_url = "<CallbackUri>")
306+
307+
# Pause recording using recording_id received in response of start recording
308+
pause_recording = call_automation_client.pause_recording(recording_id = recording_id)
309+
310+
# Resume recording using recording_id received in response of start recording
311+
resume_recording = call_automation_client.resume_recording(recording_id = recording_id)
312+
313+
# Stop recording using recording_id received in response of start recording
314+
stop_recording = call_automation_client.stop_recording(recording_id = recording_id)
315+
```
316+
-----
317+
318+
### Terminate a Call
319+
You can use the Call Automation SDK Hang Up action to terminate a call. When the Hang Up action completes, the SDK publishes a `CallDisconnected` event.
320+
321+
### [csharp](#tab/csharp)
322+
323+
```csharp
324+
_ = await client.GetCallConnection(callConnectionId).HangUpAsync(forEveryone: true);
325+
```
326+
327+
### [Java](#tab/java)
328+
329+
```java
330+
Response<Void> response = client.getCallConnectionAsync(callConnectionId).hangUpWithResponse(true).block();
331+
```
332+
333+
### [JavaScript](#tab/javascript)
334+
335+
```javascript
336+
await callConnection.hangUp(true);
337+
```
338+
339+
### [Python](#tab/python)
340+
341+
```python
342+
call_connection_client = call_automation_client.get_call_connection(
343+
"call_connection_id"
344+
)
345+
346+
call_connection_client.hang_up(is_for_everyone=True)
347+
```
348+
-----
349+
350+
## Other Actions
351+
The following in-call actions are also supported in a room call.
352+
1. Add participant (ACS identifier)
353+
1. Remove participant (ACS identifier)
354+
1. Cancel add participant (ACS identifier and PSTN number)
355+
1. Hang up call
356+
1. Get participant (ACS identifier and PSTN number)
357+
1. Get multiple participants (ACS identifier and PSTN number)
358+
1. Get latest info about a call
359+
1. Play both audio files and text
360+
1. Play all both audio files and text
361+
1. Recognize both DTMF and speech
362+
1. Recognize continuous DTMF
363+
364+
For more information, see [call actions](../../how-tos/call-automation/actions-for-call-control.md?branch=pr-en-us-280574&tabs=csharp) and [media actions](../../how-tos/call-automation/control-mid-call-media-actions.md?branch=pr-en-us-280574&tabs=csharp).
365+
366+
## Next steps
367+
368+
In this section you learned how to:
369+
> [!div class="checklist"]
370+
> - Join a room call from your application
371+
> - Add in-call actions into a room call using calling SDKs
372+
> - Add in-call actions into a room call using Call Automation SDKs
373+
374+
You may also want to:
375+
- Learn about [Rooms concept](../../concepts/rooms/room-concept.md)
376+
- Learn about [Calling SDKs features](../../concepts/voice-video-calling/calling-sdk-features.md)
377+
- Learn about [Call Automation concepts](../../concepts/call-automation/call-automation.md)

0 commit comments

Comments
 (0)