Voice SDKs
...
Getting Started
Web Client SDK APIs-2
57 min
receive calls once the registration has happened, and when there is an incoming call, the callback registered for “call events” would get an event along with the details of the incoming call api name calllistenercallback args params type values callobj object { callid, callstate, calldirection, callstartedtime, remotedisplayname } callid {string} sip call id callstate {string} incoming calldirection {string} incoming callstartedtime {string} call start time remotedisplayname {string} callee name eventtype string incoming shows incoming call message connected open dialer callended close dialer activesession session continuity phone string username identifying the phone to which the call is coming exported to application ui in the following snippet,the ui states are appropriately modified based on the call events function calllistenercallback(callobj, eventtype, phone) { if (eventtype === 'incoming') { // incoming call setcallcoming(true) } else if (eventtype === 'connected') { // call in connected state setcallcoming(false) setcallstate(true) } else if (eventtype === 'callended') { // call ended setcallcoming(false) setcallstate(false) } else if (eventtype === 'terminated') { // call terminated setcallcoming(false) setcallstate(false) } } accept calls once the incoming call event is received, based on the user action the call can be accepted the api to do so is “call answer” as below the call object could be obtained by invoking the “getcall()” method in exwebclient object api name call answer args none exported to application ui function acceptcallhandler() { call = exwebclient getcall() call answer(); } the response event to accept calls comes in “calllistenercallback” successful acceptance results in a “connected” event other possible events are “callended” call ended locally “terminated” call terminated remotely function calllistenercallback(callobj, eventtype, phone) { if (eventtype === 'incoming') { // incoming call setcallcoming(true) } else if (eventtype === 'connected') { // call in connected state setcallcoming(false) setcallstate(true) } else if (eventtype === 'callended') { // call ended setcallcoming(false) setcallstate(false) } else if (eventtype === 'terminated') { // call terminated setcallcoming(false) setcallstate(false) } } hangup / reject calls once the incoming call event is received, based on the user action the call can be rejected the api to do so is “call hangup” as below api name call hangup args none exported to application ui function rejectcallhandler() { call = exwebclient getcall() call hangup(); } for call hangup by local user, the response comes as a “callended” event for call hangup by remote user,, the event comes as “terminated” function calllistenercallback(callobj, eventtype, phone) { if (eventtype === 'callended') { // call ended setcallcoming(false) setcallstate(false) } else if (eventtype === 'terminated') { // call terminated setcallcoming(false) setcallstate(false) } } mute / unmute calls once the call is in progress, based on the user action the call can be muted/unmuted the apis to do so are “call mute” and “call unmute” as below api name call mute args none exported to application ui api name call unmute args none exported to application ui you can also use a single api to toggle the mic using call mutetoggle api name call mutetoggle args none exported to application ui function mutehandler() { call = exwebclient getcall() //call mutetoggle(); // or if (!callonmute) { call mute() callonmute = true } else { call unmute() callonmute = false } } there is no callback event for mute call remains “connected” but with the mic muted this is a toggle operation hold / resume calls once the call is in progress, based on the user action the remote user can be set on hold/unhold the api to do so is “call hold” and “call unhold” as below api name call hold args none exported to application ui api name call unhold args none exported to application ui you can also use a single api to hold the remote caller using call holdtoggle function holdhandler() { call = exwebclient getcall() //call holdtoggle(); // or if (!callonhold) { call hold() callonhold = true } else { call unhold() callonhold = false } } there is no callback event for call hold call remains in “connected” but in sendonly mode this is a toggle operation send dtmf once the call is in progress, based on the user action the remote user can be sent dtmf digits the api to do so is “call senddtmf” as below api name call senddtmf args params type values digit string 0 9, a d, , # exported to application ui call = exwebclient getcall() if (call) { call senddtmf(digit); } multitab scenarios when the webrtc sdk is loaded in multiple tabs then all the instances will register with the backend and receive incoming call alerts there are two ways to avoid this, maintain a single login session for the user in your webapp so that only one instance of the webrtc sdk is loaded this is preferred maintain a parent child relationship across the tabs in your webapp so that call is handled only in the parent tab exotel webrtc sdk supports multiple tab sessions using broadcast channel in this feature, session listener and session callbacks can be used to get the indication on child tabs a sessionlistener creates a broadcast channel and sends a broadcast event to each child tab for the following events, incoming / connected / callended / re register when a child tab (as per the logic maintained by the “application backend” ) receives a session event, it may notify but not handle the callback when the parent tab is destroyed, a re register event comes to child tabs, based on the logic of the client, a child can opt to be the new parent note 1 the logic of maintaining the parent and child tabs has to be in “application backend” by the “customer” note 2 if multitab scenario is not used, there is no need to handle the events in the session callback api name sessionlistener args none exported to application ui sessionlistener(); // to be called during initialization api name sessioncallback args params type values callstate string incoming / connected / callended / re register incoming child tab to show a notification message connected child tab to close the notification message callended child tab to close the notification message re register child tab to register when parent tab is closed ice gathering state \<state> ice gathering state changed \<state> will be the new ice gathering state (e g , new, gathering, complete) ice connection state \<state> ice connection state changed \<state> will be the new ice connection state (e g , new, checking, connected, disconnected, failed, closed) media permission denied user denied media (microphone/camera) permissions phone string username identifying the phone to which the call is coming exported to application ui a sample code snippet for session callback is as below function sessioncallback(callstate, phone) { / sessioncallback is triggered whenever an incoming call arrives which needs to be handled across tabs / switch(callstate){ case 'incoming' console log('incoming call' + phone) / display a different notification popup in case of child tabs / if(window\ sessionstorage getitem('activesessiontab') !== 'parent0'){ const message = 'incoming call from ' + phone + ' ,switch tab to find dialpad' setmessage(message); } break; case 'callended' / when call is either accepted or rejected then this is gets shutdown / console log('call ended' + phone) setopen(false); break; case 'connected' / when call is connected close the notification popup on child tabs / console log('call connected' + phone) setopen(false); break; case 're register' / in case if the main/parent tab is closed then make the subsequent tab in the tab list as the parent tab and send register for the same and also make that tab as the master / // ice gathering state events case 'ice gathering state new' case 'ice gathering state gathering' case 'ice gathering state complete' console log('ice state change ', callstate, 'for call from ', phone); // handle ice state changes as needed break; // media permission error case 'media permission denied' console log('media permission denied for call from ', phone); showerrormessage('microphone access is required for calls please allow microphone permissions '); break; window\ sessionstorage removeitem('activesessiontab'); window\ sessionstorage setitem('activesessiontab', 'parent0'); sendautoregistration(); } break; } }; device and network diagnostics initialize diagnostics diagnostics can be initialized by passing two callbacks, one troubleshooting logs and one to get the responses of diagnostics back api name exotelwebclient initdiagnostics args params type values diagnosticsreportcallback object defined below keyvaluesetcallback object defined below exported to application ui the signature of the callbacks are as below diagnosticsreportcallback is for logs function diagnosticsreportcallback(logstatus, logdata) { // logstatus additional information on the logs, can be ignored as of now // logdata troubleshooting log to save in a file } diagnosticskeyvaluecallback is for test responses, described in the following sections function diagnosticskeyvaluecallback(key, status, description) { // key indicates the type of response // status the value/status specific to key // description description specific to key } immediately after invoking the initdiagnostics, three parameters are returned through the diagnosticskeyvaluecallback callback browserversion browsername/browserversion eg chrome/101 0 0 0 micinfo mic name returned by the browser eg “built in audio analog stereo” speakerinfo speaker name returned by the browser eg “built in audio analog stereo” speaker test speaker test can be started by invoking the api “startspeakerdiagnosticstest” api name exotelwebclient startspeakerdiagnosticstest args none exported to application ui this starts a test by playing a ringtone and as the ring tone gets played, the volume levels are passed through the callback function “diagnosticskeyvaluecallback” which can then be used to render the ui to show volume meter function diagnosticskeyvaluecallback(key, status, description) { //key “speaker” //status a floating point value //description "speaker ok"/”speaker error” } once the user response is captured, it can be passed back to the api, “stopspeakerdiagnosticstest '' as below the responses are passed as arguments the api name exotelwebclient stopspeakerdiagnosticstest args optional, if present, “yes”/”no” exported to application ui the response “yes” indicates that the user has heard the speaker's sound “no” indicates that the user did not hear the speaker's sound this response is further used to update the troubleshooting logs if no arguments are passed, only the test is terminated no updates would be made to troubleshooting logs mic test mic test can be started by invoking the api “startmicdiagnosticstest” api name exotelwebclient startmicdiagnosticstest args none exported to application ui this starts a test by capturing the audio spoken on the mic and as the audio is analyzed, the volume levels are passed through the callback function “diagnosticskeyvaluecallback” with key as “mic” which can then be used to render the ui to show mic volume meter function diagnosticskeyvaluecallback(key, status, description) { //key “mic” //status a floating point value //description "mic ok"/”mic error” } once the user response is captured, it can be passed back to the api, “stopmicdiagnosticstest '' as below the responses are passed as arguments the api name exotelwebclient stopmicdiagnosticstest args optional, if present, “yes”/”no” exported to application ui the response “yes” indicates that the user has been captured by the mic “no” indicates that the user's voice could not be captured this response is further used to update the troubleshooting logs if no arguments are passed, only the test is terminated no updates would be made to troubleshooting logs network diagnostics network diagnosis can be started by invoking the api “startnetworkdiagnostics” api name exotelwebclient startnetworkdiagnostics args none exported to application ui this api starts network operations testing the callback “diagnosticskeyvaluecallback” is called with appropriate keys after each test completion web socket connection callback returns a wss url with status “connected” on successful connectivity function diagnosticskeyvaluecallback(key, status, description) { // key “wss” // status = connected/disconnected // description = wss url } user registration status callback returns a status “connected” on successful registration of the configured “username” this is the callback from the background registration requests no explicit registration requests are sent specifically for diagnostics purposes function diagnosticskeyvaluecallback(key, status, description) { // key “userreg” // status "registered"/"unregistered" // description username } tcp connectivity callback returns a key value “tcp”with ice candidate information as description function diagnosticskeyvaluecallback(key, status, description) { // key “tcp” // status connected/disconnected // description ice candidate line for tcp connectivity/empty string } udp connectivity callback returns a key value “udp” with ice candidate information as description function diagnosticskeyvaluecallback(key, status, description) { // key “udp” // key connected/disconnected // description ice candidate line for udp connectivity/empty string } host connectivity callback returns a key value “host” with ice candidate information as description for internal network function diagnosticskeyvaluecallback(key, status, description) { // key “host” // key connected/disconnected // description ice candidate for the host connectivity (local facing)/empty string } reflexive connectivity callback returns a key value “srflx” with ice candidate information as description for external network function diagnosticskeyvaluecallback(key, status, description) { // key “srflx” // key connected/disconnected // description ice candidate for the reflex connectivity (remote facing)/empty string } auto reconnect sometimes due to network issues, websocket connections get disconnected in that case the application has to retry the connection to implement it we can store the state for shouldautoretry, and during doregistration it could be set as true, and during explicit unregistration it could be set as false, and based on an unregistered event we can invoke doregister api var shouldautoretry = false; function registertoggle() { if (document getelementbyid("registerbutton") innerhtml === "register") { shouldautoretry = true; useragentregistration(); } else { shouldautoretry = false; exwebclient unregister(); } } function registereventcallback(state, sipinfo) { document getelementbyid("status") innerhtml = state; if (state === 'registered') { document getelementbyid("registerbutton") innerhtml = "unregister"; } else { document getelementbyid("registerbutton") innerhtml = "register"; if (shouldautoretry) { exwebclient doregister(); } } } check sdk readiness to check the sdk readiness, whether sdk is ready to receive a call or not we can invoke checkclientstatus api with a callback method first it checks if the microphone is available or not, then it checks whether the websocket is connected or not, then it checks if the user is registered or not args datatype clientstatuscallback callback function with status as string event event decription media permission denied either media device not available, or permission not given not initialized sdk is not initialized websocket connection failed websocket connection is failing, due to network connectivity unregistered,terminated either your credential is invalid or registration keepalive failed initial sdk registration is progress registered ready to receive the calls unknown something went wrong disconnected websocket is not connected connecting trying to connect the websocket exwebclient checkclientstatus(function (status) { console log("sdk status " + status); }); audio device selection to get the device id when the default device got changed, we can register callbacks registeraudiodevicechangecallback function argument argument type audioinputdevicechangecallback function manadatory audiooutputdevicecallback function mandatory ondevicechangecallback function optional in case we dont pass ondevicechangecallback then sdk will internally try to change the default input/output device if ondevicechangecallback is passed as third argument then sdk will not try to change the default audio/input device internally, however, os may have change the default device at os level exwebclient registeraudiodevicechangecallback(function (deviceid) { console log(`demo\ audioinputdevicecallback device changed to ${deviceid}`); }, function (deviceid) { console log(`demo\ audiooutputdevicecallback device changed to ${deviceid}`); }); during the call or before the call, to change the audio output device you can optionally set the `forcedevicechange` parameter to `true` this action will bypass the system's internal auto switching mechanisms exwebclient changeaudiooutputdevice( selecteddeviceid, () => console log(`output device changed successfully`), (error) => console log(`failed to change output device ${error}`), true // optional ); during the call or before the call, to change the audio input device you can optionally set the `forcedevicechange` parameter to `true` this action will bypass the system's internal auto switching mechanisms function changeaudioinputdevice() { const selecteddeviceid = document getelementbyid('inputdevices') value; exwebclient changeaudioinputdevice( selecteddeviceid, () => console log(`input device changed successfully`), (error) => console log(`failed to change input device ${error}`), true // optional ); } if you want the sdk to automatically detect and switch to newly plugged in audio input/output devices, you can enable this option by passing a 4th argument to `initwebrtc` exwebclient initwebrtc( sipaccountinfo, registereventcallback, calllistenercallback, sessioncallback, true // optional enables auto audio device change handling ); noise suppression the sdk provides control over noise suppression for improved call quality by default, noise suppression is disabled call after doregister() api name args exwebclient setnoisesuppression boolean (true / false) // enable noise suppression exwebclient setnoisesuppression(true); // disable noise suppression exwebclient setnoisesuppression(false); logger callback to get the sdk logs item as a callback event we can register own logger registerloggercallback is static methods in exotelwebclient registerloggercallback args args datatype type string message string args array exotelsdk exotelwebclient registerloggercallback(function (type, message, args) { switch (type) { case "log" console log(`demo ${message}`, args); break; case "info" console info(`demo ${message}`, args); break; case "error" console error(`demo ${message}`, args); break; case "warn" console warn(`demo ${message}`, args); break; default console log(`demo ${message}`, args); break; } }); audio volume control the sdk provides granular control over different audio elements including call audio, ringtone, ringback tone, dtmf tone, and beep tone volumes volume values are normalized between 0 0 (silent) and 1 0 (maximum) volume settings persist during the session but reset when the page is reloaded since the notifications are global, these functions are static notification audio volume control methods to control audio output volume for notification sounds api name args returns description exotelwebclient setaudiooutputvolume audioelementname (string) value (number 0 0 1 0) none set notification sound volume exotelwebclient getaudiooutputvolume audioelementname (string) current volume (number 0 0 1 0) get notification sound volume valid audioelementname values "ringtone" incoming call ringtone "ringbacktone" outgoing call ringback tone "dtmftone" dtmf keypad tones "beeptone" system beep sounds // eg set ringtone volume to 50% exotelsdk exotelwebclient setaudiooutputvolume("ringtone", 0 5); // get current ringtone volume const volume = exotelsdk exotelwebclient getaudiooutputvolume ("ringtone"); call audio volume control methods to control audio output volume for call audio since this method is call volume per account, this function is not static api name args returns description exwebclient setcallaudiooutputvolume value (number 0 0 1 0) none set call audio volume exwebclient getcallaudiooutputvolume none current volume (number 0 0 1 0) get call audio volume // eg set call audio volume to 80% exwebclient setcallaudiooutputvolume(0 8); // get current call audio volume const callvolume = exwebclient getcallaudiooutputvolume(); disabling built in logging the sdk provides a way to control all built in logging (console output, sdk logs, and sip js logs) using the setenableconsolelogging method setenableconsolelogging is static methods in exotelwebclient // disable all sdk and sip js logs exotelsdk exotelwebclient setenableconsolelogging(false); default logging is enabled (true) effect when set to false, all sdk logs, sip js logs, and internal logger callbacks are suppressed note this should be called before initializing or registering the client to ensure no logs are printed
🤔
Have a question?
Our knowledgeable support team and an awesome community will get you an answer in a flash.
To ask a question or participate in discussions, you'll need to authenticate first.