UNPKG

48.8 kBMarkdownView Raw
1# Amazon Chime SDK for JavaScript
2[Amazon Chime SDK Project Board](https://github.com/orgs/aws/projects/12)
3
4[Amazon Chime SDK React Components](https://github.com/aws/amazon-chime-sdk-component-library-react)
5
6<a href="https://www.npmjs.com/package/amazon-chime-sdk-js"><img src="https://img.shields.io/npm/v/amazon-chime-sdk-js?style=flat-square"></a>
7<a href="https://github.com/aws/amazon-chime-sdk-js/actions?query=workflow%3A%22Deploy+Demo+App+Workflow%22"><img src="https://github.com/aws/amazon-chime-sdk-js/workflows/Deploy%20Demo%20App%20Workflow/badge.svg"></a>
8### Build video calling, audio calling, and screen sharing applications powered by Amazon Chime.
9
10The Amazon Chime SDK makes it easy to add collaborative audio calling,
11video calling, and screen share features to web applications by using
12the same infrastructure services that power millions of Amazon Chime
13online meetings.
14
15This Amazon Chime SDK for JavaScript works by connecting to meeting session
16resources that you have created in your AWS account. The SDK has everything
17you need to build custom calling and collaboration experiences in your
18web application, including methods to: configure meeting sessions, list and
19select audio and video devices, start and stop screen share and screen share
20viewing, receive callbacks when media events occur such as volume changes, and
21control meeting features such as audio mute and video tile bindings.
22
23If you are building a React application, consider using the [Amazon Chime SDK React Component Library](https://github.com/aws/amazon-chime-sdk-component-library-react) that supplies client-side state management and reusable UI components for common web interfaces used in audio and video conferencing applications. Amazon Chime also offers [Amazon Chime SDK for iOS](https://github.com/aws/amazon-chime-sdk-ios) and [Amazon Chime SDK for Android](https://github.com/aws/amazon-chime-sdk-android) for native mobile application development.
24
25The [Amazon Chime SDK Project Board](https://github.com/orgs/aws/projects/12) captures the status of community feature requests across all our repositories. The descriptions of the columns on the board are captured in this [guide](https://aws.github.io/amazon-chime-sdk-js/modules/projectboard.html).
26
27## Resources
28
29- [Amazon Chime SDK Overview](https://aws.amazon.com/chime/chime-sdk/)
30- [Pricing](https://aws.amazon.com/chime/pricing/#Chime_SDK_)
31- [Supported Browsers](https://docs.aws.amazon.com/chime/latest/dg/meetings-sdk.html#mtg-browsers)
32- [Developer Guide](https://docs.aws.amazon.com/chime/latest/dg/meetings-sdk.html)
33- [Control Plane API Reference](https://docs.aws.amazon.com/chime/latest/APIReference/Welcome.html)
34
35## Blog posts
36
37- [High Level Architecture — Building a Meeting Application with the Amazon Chime SDK](https://aws.amazon.com/blogs/business-productivity/building-a-meeting-application-using-the-amazon-chime-sdk/)
38- [Understanding security in Amazon Chime](https://aws.amazon.com/blogs/business-productivity/understanding-security-in-the-amazon-chime-application-and-sdk/)
39- [Transforming audio and shared content](https://aws.amazon.com/blogs/business-productivity/transforming-audio-and-shared-content-in-the-amazon-chime-sdk-for-javascript/)
40- [Capturing Amazon Chime SDK Meeting Content](https://aws.amazon.com/blogs/business-productivity/capture-amazon-chime-sdk-meetings-using-media-capture-pipelines/)
41- [Quickly launch an Amazon Chime SDK application with AWS Amplify](https://aws.amazon.com/blogs/business-productivity/quickly-launch-an-amazon-chime-sdk-application-with-aws-amplify/)
42- [Monitoring and troubleshooting with Amazon Chime SDK meeting events](https://aws.amazon.com/blogs/business-productivity/monitoring-and-troubleshooting-with-amazon-chime-sdk-meeting-events/)
43
44Here is a list of all blog posts about the Amazon Chime SDK](https://aws.amazon.com/blogs/business-productivity/tag/amazon-chime-sdk/).
45
46### Webinars and videos
47
48- [Webinar: Creating Classroom Experiences Using the Amazon Chime SDK](https://www.youtube.com/watch?v=S8T-0xfvXJ8)
49
50## Guides
51
52The following developer guides cover specific topics for a technical audience.
53
54- [Getting Started](https://aws.github.io/amazon-chime-sdk-js/modules/gettingstarted.html)
55- [API Overview](https://aws.github.io/amazon-chime-sdk-js/modules/apioverview.html)
56- [Frequently Asked Questions (FAQ)](https://aws.github.io/amazon-chime-sdk-js/modules/faqs.html)
57- [Content Share](https://aws.github.io/amazon-chime-sdk-js/modules/contentshare.html)
58- [Quality, Bandwidth, and Connectivity](https://aws.github.io/amazon-chime-sdk-js/modules/qualitybandwidth_connectivity.html)
59- [Simulcast](https://aws.github.io/amazon-chime-sdk-js/modules/simulcast.html)
60- [Meeting events](https://aws.github.io/amazon-chime-sdk-js/modules/meetingevents.html)
61- [Integrating Amazon Voice Focus into your application](https://aws.github.io/amazon-chime-sdk-js/modules/amazonvoice_focus.html)
62- [Adding frame-by-frame processing to an outgoing video stream](https://aws.github.io/amazon-chime-sdk-js/modules/videoprocessor.html)
63- [Adapting video to limited bandwidth using a priority-based video downlink policy](https://aws.github.io/amazon-chime-sdk-js/modules/prioritybased_downlink_policy.html)
64- [Client event ingestion](https://aws.github.io/amazon-chime-sdk-js/modules/clientevent_ingestion.html)
65
66## Migration Guides
67- [Migrating from v1.0 to v2.0](https://aws.github.io/amazon-chime-sdk-js/modules/migrationto_2_0.html)
68
69## Examples
70
71- [Amazon Chime SDK Samples](https://github.com/aws-samples/amazon-chime-sdk) - Amazon Chime SDK Samples repository
72- [Meeting Demo](https://github.com/aws/amazon-chime-sdk-js/tree/master/demos/browser) — A browser
73 meeting application with a local server
74- [Serverless Meeting Demo](https://github.com/aws/amazon-chime-sdk-js/tree/master/demos/serverless) — A self-contained serverless meeting application
75- [Single JS](https://github.com/aws/amazon-chime-sdk-js/tree/master/demos/singlejs) — A script to bundle the SDK into a single `.js` file
76- [Recording Demo](https://aws.amazon.com/blogs/business-productivity/how-to-enable-client-side-recording-using-the-amazon-chime-sdk/) — Recording the meeting's audio, video and screen share in high definition
77- [Virtual Classroom](https://aws.amazon.com/blogs/business-productivity/building-a-virtual-classroom-application-using-the-amazon-chime-sdk/) — An online classroom built with Electron and React
78- [Live Events](https://aws.amazon.com/blogs/opensource/how-to-deploy-a-live-events-solution-built-with-the-amazon-chime-sdk/) — Interactive live events solution
79- [Amazon Chime SDK Smart Video Sending Demo](https://aws.amazon.com/blogs/business-productivity/amazon-chime-sdk-smart-video-sending-demo/) — Demo showcasing how to dynamically display up to 25 video tiles from a pool of up to 250 meeting attendees
80- [Amazon Chime SDK and Amazon Connect Integration](https://aws.amazon.com/blogs/business-productivity/build-a-video-contact-center-with-amazon-connect-and-amazon-chime-sdk/) — Build a video contact center with Amazon Connect and Amazon Chime SDK
81- [PSTN Dial In](https://github.com/aws-samples/chime-sipmediaapplication-samples) — Add PSTN dialin capabilities to your Amazon Chime SDK Meeting using SIP Media Application
82- [Device Integration](https://aws.amazon.com/blogs/business-productivity/using-the-amazon-chime-sdk-for-3rd-party-devices/) — Using the Amazon Chime SDK for 3rd party devices
83- [Messaging](https://aws.amazon.com/blogs/business-productivity/build-chat-features-into-your-application-with-amazon-chime-sdk-messaging/) — Build chat features into your application with Amazon Chime SDK messaging
84
85## Troubleshooting and Support
86Review the resources given in the ReadMe and use our [client documentation](https://aws.github.io/amazon-chime-sdk-js/) for guidance on how to develop on the Chime SDK for JavaScript. Additionally, search our [issues database](https://github.com/aws/amazon-chime-sdk-js/issues) and [FAQs](https://aws.github.io/amazon-chime-sdk-js/modules/faqs.html) to see if your issue is already addressed. If not please cut us an [issue](https://github.com/aws/amazon-chime-sdk-js/issues/new/choose) using the provided templates.
87
88If you have more questions, or require support for your business, you can reach out to [AWS Customer support](https://pages.awscloud.com/GLOBAL-aware-GC-Amazon-Chime-SDK-2020-reg.html). You can review our support plans [here](https://aws.amazon.com/premiumsupport/plans/?nc=sn&loc=1).
89
90
91## WebRTC Resources
92> Amazon Chime JS SDK uses WebRTC and hence here are some general resources on WebRTC.
93- [WebRTC Basics](https://www.html5rocks.com/en/tutorials/webrtc/basics/)
94- [WebRTC Org - Getting started, presentation, samples, tutorials, books and more resources](https://webrtc.github.io/webrtc-org/start/)
95- [High Performance Browser Networking - WebRTC (Browser APIs and Protocols)](https://hpbn.co/webrtc/)
96- [MDN - WebRTC APIs](https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API)
97
98## Installation
99
100Make sure you have Node.js version 12 or higher. Node 14 is recommended and supported.
101
102To add the Amazon Chime SDK for JavaScript into an existing application,
103install the package directly from npm:
104
105```
106npm install amazon-chime-sdk-js --save
107```
108
109Note that the Amazon Chime SDK for JavaScript targets ES2015, which is fully compatible with
110all supported browsers.
111
112## Setup
113
114### Meeting session
115Create a meeting session in your client application.
116
117```js
118import {
119 ConsoleLogger,
120 DefaultDeviceController,
121 DefaultMeetingSession,
122 LogLevel,
123 MeetingSessionConfiguration
124} from 'amazon-chime-sdk-js';
125
126const logger = new ConsoleLogger('MyLogger', LogLevel.INFO);
127const deviceController = new DefaultDeviceController(logger);
128
129// You need responses from server-side Chime API. See below for details.
130const meetingResponse = /* The response from the CreateMeeting API action */;
131const attendeeResponse = /* The response from the CreateAttendee or BatchCreateAttendee API action */;
132const configuration = new MeetingSessionConfiguration(meetingResponse, attendeeResponse);
133
134// In the usage examples below, you will use this meetingSession object.
135const meetingSession = new DefaultMeetingSession(
136 configuration,
137 logger,
138 deviceController
139);
140```
141
142#### Getting responses from your server application
143
144You can use an AWS SDK, the AWS Command Line Interface (AWS CLI), or the REST API
145to make API calls. In this section, you will use the AWS SDK for JavaScript in your server application, e.g. Node.js.
146See [Amazon Chime SDK API Reference](https://docs.aws.amazon.com/chime/latest/APIReference/Welcome.html) for more information.
147
148> ⚠️ The server application does not require the Amazon Chime SDK for JavaScript.
149
150```js
151const AWS = require('aws-sdk');
152const { v4: uuid } = require('uuid');
153
154// You must use "us-east-1" as the region for Chime API and set the endpoint.
155const chime = new AWS.Chime({ region: 'us-east-1' });
156chime.endpoint = new AWS.Endpoint('https://service.chime.aws.amazon.com');
157
158const meetingResponse = await chime.createMeeting({
159 ClientRequestToken: uuid(),
160 MediaRegion: 'us-west-2' // Specify the region in which to create the meeting.
161}).promise();
162
163const attendeeResponse = await chime.createAttendee({
164 MeetingId: meetingResponse.Meeting.MeetingId,
165 ExternalUserId: uuid() // Link the attendee to an identity managed by your application.
166}).promise();
167```
168
169Now securely transfer the `meetingResponse` and `attendeeResponse` objects to your client application.
170These objects contain all the information needed for a client application using the Amazon Chime SDK for JavaScript to join the meeting.
171
172The value of the MediaRegion parameter in the createMeeting() should ideally be set to the one of the media regions which is closest to the user creating a meeting. An implementation can be found under the topic 'Choosing the nearest media Region' in the [Amazon Chime SDK Media Regions documentation](https://docs.aws.amazon.com/chime/latest/dg/chime-sdk-meetings-regions.html).
173
174### Messaging session
175Create a messaging session in your client application to receive messages from Amazon Chime SDK for Messaging.
176
177```js
178import * as AWS from 'aws-sdk/global';
179import * as Chime from 'aws-sdk/clients/chime';
180
181import {
182 ConsoleLogger,
183 DefaultMessagingSession,
184 LogLevel,
185 MessagingSessionConfiguration,
186} from 'amazon-chime-sdk-js';
187
188const logger = new ConsoleLogger('SDK', LogLevel.INFO);
189
190// You will need AWS credentials configured before calling AWS or Amazon Chime APIs.
191const chime = new Chime({ region: 'us-east-1' });
192const endpoint = await chime.getMessagingSessionEndpoint().promise();
193
194const userArn = /* The userArn */;
195const sessionId = /* The sessionId */;
196const configuration = new MessagingSessionConfiguration(userArn, sessionId, endpoint.Endpoint.Url, chime, AWS);
197const messagingSession = new DefaultMessagingSession(configuration, logger);
198
199```
200## Building and testing
201
202```
203git fetch --tags https://github.com/aws/amazon-chime-sdk-js
204npm run build
205npm run test
206```
207
208After running `npm run test` the first time, you can use `npm run test:fast` to
209speed up the test suite.
210
211Tags are fetched in order to correctly generate versioning metadata.
212
213To view code coverage results open `coverage/index.html` in your browser
214after running `npm run test`.
215
216## Generating the documentation
217
218To generate JavaScript API reference documentation run:
219
220```
221npm run build
222npm run doc
223```
224
225Then open `docs/index.html` in your browser.
226
227## Reporting a suspected vulnerability
228
229If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our
230[vulnerability reporting page](https://aws.amazon.com/security/vulnerability-reporting/).
231Please do **not** create a public GitHub issue.
232
233## Usage
234
235- [Device](#device)
236- [Starting a session](#starting-a-session)
237- [Audio](#audio)
238- [Video](#video)
239- [Screen and content share](#screen-and-content-share)
240- [Attendees](#attendees)
241- [Monitoring and alerts](#monitoring-and-alerts)
242- [Stopping a session](#stopping-a-session)
243- [Meeting readiness checker](#meeting-readiness-checker)
244- [Selecting an Audio Profile](#selecting-an-audio-profile)
245- [Starting a Messaging Session](#starting-a-messaging-session)
246
247### Device
248
249> Note: Before starting a session, you need to choose your microphone, speaker, and camera.
250
251**Use case 1.** List audio input, audio output, and video input devices. The browser will ask for microphone and camera permissions.
252
253With the `forceUpdate` parameter set to true, cached device information is discarded and updated after the device label trigger is called. In some cases, builders need to delay the triggering of permission dialogs, e.g., when joining a meeting in view-only mode, and then later be able to trigger a permission prompt in order to show device labels; specifying `forceUpdate` allows this to occur.
254
255```js
256const audioInputDevices = await meetingSession.audioVideo.listAudioInputDevices();
257const audioOutputDevices = await meetingSession.audioVideo.listAudioOutputDevices();
258const videoInputDevices = await meetingSession.audioVideo.listVideoInputDevices();
259
260// An array of MediaDeviceInfo objects
261audioInputDevices.forEach(mediaDeviceInfo => {
262 console.log(`Device ID: ${mediaDeviceInfo.deviceId} Microphone: ${mediaDeviceInfo.label}`);
263});
264```
265
266**Use case 2.** Choose audio input and audio output devices by passing the `deviceId` of a `MediaDeviceInfo` object.
267Note that you need to call `listAudioInputDevices` and `listAudioOutputDevices` first.
268
269```js
270const audioInputDeviceInfo = /* An array item from meetingSession.audioVideo.listAudioInputDevices */;
271await meetingSession.audioVideo.chooseAudioInputDevice(audioInputDeviceInfo.deviceId);
272
273const audioOutputDeviceInfo = /* An array item from meetingSession.audioVideo.listAudioOutputDevices */;
274await meetingSession.audioVideo.chooseAudioOutputDevice(audioOutputDeviceInfo.deviceId);
275```
276
277**Use case 3.** Choose a video input device by passing the `deviceId` of a `MediaDeviceInfo` object.
278Note that you need to call `listVideoInputDevices` first.
279
280If there is an LED light next to the attendee's camera, it will be turned on indicating that it is now capturing from the camera.
281You probably want to choose a video input device when you start sharing your video.
282
283```js
284const videoInputDeviceInfo = /* An array item from meetingSession.audioVideo.listVideoInputDevices */;
285await meetingSession.audioVideo.chooseVideoInputDevice(videoInputDeviceInfo.deviceId);
286
287// You can pass null to choose none. If the previously chosen camera has an LED light on,
288// it will turn off indicating the camera is no longer capturing.
289await meetingSession.audioVideo.chooseVideoInputDevice(null);
290```
291
292**Use case 4.** Add a device change observer to receive the updated device list.
293For example, when you pair Bluetooth headsets with your computer, `audioInputsChanged` and `audioOutputsChanged` are called
294with the device list including headsets.
295
296```js
297const observer = {
298 audioInputsChanged: freshAudioInputDeviceList => {
299 // An array of MediaDeviceInfo objects
300 freshAudioInputDeviceList.forEach(mediaDeviceInfo => {
301 console.log(`Device ID: ${mediaDeviceInfo.deviceId} Microphone: ${mediaDeviceInfo.label}`);
302 });
303 },
304 audioOutputsChanged: freshAudioOutputDeviceList => {
305 console.log('Audio outputs updated: ', freshAudioOutputDeviceList);
306 },
307 videoInputsChanged: freshVideoInputDeviceList => {
308 console.log('Video inputs updated: ', freshVideoInputDeviceList);
309 }
310};
311
312meetingSession.audioVideo.addDeviceChangeObserver(observer);
313````
314
315### Starting a session
316
317**Use case 5.** Start a session. To hear audio, you need to bind a device and stream to an `<audio>` element.
318Once the session has started, you can talk and listen to attendees.
319Make sure you have chosen your microphone and speaker (See the "Device" section), and at least one other attendee has joined the session.
320
321```js
322const audioElement = /* HTMLAudioElement object e.g. document.getElementById('audio-element-id') */;
323meetingSession.audioVideo.bindAudioElement(audioElement);
324
325const observer = {
326 audioVideoDidStart: () => {
327 console.log('Started');
328 }
329};
330
331meetingSession.audioVideo.addObserver(observer);
332
333meetingSession.audioVideo.start();
334```
335
336**Use case 6.** Add an observer to receive session lifecycle events: connecting, start, and stop.
337
338> Note: You can remove an observer by calling `meetingSession.audioVideo.removeObserver(observer)`.
339In a component-based architecture (such as React, Vue, and Angular), you may need to add an observer
340when a component is mounted, and remove it when unmounted.
341
342```js
343const observer = {
344 audioVideoDidStart: () => {
345 console.log('Started');
346 },
347 audioVideoDidStop: sessionStatus => {
348 // See the "Stopping a session" section for details.
349 console.log('Stopped with a session status code: ', sessionStatus.statusCode());
350 },
351 audioVideoDidStartConnecting: reconnecting => {
352 if (reconnecting) {
353 // e.g. the WiFi connection is dropped.
354 console.log('Attempting to reconnect');
355 }
356 }
357};
358
359meetingSession.audioVideo.addObserver(observer);
360```
361
362### Audio
363
364> Note: So far, you've added observers to receive device and session lifecycle events.
365In the following use cases, you'll use the real-time API methods to send and receive volume indicators and control mute state.
366
367**Use case 7.** Mute and unmute an audio input.
368
369```js
370// Mute
371meetingSession.audioVideo.realtimeMuteLocalAudio();
372
373// Unmute
374const unmuted = meetingSession.audioVideo.realtimeUnmuteLocalAudio();
375if (unmuted) {
376 console.log('Other attendees can hear your audio');
377} else {
378 // See the realtimeSetCanUnmuteLocalAudio use case below.
379 console.log('You cannot unmute yourself');
380}
381```
382
383**Use case 8.** To check whether the local microphone is muted, use this method rather than keeping track of your own mute state.
384
385```js
386const muted = meetingSession.audioVideo.realtimeIsLocalAudioMuted();
387if (muted) {
388 console.log('You are muted');
389} else {
390 console.log('Other attendees can hear your audio');
391}
392```
393
394**Use case 9.** Disable unmute. If you want to prevent users from unmuting themselves (for example during a presentation), use these methods rather than keeping track of your own can-unmute state.
395
396```js
397meetingSession.audioVideo.realtimeSetCanUnmuteLocalAudio(false);
398
399// Optional: Force mute.
400meetingSession.audioVideo.realtimeMuteLocalAudio();
401
402const unmuted = meetingSession.audioVideo.realtimeUnmuteLocalAudio();
403console.log(`${unmuted} is false. You cannot unmute yourself`)
404```
405
406**Use case 10.** Subscribe to volume changes of a specific attendee. You can use this to build a real-time volume indicator UI.
407
408```js
409import { DefaultModality } from 'amazon-chime-sdk-js';
410
411// This is your attendee ID. You can also subscribe to another attendee's ID.
412// See the "Attendees" section for an example on how to retrieve other attendee IDs
413// in a session.
414const presentAttendeeId = meetingSession.configuration.credentials.attendeeId;
415
416meetingSession.audioVideo.realtimeSubscribeToVolumeIndicator(
417 presentAttendeeId,
418 (attendeeId, volume, muted, signalStrength) => {
419 const baseAttendeeId = new DefaultModality(attendeeId).base();
420 if (baseAttendeeId !== attendeeId) {
421 // See the "Screen and content share" section for details.
422 console.log(`The volume of ${baseAttendeeId}'s content changes`);
423 }
424
425 // A null value for any field means that it has not changed.
426 console.log(`${attendeeId}'s volume data: `, {
427 volume, // a fraction between 0 and 1
428 muted, // a boolean
429 signalStrength // 0 (no signal), 0.5 (weak), 1 (strong)
430 });
431 }
432);
433```
434
435**Use case 11.** Subscribe to mute or signal strength changes of a specific attendee. You can use this to build UI for only mute or only signal strength changes.
436
437```js
438// This is your attendee ID. You can also subscribe to another attendee's ID.
439// See the "Attendees" section for an example on how to retrieve other attendee IDs
440// in a session.
441const presentAttendeeId = meetingSession.configuration.credentials.attendeeId;
442
443// To track mute changes
444meetingSession.audioVideo.realtimeSubscribeToVolumeIndicator(
445 presentAttendeeId,
446 (attendeeId, volume, muted, signalStrength) => {
447 // A null value for volume, muted and signalStrength field means that it has not changed.
448 if (muted === null) {
449 // muted state has not changed, ignore volume and signalStrength changes
450 return;
451 }
452
453 // mute state changed
454 console.log(`${attendeeId}'s mute state changed: `, {
455 muted, // a boolean
456 });
457 }
458);
459
460// To track signal strength changes
461meetingSession.audioVideo.realtimeSubscribeToVolumeIndicator(
462 presentAttendeeId,
463 (attendeeId, volume, muted, signalStrength) => {
464 // A null value for volume, muted and signalStrength field means that it has not changed.
465 if (signalStrength === null) {
466 // signalStrength has not changed, ignore volume and muted changes
467 return;
468 }
469
470 // signal strength changed
471 console.log(`${attendeeId}'s signal strength changed: `, {
472 signalStrength // 0 (no signal), 0.5 (weak), 1 (strong)
473 });
474 }
475);
476```
477
478**Use case 12.** Detect the most active speaker. For example, you can enlarge the active speaker's video element if available.
479
480```js
481import { DefaultActiveSpeakerPolicy } from 'amazon-chime-sdk-js';
482
483const activeSpeakerCallback = attendeeIds => {
484 if (attendeeIds.length) {
485 console.log(`${attendeeIds[0]} is the most active speaker`);
486 }
487};
488
489meetingSession.audioVideo.subscribeToActiveSpeakerDetector(
490 new DefaultActiveSpeakerPolicy(),
491 activeSpeakerCallback
492);
493````
494
495### Video
496
497> Note: In Chime SDK terms, a video tile is an object containing an attendee ID,
498a video stream, etc. To view a video in your application, you must bind a tile to a `<video>` element.
499> - Make sure you bind a tile to the same video element until the tile is removed.
500> - A local video tile can be identified using `localTile` property.
501> - A tile is created with a new tile ID when the same remote attendee restarts the video.
502
503**Use case 13.** Start sharing your video. The local video element is flipped horizontally (mirrored mode).
504
505```js
506const videoElement = /* HTMLVideoElement object e.g. document.getElementById('video-element-id') */;
507
508// Make sure you have chosen your camera. In this use case, you will choose the first device.
509const videoInputDevices = await meetingSession.audioVideo.listVideoInputDevices();
510
511// The camera LED light will turn on indicating that it is now capturing.
512// See the "Device" section for details.
513await meetingSession.audioVideo.chooseVideoInputDevice(videoInputDevices[0].deviceId);
514
515const observer = {
516 // videoTileDidUpdate is called whenever a new tile is created or tileState changes.
517 videoTileDidUpdate: tileState => {
518 // Ignore a tile without attendee ID and other attendee's tile.
519 if (!tileState.boundAttendeeId || !tileState.localTile) {
520 return;
521 }
522
523 meetingSession.audioVideo.bindVideoElement(tileState.tileId, videoElement);
524 }
525};
526
527meetingSession.audioVideo.addObserver(observer);
528
529meetingSession.audioVideo.startLocalVideoTile();
530```
531
532**Use case 14.** Stop sharing your video.
533
534```js
535const videoElement = /* HTMLVideoElement object e.g. document.getElementById('video-element-id') */;
536
537let localTileId = null;
538const observer = {
539 videoTileDidUpdate: tileState => {
540 // Ignore a tile without attendee ID and other attendee's tile.
541 if (!tileState.boundAttendeeId || !tileState.localTile) {
542 return;
543 }
544
545 // videoTileDidUpdate is also invoked when you call startLocalVideoTile or tileState changes.
546 // The tileState.active can be false in poor Internet connection, when the user paused the video tile, or when the video tile first arrived.
547 console.log(`If you called stopLocalVideoTile, ${tileState.active} is false.`);
548 meetingSession.audioVideo.bindVideoElement(tileState.tileId, videoElement);
549 localTileId = tileState.tileId;
550 },
551 videoTileWasRemoved: tileId => {
552 if (localTileId === tileId) {
553 console.log(`You called removeLocalVideoTile. videoElement can be bound to another tile.`);
554 localTileId = null;
555 }
556 }
557};
558
559meetingSession.audioVideo.addObserver(observer);
560
561meetingSession.audioVideo.stopLocalVideoTile();
562
563// Optional: You can remove the local tile from the session.
564meetingSession.audioVideo.removeLocalVideoTile();
565```
566
567**Use case 15.** View one attendee video, e.g. in a 1-on-1 session.
568
569```js
570const videoElement = /* HTMLVideoElement object e.g. document.getElementById('video-element-id') */;
571
572const observer = {
573 // videoTileDidUpdate is called whenever a new tile is created or tileState changes.
574 videoTileDidUpdate: tileState => {
575 // Ignore a tile without attendee ID, a local tile (your video), and a content share.
576 if (!tileState.boundAttendeeId || tileState.localTile || tileState.isContent) {
577 return;
578 }
579
580 meetingSession.audioVideo.bindVideoElement(tileState.tileId, videoElement);
581 }
582};
583
584meetingSession.audioVideo.addObserver(observer);
585```
586
587**Use case 16.** View up to 25 attendee videos. Assume that you have 25 video elements in your application,
588and that an empty cell means it's taken.
589
590```js
591/*
592 No one is sharing video e.g. 9 attendee videos (9 empty cells)
593
594 Next available: Next available:
595 videoElements[0] videoElements[7]
596 ╔════╦════╦════╦════╦════╗ ╔════╦════╦════╦════╦════╗
597 ║ 0 ║ 1 ║ 2 ║ 3 ║ 4 ║ ║ ║ ║ ║ ║ ║
598 ╠════╬════╬════╬════╬════╣ ╠════╬════╬════╬════╬════╣
599 ║ 5 ║ 6 ║ 7 ║ 8 ║ 9 ║ ║ ║ ║ 7 ║ 8 ║ ║
600 ╠════╬════╬════╬════╬════╣ ╠════╬════╬════╬════╬════╣
601 ║ 10 ║ 11 ║ 12 ║ 13 ║ 14 ║ ║ 10 ║ ║ 12 ║ 13 ║ 14 ║
602 ╠════╬════╬════╬════╬════╣ ╠════╬════╬════╬════╬════╣
603 ║ 15 ║ 16 ║ 17 ║ 18 ║ 19 ║ ║ 15 ║ 16 ║ 17 ║ 18 ║ 19 ║
604 ╠════╬════╬════╬════╬════╣ ╠════╬════╬════╬════╬════╣
605 ║ 20 ║ 21 ║ 22 ║ 23 ║ 24 ║ ║ 20 ║ 21 ║ 22 ║ 23 ║ 24 ║
606 ╚════╩════╩════╩════╩════╝ ╚════╩════╩════╩════╩════╝
607 */
608const videoElements = [/* an array of 25 HTMLVideoElement objects in your application */];
609
610// index-tileId pairs
611const indexMap = {};
612
613const acquireVideoElement = tileId => {
614 // Return the same video element if already bound.
615 for (let i = 0; i < 25; i += 1) {
616 if (indexMap[i] === tileId) {
617 return videoElements[i];
618 }
619 }
620 // Return the next available video element.
621 for (let i = 0; i < 25; i += 1) {
622 if (!indexMap.hasOwnProperty(i)) {
623 indexMap[i] = tileId;
624 return videoElements[i];
625 }
626 }
627 throw new Error('no video element is available');
628};
629
630const releaseVideoElement = tileId => {
631 for (let i = 0; i < 25; i += 1) {
632 if (indexMap[i] === tileId) {
633 delete indexMap[i];
634 return;
635 }
636 }
637};
638
639const observer = {
640 // videoTileDidUpdate is called whenever a new tile is created or tileState changes.
641 videoTileDidUpdate: tileState => {
642 // Ignore a tile without attendee ID, a local tile (your video), and a content share.
643 if (!tileState.boundAttendeeId || tileState.localTile || tileState.isContent) {
644 return;
645 }
646
647 meetingSession.audioVideo.bindVideoElement(
648 tileState.tileId,
649 acquireVideoElement(tileState.tileId)
650 );
651 },
652 videoTileWasRemoved: tileId => {
653 releaseVideoElement(tileId);
654 }
655};
656
657meetingSession.audioVideo.addObserver(observer);
658```
659
660**Use case 17.** Add an observer to know all the remote video sources when changed.
661```js
662const observer = {
663 remoteVideoSourcesDidChange: videoSources => {
664 videoSources.forEach(videoSource => {
665 const { attendee } = videoSource;
666 console.log(`An attendee (${attendee.attendeeId} ${attendee.externalUserId}) is sending video`);
667 });
668 }
669};
670
671meetingSession.audioVideo.addObserver(observer);
672```
673You can also call below method to know all the remote video sources:
674> Note: `getRemoteVideoSources` method is different from `getAllRemoteVideoTiles`,
675`getRemoteVideoSources` returns all the remote video sources that are available to be viewed,
676while `getAllRemoteVideoTiles` returns the ones that are actually being seen.
677```js
678const videoSources = meetingSession.audioVideo.getRemoteVideoSources();
679videoSources.forEach(videoSource => {
680 const { attendee } = videoSource;
681 console.log(`An attendee (${attendee.attendeeId} ${attendee.externalUserId}) is sending video`);
682});
683```
684
685### Screen and content share
686
687> Note: When you or other attendees share content (a screen capture, a video file, or any other MediaStream object),
688the content attendee (attendee-id#content) joins the session and shares content as if a regular attendee shares a video.
689>
690> For example, your attendee ID is "my-id". When you call `meetingSession.audioVideo.startContentShare`,
691the content attendee "my-id#content" will join the session and share your content.
692
693**Use case 18.** Start sharing your screen.
694
695```js
696import { DefaultModality } from 'amazon-chime-sdk-js';
697
698const observer = {
699 videoTileDidUpdate: tileState => {
700 // Ignore a tile without attendee ID and videos.
701 if (!tileState.boundAttendeeId || !tileState.isContent) {
702 return;
703 }
704
705 const yourAttendeeId = meetingSession.configuration.credentials.attendeeId;
706
707 // tileState.boundAttendeeId is formatted as "attendee-id#content".
708 const boundAttendeeId = tileState.boundAttendeeId;
709
710 // Get the attendee ID from "attendee-id#content".
711 const baseAttendeeId = new DefaultModality(boundAttendeeId).base();
712 if (baseAttendeeId === yourAttendeeId) {
713 console.log('You called startContentShareFromScreenCapture');
714 }
715 },
716 contentShareDidStart: () => {
717 console.log('Screen share started');
718 },
719 contentShareDidStop: () => {
720 // Chime SDK allows 2 simultaneous content shares per meeting.
721 // This method will be invoked if two attendees are already sharing content
722 // when you call startContentShareFromScreenCapture or startContentShare.
723 console.log('Screen share stopped');
724 }
725};
726
727meetingSession.audioVideo.addContentShareObserver(observer);
728meetingSession.audioVideo.addObserver(observer);
729
730// A browser will prompt the user to choose the screen.
731const contentShareStream = await meetingSession.audioVideo.startContentShareFromScreenCapture();
732```
733
734If you want to display the content share stream for the sharer, you can bind the returned content share stream to a
735 video element using `connectVideoStreamToVideoElement` from DefaultVideoTile.
736
737```js
738DefaultVideoTile.connectVideoStreamToVideoElement(contentShareStream, videoElement, false);
739```
740
741**Use case 19.** Start sharing your screen in an environment that does not support a screen picker dialog. e.g. Electron
742
743```js
744const sourceId = /* Window or screen ID e.g. the ID of a DesktopCapturerSource object in Electron */;
745
746await meetingSession.audioVideo.startContentShareFromScreenCapture(sourceId);
747```
748
749**Use case 20.** Start streaming your video file from an `<input>` element of type `file`.
750
751```js
752const videoElement = /* HTMLVideoElement object e.g. document.getElementById('video-element-id') */;
753const inputElement = /* HTMLInputElement object e.g. document.getElementById('input-element-id') */;
754
755inputElement.addEventListener('change', async () => {
756 const file = inputElement.files[0];
757 const url = URL.createObjectURL(file);
758 videoElement.src = url;
759 await videoElement.play();
760
761 const mediaStream = videoElement.captureStream(); /* use mozCaptureStream for Firefox e.g. videoElement
762.mozCaptureStream(); */
763 await meetingSession.audioVideo.startContentShare(mediaStream);
764 inputElement.value = '';
765});
766```
767
768**Use case 21.** Stop sharing your screen or content.
769
770```js
771const observer = {
772 contentShareDidStop: () => {
773 console.log('Content share stopped');
774 }
775};
776
777meetingSession.audioVideo.addContentShareObserver(observer);
778
779await meetingSession.audioVideo.stopContentShare();
780```
781
782**Use case 22.** View up to 2 attendee content or screens. Chime SDK allows 2 simultaneous content shares per meeting.
783
784```js
785import { DefaultModality } from 'amazon-chime-sdk-js';
786
787const videoElementStack = [/* an array of 2 HTMLVideoElement objects in your application */];
788
789// tileId-videoElement map
790const tileMap = {};
791
792const observer = {
793 videoTileDidUpdate: tileState => {
794 // Ignore a tile without attendee ID and videos.
795 if (!tileState.boundAttendeeId || !tileState.isContent) {
796 return;
797 }
798
799 const yourAttendeeId = meetingSession.configuration.credentials.attendeeId;
800
801 // tileState.boundAttendeeId is formatted as "attendee-id#content".
802 const boundAttendeeId = tileState.boundAttendeeId;
803
804 // Get the attendee ID from "attendee-id#content".
805 const baseAttendeeId = new DefaultModality(boundAttendeeId).base();
806 if (baseAttendeeId !== yourAttendeeId) {
807 console.log(`${baseAttendeeId} is sharing screen now`);
808
809 // Get the already bound video element if available, or use an unbound element.
810 const videoElement = tileMap[tileState.tileId] || videoElementStack.pop();
811 if (videoElement) {
812 tileMap[tileState.tileId] = videoElement;
813 meetingSession.audioVideo.bindVideoElement(tileState.tileId, videoElement);
814 } else {
815 console.log('No video element is available');
816 }
817 }
818 },
819 videoTileWasRemoved: tileId => {
820 // Release the unused video element.
821 const videoElement = tileMap[tileId];
822 if (videoElement) {
823 videoElementStack.push(videoElement);
824 delete tileMap[tileId];
825 }
826 }
827};
828
829meetingSession.audioVideo.addObserver(observer);
830```
831
832### Attendees
833
834**Use case 23.** Subscribe to attendee presence changes. When an attendee joins or leaves a session,
835the callback receives `presentAttendeeId` and `present` (a boolean).
836
837```js
838const attendeePresenceSet = new Set();
839const callback = (presentAttendeeId, present) => {
840 console.log(`Attendee ID: ${presentAttendeeId} Present: ${present}`);
841 if (present) {
842 attendeePresenceSet.add(presentAttendeeId);
843 } else {
844 attendeePresenceSet.delete(presentAttendeeId);
845 }
846};
847
848meetingSession.audioVideo.realtimeSubscribeToAttendeeIdPresence(callback);
849```
850
851**Use case 24.** Create a simple roster by subscribing to attendee presence and volume changes.
852
853```js
854import { DefaultModality } from 'amazon-chime-sdk-js';
855
856const roster = {};
857
858meetingSession.audioVideo.realtimeSubscribeToAttendeeIdPresence(
859 (presentAttendeeId, present) => {
860 if (!present) {
861 delete roster[presentAttendeeId];
862 return;
863 }
864
865 meetingSession.audioVideo.realtimeSubscribeToVolumeIndicator(
866 presentAttendeeId,
867 (attendeeId, volume, muted, signalStrength) => {
868 const baseAttendeeId = new DefaultModality(attendeeId).base();
869 if (baseAttendeeId !== attendeeId) {
870 // Optional: Do not include the content attendee (attendee-id#content) in the roster.
871 // See the "Screen and content share" section for details.
872 return;
873 }
874
875 if (roster.hasOwnProperty(attendeeId)) {
876 // A null value for any field means that it has not changed.
877 roster[attendeeId].volume = volume; // a fraction between 0 and 1
878 roster[attendeeId].muted = muted; // A boolean
879 roster[attendeeId].signalStrength = signalStrength; // 0 (no signal), 0.5 (weak), 1 (strong)
880 } else {
881 // Add an attendee.
882 // Optional: You can fetch more data, such as attendee name,
883 // from your server application and set them here.
884 roster[attendeeId] = {
885 attendeeId,
886 volume,
887 muted,
888 signalStrength
889 };
890 }
891 }
892 );
893 }
894);
895```
896
897### Monitoring and alerts
898
899**Use case 25.** Add an observer to receive video metrics. See `AudioVideoObserver` for more available metrics,
900such as WebRTC statistics processed by Chime SDK.
901
902```js
903const observer = {
904 videoSendHealthDidChange: (bitrateKbps, packetsPerSecond) => {
905 console.log(`Sending bitrate in kilobits per second: ${bitrateKbps} and ${packetsPerSecond}`);
906 },
907 videoSendBandwidthDidChange: (newBandwidthKbps, oldBandwidthKbps) => {
908 console.log(`Sending bandwidth changed from ${oldBandwidthKbps} to ${newBandwidthKbps}`);
909 },
910 videoReceiveBandwidthDidChange: (newBandwidthKbps, oldBandwidthKbps) => {
911 console.log(`Receiving bandwidth changed from ${oldBandwidthKbps} to ${newBandwidthKbps}`);
912 }
913};
914
915meetingSession.audioVideo.addObserver(observer);
916```
917
918**Use case 26.** Add an observer to receive alerts. You can use these alerts to notify users of connection problems.
919
920```js
921const observer = {
922 connectionDidBecomePoor: () => {
923 console.log('Your connection is poor');
924 },
925 connectionDidSuggestStopVideo: () => {
926 console.log('Recommend turning off your video');
927 },
928 videoSendDidBecomeUnavailable: () => {
929 // Chime SDK allows a total of 25 simultaneous videos per meeting.
930 // If you try to share more video, this method will be called.
931 // See videoAvailabilityDidChange below to find out when it becomes available.
932 console.log('You cannot share your video');
933 },
934 videoAvailabilityDidChange: videoAvailability => {
935 // canStartLocalVideo will also be true if you are already sharing your video.
936 if (videoAvailability.canStartLocalVideo) {
937 console.log('You can share your video');
938 } else {
939 console.log('You cannot share your video');
940 }
941 }
942};
943
944meetingSession.audioVideo.addObserver(observer);
945```
946
947### Stopping a session
948
949**Use case 27.** Leave a session.
950
951```js
952import { MeetingSessionStatusCode } from 'amazon-chime-sdk-js';
953
954const observer = {
955 audioVideoDidStop: sessionStatus => {
956 const sessionStatusCode = sessionStatus.statusCode();
957 if (sessionStatusCode === MeetingSessionStatusCode.Left) {
958 /*
959 - You called meetingSession.audioVideo.stop().
960 - When closing a browser window or page, Chime SDK attempts to leave the session.
961 */
962 console.log('You left the session');
963 } else {
964 console.log('Stopped with a session status code: ', sessionStatusCode);
965 }
966 }
967};
968
969meetingSession.audioVideo.addObserver(observer);
970
971meetingSession.audioVideo.stop();
972```
973
974**Use case 28.** Add an observer to get notified when a session has ended.
975
976```js
977import { MeetingSessionStatusCode } from 'amazon-chime-sdk-js';
978
979const observer = {
980 audioVideoDidStop: sessionStatus => {
981 const sessionStatusCode = sessionStatus.statusCode();
982 if (sessionStatusCode === MeetingSessionStatusCode.MeetingEnded) {
983 /*
984 - You (or someone else) have called the DeleteMeeting API action in your server application.
985 - You attempted to join a deleted meeting.
986 - No audio connections are present in the meeting for more than five minutes.
987 - Fewer than two audio connections are present in the meeting for more than 30 minutes.
988 - Screen share viewer connections are inactive for more than 30 minutes.
989 - The meeting time exceeds 24 hours.
990 See https://docs.aws.amazon.com/chime/latest/dg/mtgs-sdk-mtgs.html for details.
991 */
992 console.log('The session has ended');
993 } else {
994 console.log('Stopped with a session status code: ', sessionStatusCode);
995 }
996 }
997};
998
999meetingSession.audioVideo.addObserver(observer);
1000```
1001
1002### Meeting readiness checker
1003
1004**Use case 29.** Initialize the meeting readiness checker.
1005
1006```js
1007import { DefaultMeetingReadinessChecker } from 'amazon-chime-sdk-js';
1008
1009// In the usage examples below, you will use this meetingReadinessChecker object.
1010const meetingReadinessChecker = new DefaultMeetingReadinessChecker(logger, meetingSession);
1011```
1012
1013**Use case 30.** Use the meeting readiness checker to perform local checks.
1014
1015```js
1016import { CheckAudioInputFeedback } from 'amazon-chime-sdk-js';
1017
1018const audioInputDeviceInfo = /* An array item from meetingSession.audioVideo.listAudioInputDevices */;
1019const audioInputFeedback = await meetingReadinessChecker.checkAudioInput(audioInputDeviceInfo.deviceId);
1020
1021switch (audioInputFeedback) {
1022 case CheckAudioInputFeedback.Succeeded:
1023 console.log('Succeeded');
1024 break;
1025 case CheckAudioInputFeedback.Failed:
1026 console.log('Failed');
1027 break;
1028 case CheckAudioInputFeedback.PermissionDenied:
1029 console.log('Permission denied');
1030 break;
1031}
1032```
1033
1034**Use case 31.** Use the meeting readiness checker to perform end-to-end checks, e.g. audio, video, and content share.
1035
1036```js
1037import {
1038 CheckAudioConnectivityFeedback,
1039 CheckContentShareConnectivityFeedback,
1040 CheckVideoConnectivityFeedback
1041} from 'amazon-chime-sdk-js';
1042
1043// Tests audio connection
1044const audioDeviceInfo = /* An array item from meetingSession.audioVideo.listAudioInputDevices */;
1045const audioFeedback = await meetingReadinessChecker.checkAudioConnectivity(audioDeviceInfo.deviceId);
1046console.log(`Feedback result: ${CheckAudioConnectivityFeedback[audioFeedback]}`);
1047
1048// Test video connection
1049const videoInputInfo = /* An array item from meetingSession.audioVideo.listVideoInputDevices */;
1050const videoFeedback = await meetingReadinessChecker.checkVideoConnectivity(videoInputInfo.deviceId);
1051console.log(`Feedback result: ${CheckVideoConnectivityFeedback[videoFeedback]}`);
1052
1053// Tests content share connectivity
1054const contentShareFeedback = await meetingReadinessChecker.checkContentShareConnectivity();
1055console.log(`Feedback result: ${CheckContentShareConnectivityFeedback[contentShareFeedback]}`);
1056```
1057
1058**Use case 32.** Use the meeting readiness checker to perform network checks, e.g. TCP and UDP.
1059
1060```js
1061import {
1062 CheckNetworkUDPConnectivityFeedback,
1063 CheckNetworkTCPConnectivityFeedback
1064} from 'amazon-chime-sdk-js';
1065
1066// Tests for UDP network connectivity
1067const networkUDPFeedback = await meetingReadinessChecker.checkNetworkUDPConnectivity();
1068console.log(`Feedback result: ${CheckNetworkUDPConnectivityFeedback[networkUDPFeedback]}`);
1069
1070// Tests for TCP network connectivity
1071const networkTCPFeedback = await meetingReadinessChecker.checkNetworkTCPConnectivity();
1072console.log(`Feedback result: ${CheckNetworkTCPConnectivityFeedback[networkTCPFeedback]}`);
1073```
1074
1075### Selecting an audio profile
1076
1077**Use case 32.** Set the audio quality of the main audio input to optimize for speech or music:
1078
1079Use the following setting to optimize the audio bitrate of the main audio input for fullband speech with a mono channel:
1080
1081```js
1082meetingSession.audioVideo.setAudioProfile(AudioProfile.fullbandSpeechMono());
1083````
1084
1085**Use case 33.** Set the audio quality of content share audio to optimize for speech or music:
1086
1087Use the following setting to optimize the audio bitrate of content share audio for fullband music with a mono channel:
1088
1089```js
1090meetingSession.audioVideo.setContentAudioProfile(AudioProfile.fullbandMusicMono());
1091```
1092
1093### Starting a messaging session
1094
1095**Use case 34.** Setup an observer to receive events: connecting, start, stop and receive message; and
1096start a messaging session.
1097
1098> Note: You can remove an observer by calling `messagingSession.removeObserver(observer)`.
1099In a component-based architecture (such as React, Vue, and Angular), you may need to add an observer
1100when a component is mounted, and remove it when unmounted.
1101>
1102```js
1103const observer = {
1104 messagingSessionDidStart: () => {
1105 console.log('Session started');
1106 },
1107 messagingSessionDidStartConnecting: reconnecting => {
1108 if (reconnecting) {
1109 console.log('Start reconnecting');
1110 } else {
1111 console.log('Start connecting');
1112 }
1113 },
1114 messagingSessionDidStop: event => {
1115 console.log(`Closed: ${event.code} ${event.reason}`);
1116 },
1117 messagingSessionDidReceiveMessage: message => {
1118 console.log(`Receive message type ${message.type}`);
1119 }
1120};
1121
1122messagingSession.addObserver(observer);
1123messagingSession.start();
1124```
1125
1126## Notice
1127
1128The use of Amazon Voice Focus via this SDK involves the downloading and execution of code at runtime by end users.
1129
1130The use of Amazon Voice Focus runtime code is subject to additional notices. See [this NOTICES file](https://static.sdkassets.chime.aws/workers/NOTICES.txt) for details. You agree to make these additional notices available to all end users who use Amazon Voice Focus runtime code via this SDK.
1131
1132
1133The browser demo applications in the [demos directory](https://github.com/aws/amazon-chime-sdk-js/tree/master/demos) use [TensorFlow.js](https://github.com/tensorflow/tfjs) and pre-trained [TensorFlow.js models](https://github.com/tensorflow/tfjs-models) for image segmentation. Use of these third party models involves downloading and execution of code at runtime from [jsDelivr](https://www.jsdelivr.com/) by end user browsers. For the jsDelivr Acceptable Use Policy, please visit this [link](https://www.jsdelivr.com/terms/acceptable-use-policy-jsdelivr-net).
1134
1135The use of TensorFlow runtime code referenced above may be subject to additional license requirements. See the licenses page for TensorFlow.js [here](https://github.com/tensorflow/tfjs/blob/master/LICENSE) and TensorFlow.js models [here](https://github.com/tensorflow/tfjs-models/blob/master/LICENSE) for details.
1136
1137Live transcription using the Amazon Chime SDK for JavaScript is powered by Amazon Transcribe. Use of Amazon Transcribe is subject to the [AWS Service Terms](https://aws.amazon.com/service-terms/), including the terms specific to the AWS Machine Learning and Artificial Intelligence Services. Standard charges for Amazon Transcribe and Amazon Transcribe Medical will apply.
1138
1139You and your end users understand that recording Amazon Chime SDK meetings may be subject to laws or regulations regarding the recording of electronic communications. It is your and your end users’ responsibility to comply with all applicable laws regarding the recordings, including properly notifying all participants in a recorded session, or communication that the session or communication is being recorded, and obtain their consent.
1140
1141---
1142
1143Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.