By using the Aculab site, you agree with our use of cookies.

WebRTC Interface Version 2 Application Developer Guide

How to Write WebRTC Apps

This guide shows the basic steps how to write WebRTC applications for Aculab Cloud. Refer to the API guide for detailed documentation on the APIs used.

WebRTC Client instances can call, and be called from, Aculab Cloud services only. They cannot call PSTN or SIP phones directly, although of course Aculab Cloud services can call those devices.

A web page can handle a number of concurrent WebRTC Client instances. The maximum number of concurrent instances is browser dependent. The code shown in the Integrating WebRTC section handles only one concurrent WebRTC Client instance.

Integrating WebRTC

The WebRTC specification is currently a moving target and, along with the rest of the industry, we do our best to keep in step with it. Before deployment, please be sure to try out our WebRTC interface in the environment where you expect to use it.

  • Include the JavaScript library by adding the following line to your HTML header:
    <script src="https://webrtc.aculabcloud.net/js/2/AculabCloudCaller.js" type="text/javascript"></script>
  • In your HTML page, create a WebRTC element by adding the following:
    <audio id="player"></audio>

Registering a WebRTC Client Instance with Aculab Cloud

To register a WebRTC Client instance for use with Aculab Cloud, you will need the following information:

InformationDescription
Cloud ID The Cloud ID for your Aculab Cloud account, for example 1-2-0.
WebRTC Access Key Your WebRTC Access Key which can be found in the Aculab Cloud portal.
Client Id A text identifier which Aculab Cloud uses to identify a specific WebRTC Client instance.
WebRTC Token For incoming WebRTC calls only, a WebRTC token is needed to enable incoming calls. Instructions for generating a token are shown in Enabling Incoming Calls on a WebRTC Instance.

Basics of Registering an Instance

All WebRTC calls are controlled through the AculabCloudClient class. Create a new instance of the class with:

    acc = new AculabCloudClient(cloudId, webRtcAccessKey, clientId, logLevel);

where logLevel is between 0 and 6 inclusive. 0 disables logging.

If you will be accepting incoming WebRTC calls, then set up maxConcurrent, onIncoming and onIncomingState properties. The example code in this guide assumes only 1 call at a time.

    acc.maxConcurrent = <number of concurrent WebRTC calls to handle>;
    acc.onIncoming = newCall;
    acc.onIncomingState = incomingState;

See Accepting an Incoming WebRTC Call for information on the newCall and incomingState functions.

Enabling Incoming Calls on a WebRTC Client Instance

A WebRTC Client instance needs a token to be able to receive incoming WebRTC calls. This token is retrieved from the webrtc_generate_token Web Services API, it should be generated by server side code. An example as follows:

    // Use the token to enable incoming WebRTC calls
    acc.enableIncoming(<webrtc_token>);

The onIncomingState callback is used to notify you if incoming WebRTC calls are enabled or disabled.

Calling an Aculab Cloud Service from WebRTC

WebRTC Client instances can only call Aculab Cloud inbound services. This is achieved by calling AculabCloudClient.makeOutgoing() then setting up the AculabCloudOutgoingCall callbacks to handle the call control events.

    call = acc.makeOutgoing(encodeURIComponent("incoming_service_name"));
    call.onDisconnect = callDisconnected;
    call.onRinging = ringing;
    call.onMedia = gotMedia;
    call.onConnecting = connecting;
    call.onConnected = connected;
    call.onError = handleError;

See Call Control Callbacks for information on these callbacks.

Calling a WebRTC Client Instance from Aculab Cloud

UAS and REST applications can call a WebRTC Client instance by setting the call destination to webrtc:<username>.

Calling a WebRTC Client Instance from the REST API

An example of using the Connect action to call a WebRTC Client instance, written in Python.

    my_connect = Connect()
    my_connect.set_next_page("/call_finished")
    my_connect.append_destination("webrtc:{0}".format(username))
    my_connect.set_call_origin('441234567890')
    my_connect.set_hold_media(Play(file_to_play='holdmusic.wav'))
    my_connect.set_secondary_call(SecondaryCall(first_page=WebPage(url='secondary_first'),
                                                final_page=WebPage(url='secondary_final'),
                                                error_page=WebPage(url='error_page')))

Calling a WebRTC Client Instance from the UAS API

A Python example of using the UASCallChannel object to call a WebRTC Client instance.

    if channel.start_call('webrtc:{0}'.format(username), call_from='441234567890') is True:
        # we have started an outbound call
        pass

Accepting an Incoming WebRTC Call

onIncomingState

onIncomingState is used to inform you whether incoming WebRTC calls are enabled or disabled.

    function incomingState(state) {
        if (state.ready) {
            // We can receive incoming calls
        } else {
            // We cannot receive incoming calls
            // Report state.cause to the user
        }
    }

onIncoming

If WebRTC Client has been configured to accept incoming calls, then the onIncoming callback is used to accept any incoming call.

The onIncoming callback should set up the AculabCloudIncomingCall callbacks, connect audio to the player, and send the ringing notification to the remote end.

    // newCall has been assigned to the onIncoming callback above
    function newCall(obj) {
        call = obj.call;
        inbound = true;

        // Set up callbacks
        call.onDisconnect = callDisconnected;
        call.onRinging = ringing;
        call.onMedia = gotMedia;
        call.onConnecting = connecting;
        call.onConnected = connected;
        call.onError = handleError;

        // Send ringing notification
        call.ringing();
    }

See Call Control Callbacks for information on these callbacks.

Call Control Callbacks

The various call control callbacks have been set up in the code snippets above. Example code showing how these callbacks are implemented is shown in this section.

onDisconnect

This callback is called when the call has been disconnected. The player element should be reset, and any resources cleaned up.

    function callDisconnected(obj) {
        if (obj.call != null) {
            obj.call.disconnect();
        }
        
        // Call the gotMedia callback to disable the player element
        gotMedia(obj.call, null);
    }

onRinging

If you have not got an audio stream from the remote end, then you can generate a ringtone locally.

    function onRinging(obj) {
        // get the <audio> element
        var player = document.getElementById('player');
        if (!playing_ringing) {
            if (player.canPlayType('audio/wav')) {
                // Play a ring tone if we have not got an audio stream
                // from the remote end
                // gotremotestream is initialised in gotMedia()
                if (!gotremotestream) {
                    player.loop = 'loop';
                    player.src = 'audio/ringback.wav';
                    player.type = 'audio/wav';
                    player.load();
                    var p = player.play();
                    if (p !== undefined) {
                        // handle error
                    }
                }
            } else {
                // Browser can't play audio/wav
            }
            playing_ringing = true;
        }
    }

onMedia

The onMedia callback is used to give you the remote audio stream which you can connect to your <audio> element.

    function gotMedia(call, stream) {
        // Get the <audio> element
        var player = document.getElementById('player');
 
        // Reset the player state
        player.pause();
        player.loop = '';
        player.src = '';
        player.srcObject = '';
        player.type = '';
        player.load();
        playing_ringing = false;
        gotremotestream = false;

        // If there is a stream then connect it to the <audio> element
        if (stream !== null) {
            gotremotestream = true;
            player.srcObject = stream;
            player.load();
            var p = player.play();
            if (p !== undefined) {
                // Handle error
            }
        }
    }

onConnecting

onConnecting is called when the browser is preparing the sockets needed to transport the call media. There is nothing that specifically needs doing in this callback, but it can be used to notify the user about call progress.

    function connecting(obj) {
        // Update a web page element to notify the user that the
        // call is connecting
    }

onConnected

When the call has been answered the onConnected callback will be called. You can use this callback to notify the user about call progress.

    function connected(obj) {
        // Update a web page element to notify the user that the
        // call is connected
        connected = true;
    }

onError

The onError callback can be used to clean up connected calls, and report issues to the user.

    function handleError(obj) {
        // Report the error to the user

        // Call the callDisconnected callback to clean up the call
        // and reset the audio player
        callDisconnected(obj.call)
    }

Disconnecting a Call

Disconnecting a connected call is as simple as calling disconnect() on the call object. Inbound calls that have not connected should be rejected with a valid SIP cause, for example 486 busy here, instead.

    function stopCall() {
        if (call) {
            // If inbound call has not been accepted, then reject the call
            if (inbound && !connected) {
                call.reject(486);
            } else {
                call.disconnect();
            }
        }
    }

Troubleshooting

A number of common issues can cause problems with audio in a WebRTC call.

HTML5 autoplay blockers will prevent the <audio> element from automatically playing the audio from the remote end. Ensure that any blockers are disabled for your WebRTC page.

If the same username is registered from more than one browser instance then the most recently registered instance will receive incoming WebRTC calls. As WebRTC Client instances are automatically re-registered at various intervals, the most recently registered instance may change without warning. Therefore, in general it's best to register a given username with only one browser instance at a time.