|
1 | 1 | ---
|
2 |
| -title: Get started with Azure Communication Services closed caption on web |
3 |
| -titleSuffix: An Azure Communication Services quickstart document |
4 |
| -description: Learn about the Azure Communication Services Closed Captions in web apps |
5 |
| -author: RinaRish |
6 |
| -manager: visho |
7 |
| -services: azure-communication-services |
8 |
| - |
9 |
| -ms.author: ektrishi |
10 |
| -ms.date: 02/03/2022 |
11 |
| -ms.topic: include |
| 2 | +title: include file |
| 3 | +description: Web how-to guide for enabling Closed captions during an ACS call. |
| 4 | +author: Kunaal |
12 | 5 | ms.service: azure-communication-services
|
| 6 | +ms.subservice: calling |
| 7 | +ms.topic: include |
| 8 | +ms.topic: include file |
| 9 | +ms.date: 12/19/2023 |
| 10 | +ms.author: kpunjabi |
13 | 11 | ---
|
14 | 12 |
|
15 | 13 | ## Prerequisites
|
| 14 | +- Azure account with an active subscription, for details see [Create an account for free.](https://azure.microsoft.com/free/) |
| 15 | +- Azure Communication Services resource. See [Create an Azure Communication Services resource](../../../../quickstarts/create-communication-resource.md?tabs=windows&pivots=platform-azp). Save the connection string for this resource. |
| 16 | +- An app with voice and video calling, refer to our [Voice](../../../../quickstarts/voice-video-calling/getting-started-with-calling.md) and [Video](../../../../quickstarts/voice-video-calling/get-started-with-video-calling.md) calling quickstarts. |
| 17 | + |
16 | 18 |
|
17 |
| -Refer to the [Voice Calling Quickstart](../../getting-started-with-calling.md?pivots=platform-web) to set up a sample app with voice calling. |
| 19 | +>[!NOTE] |
| 20 | +>Please note that you will need to have a voice calling app using Azure Communication Services calling SDKs to access the closed captions feature that is described in this guide. |
18 | 21 |
|
19 | 22 | ## Models
|
20 |
| - |
21 | 23 | | Name | Description |
|
22 |
| -| - | - | |
23 |
| -| CaptionsCallFeature | API for call captions. | |
24 |
| -| StartCaptionsOptions | Used for representing options to start closed captions | |
25 |
| -| CaptionsHandler | Callback definition for handling the CaptionsReceivedEventType event. | |
26 |
| -| CaptionsInfo | Data structure received for each CaptionsReceivedEventType event. | |
| 24 | +| ---- | ----------- | |
| 25 | +| CaptionsCallFeature | API for Captions | |
| 26 | +| CaptionsCommon | Base class for captions | |
| 27 | +| StartCaptionOptions | Closed caption options like spoken language | |
| 28 | +| CaptionsHandler | Callback definition for handling CaptionsReceivedEventType event | |
| 29 | +| CaptionsInfo | Data structure received for each CaptionsReceivedEventType event | |
27 | 30 |
|
28 |
| -## Methods |
| 31 | +## Get closed captions feature |
29 | 32 |
|
30 |
| -### Start captions |
| 33 | +``` typescript |
| 34 | +let captionsCallFeature: SDK.CaptionsCallFeature = call.feature(SDK.Features.Captions); |
| 35 | +``` |
31 | 36 |
|
32 |
| -1. Get the ongoing call object established during the prerequisite steps. |
33 |
| -2. Get the captions feature object. |
34 |
| -3. Set the `captionsReceived` event handler via the `on` API. |
35 |
| -4. Call `startCaptions` on the feature object with the desired options. |
36 |
| -```js |
37 |
| -const captionsHandler = (data: CaptionsInfo) => { /* USER CODE HERE - E.G. RENDER TO DOM */ }; |
38 | 37 |
|
39 |
| -try { |
40 |
| - const callCaptionsApi = call.feature(Features.Captions); |
41 |
| - callCaptionsApi.on('captionsReceived', captionsHandler); |
42 |
| - if (!callCaptionsApi.isCaptionsActive) { |
43 |
| - await callCaptionsApi.startCaptions({ spokenLanguage: 'en-us' }); |
44 |
| - } |
45 |
| -} catch (e) { |
46 |
| - console.log('Internal error occurred when Starting Captions'); |
| 38 | +## Get captions object |
| 39 | +You need to get and cast the Captions object to utilize Captions specific features. |
| 40 | +``` typescript |
| 41 | +let captions: SDK.Captions; |
| 42 | +if (captionsCallFeature.captions.kind === 'Captions') { |
| 43 | + captions = captionsCallFeature.captions as SDK.Captions; |
47 | 44 | }
|
48 | 45 | ```
|
49 | 46 |
|
50 |
| -### Stopping captions |
| 47 | +## Subscribe to listeners |
51 | 48 |
|
52 |
| -1. Get the captions feature object. |
53 |
| -2. Call `off` with the previous specified handler. |
| 49 | +### Add a listener to receive captions active/inactive status |
| 50 | +```typescript |
| 51 | +const captionsActiveChangedHandler = () => { |
| 52 | + if (captions.isCaptionsFeatureActive()) { |
| 53 | + /* USER CODE HERE - E.G. RENDER TO DOM */ |
| 54 | + } |
| 55 | +} |
| 56 | +captions.on('CaptionsActiveChanged', captionsActiveChangedHandler); |
| 57 | +``` |
54 | 58 |
|
55 |
| -> [!NOTE] |
56 |
| -> Captions will still be processed, but this client will stop handling them. |
| 59 | +### Add a listener for captions data received |
| 60 | +Handle the returned CaptionsInfo data object. |
| 61 | + |
| 62 | +Note: The object contains a resultType prop that indicates whether the data is a partial caption or a finalized version of the caption. ResultType `Partial` indicates live unedited caption, while `Final` indicates a finalized interpreted version of the sentence (i.e includes punctuation and capitalization). |
| 63 | + |
| 64 | +```typescript |
| 65 | +const captionsReceivedHandler : CaptionsHandler = (data: CaptionsInfo) => { |
| 66 | + /** USER CODE HERE - E.G. RENDER TO DOM |
| 67 | + * data.resultType |
| 68 | + * data.speaker |
| 69 | + * data.spokenLanguage |
| 70 | + * data.spokenText |
| 71 | + * data.timeStamp |
| 72 | + */ |
| 73 | + // Example code: |
| 74 | + // Create a dom element, i.e. div, with id "captionArea" before proceeding with the sample code |
| 75 | + let mri: string; |
| 76 | + switch (data.speaker.identifier.kind) { |
| 77 | + case 'communicationUser': { mri = data.speaker.identifier.communicationUserId; break; } |
| 78 | + case 'phoneNumber': { mri = data.speaker.identifier.phoneNumber; break; } |
| 79 | + } |
| 80 | + const outgoingCaption = `prefix${mri.replace(/:/g, '').replace(/-/g, '')}`; |
| 81 | + |
| 82 | + let captionArea = document.getElementById("captionArea"); |
| 83 | + const captionText = `${data.timestamp.toUTCString()} |
| 84 | + ${data.speaker.displayName}: ${data.spokenText}`; |
| 85 | + |
| 86 | + let foundCaptionContainer = captionArea.querySelector(`.${outgoingCaption}[isNotFinal='true']`); |
| 87 | + if (!foundCaptionContainer) { |
| 88 | + let captionContainer = document.createElement('div'); |
| 89 | + captionContainer.setAttribute('isNotFinal', 'true'); |
| 90 | + captionContainer.style['borderBottom'] = '1px solid'; |
| 91 | + captionContainer.style['whiteSpace'] = 'pre-line'; |
| 92 | + captionContainer.textContent = captionText; |
| 93 | + captionContainer.classList.add(newClassName); |
| 94 | + |
| 95 | + captionArea.appendChild(captionContainer); |
| 96 | + } else { |
| 97 | + foundCaptionContainer.textContent = captionText; |
| 98 | + |
| 99 | + if (captionData.resultType === 'Final') { |
| 100 | + foundCaptionContainer.setAttribute('isNotFinal', 'false'); |
| 101 | + } |
| 102 | + } |
| 103 | +}; |
| 104 | +captions.on('CaptionsReceived', captionsReceivedHandler); |
| 105 | +``` |
57 | 106 |
|
58 |
| -```js |
59 |
| -const callCaptionsApi = call.feature(Features.Captions); |
60 |
| -callCaptionsApi.off('captionsReceived', captionsHandler); |
| 107 | +### Add a listener to receive spoken language changed status |
| 108 | +```typescript |
| 109 | +const spokenLanguageChangedHandler = () => { |
| 110 | + if (captions.activeSpokenLanguage !== currentSpokenLanguage) { |
| 111 | + /* USER CODE HERE - E.G. RENDER TO DOM */ |
| 112 | + } |
| 113 | +} |
| 114 | +captions.on('SpokenLanguageChanged', spokenLanguageChangedHandler) |
61 | 115 | ```
|
62 | 116 |
|
63 |
| -### Get available languages |
| 117 | +## Start captions |
| 118 | +Once you have set up all your listeners, you can now start adding captions. |
| 119 | +``` typescript |
| 120 | +try { |
| 121 | + await captions.startCaptions({ spokenLanguage: 'en-us' }); |
| 122 | +} catch (e) { |
| 123 | + /* USER ERROR HANDLING CODE HERE */ |
| 124 | +} |
| 125 | +``` |
64 | 126 |
|
65 |
| -Access the `availableLanguages` property on the `call.feature(Features.Captions)` API. |
| 127 | +## Stop captions |
66 | 128 |
|
67 |
| -```js |
68 |
| -const callCaptionsApi = call.feature(Features.Captions); |
69 |
| -const availableLanguages = callCaptionsApi.availableLanguages; |
| 129 | +``` typescript |
| 130 | +try { |
| 131 | + captions.stopCaptions(); |
| 132 | +} catch (e) { |
| 133 | + /* USER ERROR HANDLING CODE HERE */ |
| 134 | +} |
70 | 135 | ```
|
71 | 136 |
|
72 |
| -### Update language |
| 137 | +## Unsubscribe to listeners |
| 138 | +```typescript |
| 139 | +captions.off('CaptionsActiveChanged', captionsActiveChangedHandler); |
| 140 | +captions.off('CaptionsReceived', captionsReceivedHandler); |
| 141 | +``` |
73 | 142 |
|
74 |
| -Pass a value in from the available languages array to ensure that the requested language is supported. |
| 143 | +## Spoken language support |
75 | 144 |
|
76 |
| -```js |
77 |
| -await callCaptionsApi.selectLanguage(availableLanguages[0]); |
| 145 | +### Get a list of supported spoken languages |
| 146 | +Get a list of supported spoken languages that your users can select from when enabling closed captions. |
| 147 | +The property returns an array of languages in bcp 47 format. |
| 148 | +``` typescript |
| 149 | +const spokenLanguages = captions.supportedSpokenLanguages; |
78 | 150 | ```
|
79 | 151 |
|
80 |
| -## Clean up |
| 152 | +## Set spoken language |
81 | 153 |
|
82 |
| -If you want to clean up and remove a Communication Services subscription, you can delete the resource or resource group. Deleting the resource group also deletes any other resources associated with it. |
83 |
| -Learn more about [cleaning up resources here.](../../../create-communication-resource.md?pivots=platform-azp&tabs=windows#clean-up-resources) |
| 154 | +Pass a value in from the supported spoken languages array to ensure that the requested language is supported. |
| 155 | +By default, if contoso provides no language or an unsupported language, the spoken language defaults to 'en-us'. |
| 156 | + |
| 157 | +``` typescript |
| 158 | +// bcp 47 formatted language code |
| 159 | +const language = 'en-us'; |
| 160 | + |
| 161 | +// Altneratively, pass a value from the supported spoken languages array |
| 162 | +const language = spokenLanguages[0]; |
| 163 | + |
| 164 | +try { |
| 165 | + captions.setSpokenLanguage(language); |
| 166 | +} catch (e) { |
| 167 | + /* USER ERROR HANDLING CODE HERE */ |
| 168 | +} |
| 169 | +``` |
0 commit comments