Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Table of Contents

Example of

...

stream capturing from SIP call,

...

RTMP stream pulling from other server, streams mixing and re-publishing to a third party RTMP server

This example demonstrates how to make a call to SIP, receive audio and video traffic from SIP in response, capture RTMP stream from other server, mix audio streams, inject mixer sound to the SIP call and then redirect the SIP stream to a third-party RTMP server for further broadcasting

Image RemovedImage Added

The code of the example

This example is a simple REST client written on JavaScript, available at:

...

where host is WCS server address.

Analyzing the code

To analyze the code get sipget sip-as-rtmp-4.js file js file version with hash c306c1bbf49bfcbd8e24be927ae95f63b7dbaaba hash ecbadc3 that can be found found hereand  and is availabe to download in build build 2.0.5.28.2747212.

1.

...

code

...

REST / HTTP queries sending.

code

Sending is done using POST method with ContentType application/json by AJAX query using jQuery framework.

Code Block
languagejs
themeRDark
function loadPlayer(sendREST(url, data, successHandler, errorHandler) {
    detectFlash(console.info("url: " + url);
    var attributes = {}console.info("data: " + data);
    attributes.id = "player";
$.ajax({
       attributes.name = "player";url: url,
    attributes.styleclass="center-block";
    beforeSend: function var( flashvarsxhr =) {};
         var pathToSWF = "../../dependencies/rtmp_player/player.swf";
xhr.overrideMimeType( "text/plain;" );
     var elementId = "player"; },
    var   params = {};
type: 'POST',
       params.menu = "true";contentType: 'application/json',
    params.swliveconnect = "true";
    data: data,
     params.allowfullscreen = "true";
    params.allowscriptaccess = "always";   success: (successHandler === undefined) ? handleAjaxSuccess : successHandler,
    params.bgcolor = "#777777";
  error:  swfobject.embedSWF(pathToSWF, elementId, "350", "400", "11.2.202", "expressInstall.swf", flashvars, params, attributes(errorHandler === undefined) ? handleAjaxError : errorHandler
    });
}

2. Making outgoing call with REST / HTTP queries sending.

code

...

-request /call/startup

code

Connection and call data (RESTCall) are collected from the boxes on page

Code Block
languagejs
themeRDark
function sendREST(url, data, successHandler, errorHandler) {
var url =  console.infofield("url: restUrl") + url);"/call/startup";
    console.info("data: " + datacallId = generateCallID();
    $("#sipCallId").ajaxval({callId);
    ...
    var RESTCall url: url,= {};
    RESTCall.toStream = field("rtmpStream");
  beforeSend: function (RESTCall.hasAudio xhr= ) {field("hasAudio");
    RESTCall.hasVideo        xhr.overrideMimeType( "text/plain;" = field("hasVideo");
    RESTCall.callId = callId;
  },
  RESTCall.sipLogin = field("sipLogin");
    type: 'POST',RESTCall.sipAuthenticationName = field("sipAuthenticationName");
    RESTCall.sipPassword = field("sipPassword");
  contentType: 'application/json',
    RESTCall.sipPort = field("sipPort");
    RESTCall.sipDomain data: data,= field("sipDomain");
     RESTCall.sipOutboundProxy = field("sipOutboundProxy");
   success: (successHandler === undefined) ? handleAjaxSuccess : successHandler, RESTCall.appKey = field("appKey");
    RESTCall.sipRegisterRequired = field("sipRegisterRequired");

    for (var key in error: (errorHandler === undefined) ? handleAjaxError : errorHandler
    });
}

3. Making outgoing call with REST-request /call/startup

code

Connection and call data (RESTCall) are collected from the boxes on page

RESTCall) {
        setCookie(key, RESTCall[key]);
    }

    RESTCall.callee = field("callee");

    var data = JSON.stringify(RESTCall);

    sendREST(url, data);
    startCheckCallStatus();

3. Capturing RTMP stream from other server with /pull/rtmp/pull REST query

code

Code Block
languagejs
themeRDark
var pullRtmp = function(uri, fn) {
     var url = console.log("Pull rtmp " + uri);
    send(field("restUrl") + "/pull/callrtmp/startuppull";, {
    callId = generateCallID();    uri: uri
    $("#sipCallId").val(callId);}).then(
    ...
    var RESTCall = {};fn(STREAM_STATUS.PENDING)
    RESTCall.toStream = field("rtmpStream");).catch(function(e){
    RESTCall.hasAudio   = field("hasAudio"console.error(e);
    RESTCall.hasVideo   = field("hasVideo"fn(STREAM_STATUS.FAILED);
    RESTCall.callId = callId;
    RESTCall.sipLogin = field("sipLogin");});
};

4. Stop capturing RTMP stream from other server with /pull/rtmp/terminate REST query

code

Code Block
languagejs
themeRDark
var terminateRtmp = function(uri, fn) {
    RESTCall.sipAuthenticationName = field("sipAuthenticationName"console.log("Terminate rtmp " + uri);
    RESTCall.sipPassword = send(field("sipPasswordrestUrl");
 + "/pull/rtmp/terminate", {
 RESTCall.sipPort = field("sipPort");
    RESTCall.sipDomain = field("sipDomain");uri: uri
    RESTCall.sipOutboundProxy = field("sipOutboundProxy");
}).then(
      RESTCall.appKey = field("appKey");fn(STREAM_STATUS.STOPPED)
    RESTCall.sipRegisterRequired = field("sipRegisterRequired");

    for (var key in RESTCall).catch(function(e) {
        setCookie(key, RESTCall[key]fn(STREAM_STATUS.FAILED);
    }

    RESTCall.callee = field("callee"console.error(e);

    var data = JSON.stringify(RESTCall);

    sendREST(url, data);
    startCheckCallStatus();

...

})
};

5. Mixer starting with /mixer/startup REST query

code

Code Block
languagejs
themeRDark
var pullRtmpstartMixer = function(uri, fnstreamName) {
    console.log("PullStart rtmpmixer " + uristreamName);
    return send(field("restUrl") + "/pullmixer/rtmp/pullstartup", {
        uri: uri
    }).then("mixer://" + streamName,
        fn(STREAM_STATUS.PENDING)
    ).catch(function(e){localStreamName: streamName
        console.error(e);
        fn(STREAM_STATUS.FAILED);
    });
};

...

});
};

6. Mixer stopping with /mixer/terminate REST query

code

Code Block
languagejs
themeRDark
var terminateRtmpstopMixer = function(uristreamName, fn) {
    console.log("TerminateStop rtmpmixer " + uristreamName);
    return send(field("restUrl") + "/pull/rtmpmixer/terminate", {
        uri: uri
    }).then("mixer://" + streamName,
        fn(STREAM_STATUS.STOPPED)
    ).catch(function(e) {localStreamName: streamName
        fn(STREAM_STATUS.FAILED);
        console.error(e);
    })
};

...

});
};

7. Adding/removing streams to mixer with /mixer/add and /mixer/remove REST queries

code

Code Block
languagejs
themeRDark
var startMixer = function(streamNameif ($(ctx).is(':checked')) {
    console.log("Start mixer " + streamName);
    // Add stream to mixer
       return send(field("restUrl") + "/mixer/startupadd", {
            uri: "mixer://" + streamNamemixerStream,
            localStreamName: streamName
 mixerStream,
            remoteStreamName: stream
        });
};

7. Mixer stopping with /mixer/terminate REST query

code

Code Block
languagejs
themeRDark
var stopMixer = function(streamName, fn) {
.then(function(){
            console.log("Stop mixer " + streamNameadded");
        });
    return} else {
        // Remove stream from mixer
        send(field("restUrl") + "/mixer/terminateremove", {
            uri: "mixer://"  + streamNamemixerStream,
            localStreamName: streamName
mixerStream,
         });
};

8. Adding/removing streams to mixer with /mixer/add and /mixer/remove REST queries

code

Code Block
languagejs
themeRDark
if ($(ctx).is(':checked')) {   remoteStreamName: stream
        // Add stream to mixer
        send(field("restUrl") + "/mixer/add", }).then(function(){
            uri: "mixer://" + mixerStream,console.log("removed");
            localStreamName: mixerStream,});
    }

8. Injecting mixer stream to the SIP call with /call/inject REST query

code

Code Block
languagejs
themeRDark
function injectStreamBtn(ctx) {
    var streamName remoteStreamName: stream= $("#injectStream").val();
    if (!streamName) {
  }).then(function(){
            console.log$("added"#injectStream").parent().addClass('has-error');
        return })false;
    } else {
    var $that =  // Remove stream from mixer
        send(field$(ctx);
    send(field("restUrl") + "/mixercall/removeinject_stream", {
            uricallId: "mixer://"  + mixerStream$("#sipCallId").val(),
            localStreamNamestreamName: mixerStream,streamName
    }).then(function(){
        remoteStreamName: stream$that.removeClass('btn-success').addClass('btn-danger');
        }$that.parents().closest('.input-group').then(function(){children('input').attr('disabled', true);
       }).catch(function() {
        console.log("removed"$that.removeClass('btn-danger').addClass('btn-success');
        });
    }

...

$that.parents().closest('.input-group').children('input').attr('disabled', false);
    });
}

9. Re-publishing the SIP call stream to an RTMP server with /push/startup REST query

code

Code Block
languagejs
themeRDark
function injectStreamBtnstartRtmpStream(ctx) {
    if var streamName = $("#injectStream").val();
(!rtmpStreamStarted) {
        if (!streamName) {rtmpStreamStarted = true;
        $var url = field("#injectStream").parent().addClass('has-error')restUrl") + "/push/startup";
        returnvar false;
RESTObj =   {};
    var $that = $(ctx);
 var   send(field("restUrl") + "/call/inject_stream", {options = {};
        callId:if ($("#sipCallId#mute").valis(),':checked')) {
        streamName: streamName
    }).then(function(){options.action = "mute";
        $that.removeClass('btn-success').addClass('btn-danger');
} else if ($("#music").is(':checked')) {
         $that.parents().closest('.input-group').children('input').attr('disabled', true);
   options.action = "sound_on";
            options.soundFile = "sample.wav";
        }).catch(function() {
        $that.removeClass('btn-danger').addClass('btn-success');
RESTObj.streamName = field("rtmpStream");
        RESTObj.rtmpUrl = field("rtmpUrl");
        RESTObj.options  $that.parents().closest('.input-group').children('input').attr('disabled', false= options;
        console.log("Start rtmp");
        sendREST(url, JSON.stringify(RESTObj), startupRtmpSuccessHandler, startupRtmpErrorHandler);
    });
}

10. Re-publishing the SIP call stream to an RTMP server with /push/startup REST query

    sendDataToPlayer();
        startCheckTransponderStatus();
    }
}

10. Mute/unmute RTMP stream re-published sound

Mute sound with /push/mute code

Code Block
languagejsxml
themeRDark
function startRtmpStreammute() {
    if (!rtmpStreamStarted) {
        rtmpStreamStarted = true$("#mute").prop('disabled', true);
        var urlRESTObj = field("restUrl") + "/push/startup"{};
        var RESTObj.mediaSessionId = {}rtmpMediaSessionId;
        var optionsurl = {} field("restUrl") + "/push/mute";
        if ($("#mute").is(':checked')sendREST(url, JSON.stringify(RESTObj), muteSuccessHandler, muteErrorHandler);
    }
}

Unmute sound /push/unmute code

Code Block
languagejs
themeRDark
function unmute() {
    if (rtmpStreamStarted) {
      options.action = $("mute"#mute").prop('disabled', true);
        }var else if ($("#music").is(':checked')) {RESTObj = {};
            options.actionRESTObj.mediaSessionId = "sound_on"rtmpMediaSessionId;
        var    options.soundFile url = field("sample.wav";
        }
        RESTObj.streamName = field("rtmpStream");
restUrl") + "/push/unmute";
        sendREST(url, RESTObj.rtmpUrl = field("rtmpUrl"JSON.stringify(RESTObj), muteSuccessHandler, muteErrorHandler);
    }
}

11. Injecting additional sound to RTMP stream re-published.

Injecting sound from file with /push/sound_on code

Code Block
languagejs
themeRDark
function soundOn() {
   RESTObj.options = options; if (rtmpStreamStarted) {
        console.log("Start rtmp"$("#music").prop('disabled', true);
        sendREST(url, JSON.stringify(RESTObj), startupRtmpSuccessHandler, startupRtmpErrorHandler);
var RESTObj = {};
        RESTObj.mediaSessionId = sendDataToPlayer()rtmpMediaSessionId;
         startCheckTransponderStatus()RESTObj.soundFile = "sample.wav";
     }
}

11. Mute/unmute RTMP stream re-published sound

Mute sound with /push/mute code

Code Block
languagexml
themeRDark
function mute() {   RESTObj.loop = false;
    if (rtmpStreamStarted) {
  var url =    $field("#muterestUrl").prop('disabled', true) + "/push/sound_on";
        var RESTObj = {}sendREST(url, JSON.stringify(RESTObj), injectSoundSuccessHandler, injectSoundErrorHandler);
        RESTObj.mediaSessionId = rtmpMediaSessionId;
        var url = field("restUrl") + "/push/mute";}
}

Stop injecting sound from file with /push/sound_off code

Code Block
languagejs
themeRDark
function soundOff() {
    if (rtmpStreamStarted) {
        sendREST(url, JSON.stringify(RESTObj), muteSuccessHandler, muteErrorHandler);
    }
}

Unmute sound /push/unmute code

Code Block
languagejs
themeRDark
function unmute() {
    if (rtmpStreamStarted) {$("#music").prop('disabled', true);
        var RESTObj = {};
        RESTObj.mediaSessionId = rtmpMediaSessionId;
        $("#mute").prop('disabled', true);
        var RESTObj = {};
        RESTObj.mediaSessionId = rtmpMediaSessionId;
        var url = field("restUrl") + "/push/unmutesound_off";
        sendREST(url, JSON.stringify(RESTObj), muteSuccessHandlerinjectSoundSuccessHandler, muteErrorHandlerinjectSoundErrorHandler);
    }
}

12.  Injecting additional sound to RTMP stream re-published.

...

Hangup the SIP call with /call/terminate REST query.

code

Code Block
languagejs
themeRDark
function soundOnhangup() {
    var url if= field(rtmpStreamStarted"restUrl") { + "/call/terminate";
    var currentCallId =  $("#music").prop('disabled', true);
   { callId: callId };
     var RESTObjdata = {}JSON.stringify(currentCallId);
        RESTObj.mediaSessionId = rtmpMediaSessionId;
        RESTObj.soundFile = "sample.wav";sendREST(url, data);
}

13. RTMP URL displaying on the page to copy to a third party player

code

Code Block
languagejs
themeRDark
function sendDataToPlayer() {
        RESTObj.loopvar host = false;field("rtmpUrl")
        var url = field("restUrl") + "/push/sound_on";.replace("localhost", window.location.hostname)
        sendREST(url, JSON.stringify(RESTObj), injectSoundSuccessHandler, injectSoundErrorHandler);
    }
}

Stop injecting sound from file with /push/sound_off code

Code Block
languagejs
themeRDark
function soundOff() {
    if (rtmpStreamStarted) {
        $("#music").prop('disabled', true);
        var RESTObj = {};
        RESTObj.mediaSessionId = rtmpMediaSessionId;
        var url = field("restUrl") + "/push/sound_off";
        sendREST(url, JSON.stringify(RESTObj), injectSoundSuccessHandler, injectSoundErrorHandler);
    }
}

13. Hangup the SIP call with /call/terminate REST query.

code

Code Block
languagejs
themeRDark
function hangup() {.replace("127.0.0.1", window.location.hostname);

    var urlrtmpStreamPrefix = field("restUrl") + "/call/terminate""rtmp_";
    var currentCallIdurl = {host callId: callId };
    var data = JSON.stringify(currentCallId+ "/" + rtmpStreamPrefix + field("rtmpStream");
    sendREST$("#player").text(url, data);
}