API Version: Development

Video Echo Bot

Downloads

Explained

This is an example of a video echo bot. It removes the audio (to avoid feedback) and echoes only the video stream back to the requester. It demonstrates basic use of the video subsystem including listening for updated and new Av instances.
var TAG = 'IPC-VIDEO-ECHO:';
var host = 'https://pabx.hostname';
IPCortex.PBX.Auth.setHost(host);

/* Start the API's live data feed */{
IPCortex.PBX.startFeed().then(
    function() {
        console.log(TAG, 'Live data feed started');
        /* Enable chat to allow video negotiation messages to be exchanged */
        if ( IPCortex.PBX.enableChat() ) {
            console.log(TAG, 'Chat enable, enabling \'av\' feature');
            /* Enable the 'av' feature, passing a callback for new Av instances */
            IPCortex.PBX.enableFeature(
                'av',
                function(av) {
                    /* Process and listen for update to new Av instances */
                    av.addListener('update', processFeed);
                    processFeed(av);
                },
                ['chat']
            );
        }
    },
    function() {
        console.log(TAG, 'Live data feed failed');
    }
);
IPCortex.PBX.startFeed() will run after authentication to get the API to connect to the system to receive data and be informed of new events. If startFeed() is successful, IPCortex.PBX.enableChat() will be called; chat has to be enabled as all 'av' (video) negotiation messages are exchanged via the chat subsystem. These negotiation messages are transparent to the user. Finally the 'av' feature is enabled with a callback for new Av instances which will have an update listener added to monitor state changes.
The Av instances will be processed in processFeed()
var echoedStream = {};

/* Process the Av instances */
function processFeed(av) {
    /* Nothing to process if remoteMedia isn't an object */
    if ( typeof(av.remoteMedia) != 'object' )
        return;
    for ( var id in av.remoteMedia ) {
        if ( av.remoteMedia[id].status == 'offered' ) {
            console.log(TAG, 'Accepting offer ' + av.remoteMedia[id].cN);
            /* Accept remote parties offer */
            av.accept();
        }
        /* When the remote party has connected check the stream hasn't already been echoed */
        if ( av.remoteMedia[id].status == 'connected' && ! echoedStream[id] ) {
            console.log(TAG, 'Connected client, looping back video stream');
            echoedStream[id] = true;
            /* Clone the mediaStream and strip out the audio tracks to avoid feedback */
            var stream = av.remoteMedia[id].clone();
            stream.getAudioTracks().forEach(
                function(track) {
                    stream.removeTrack(track);
                }
            );
            /* Add the clone stream to the Av instance */
            av.addStream(stream);
        }
    }
}
When processFeed() receives a new or updated Av instance it checks to see if it contains an 'offered' or 'connected' stream. If the request is an offer, processFeed() calls av.accept() and waits for the remote party to become 'connected' (which will then run the function again). If connected, it clones the remote stream, removes the audio tracks (to avoid audio feedback) and calls av.addStream(stream) to loop the media back to the remote party.
To test, load the page over HTTPS and login using incognito mode (Chrome) to avoid clashes. Start keevio, login as a different user, open a chat room with the first user and start video. You should see your own media stream echoed back to you.