天天看點

webrtc伺服器janus echotest學習一

Echo測試示範的是發送給伺服器網關的音頻和視訊,伺服器會回傳給你,效果如下圖所示:

webrtc伺服器janus echotest學習一

代碼分析

webrtc伺服器janus echotest學習一

建立線程

在janus = new Janus()時,調用Janus(gatewayCallbacks)在其中有函數createSession,并且傳入下面的回調函數:

webrtc伺服器janus echotest學習一

createSession建立請求,成功建立一次httpAPICall,輸出Created handle: 1747107217737787

Janus.httpAPICall(server, {
    verb: 'POST',
    withCredentials: withCredentials,
    body: request,
    success: function(json) {
    Janus.debug(json);
    if(json["janus"] !== "success") {
        Janus.error("Ooops: " + json["error"].code + " " + json["error"].reason);   // FIXME
        callbacks.error(json["error"].reason);
        return;
    }
    Janus.sessions[sessionId] = that;
    eventHandler();
    callbacks.success();
},
           

成功回調eventHandler以及echoest的sucesss

建立插件

echoest的sucesss函數如下:

定義了插值對象及對應的回調函數。

janus.attach(

{

}

this.attach = function(callbacks) { createHandle(callbacks)} 實際調用createHandle,

并把對應的回調plugin,succecss等傳入,如下圖。

webrtc伺服器janus echotest學習一

在函數function createHandle(callbacks) 中,定義了插件的各個函數,并且回調echotest.js中的janus.attach中的success函數,并且輸出Plugin attached! (janus.plugin.echotest, id=1747107217737787),其函數的主要作用是傳入對應的回調函數,并且定義一個插件及其許多許應的函數,并且與伺服器進行通信:

pluginHandles[handleId] = pluginHandle;
callbacks.success(pluginHandle);
           

echotest = pluginHandle;定義為插件,其中定義許多函數。包括:

var pluginHandle =
{
        session : that,
        plugin : plugin,
        id : handleId,
        token : handleToken,
        detached : false,
        webrtcStuff : {}
        getId : function() { return handleId; },
        getPlugin : function() { return plugin; },
        getVolume : function() { return getVolume(handleId); },
        isAudioMuted : function() { return isMuted(handleId, false); },
        muteAudio : function() { return mute(handleId, false, true); },
        unmuteAudio : function() { return mute(handleId, false, false); },
        isVideoMuted : function() { return isMuted(handleId, true); },
        muteVideo : function() { return mute(handleId, true, true); },
        unmuteVideo : function() { return mute(handleId, true, false); },
        getBitrate : function() { return getBitrate(handleId); },
        send : function(callbacks) { sendMessage(handleId, callbacks); },
        data : function(callbacks) { sendData(handleId, callbacks); },
        dtmf : function(callbacks) { sendDtmf(handleId, callbacks); },
        consentDialog : callbacks.consentDialog,
        iceState : callbacks.iceState,
        mediaState : callbacks.mediaState,
        webrtcState : callbacks.webrtcState,
        slowLink : callbacks.slowLink,
        onmessage : callbacks.onmessage,
        createOffer : function(callbacks) { prepareWebrtc(handleId, callbacks); },
        createAnswer : function(callbacks) { prepareWebrtc(handleId, callbacks); },
        handleRemoteJsep : function(callbacks) { prepareWebrtcPeer(handleId, callbacks); },
        onlocalstream : callbacks.onlocalstream,
        onremotestream : callbacks.onremotestream,
        ondata : callbacks.ondata,
        ondataopen : callbacks.ondataopen,
        oncleanup : callbacks.oncleanup,
        ondetached : callbacks.ondetached,
        hangup : function(sendRequest) { cleanupWebrtc(handleId, sendRequest === true); },
        detach : function(callbacks) { destroyHandle(handleId, callbacks); }
}
           

并且向伺服器發起一次請求,通信伺服器,如果成功時,才回調echotest.js中的janus.attach中的success函數,即

success: function(pluginHandle) {
            $('#details').remove();
            echotest = pluginHandle;
            Janus.log("Plugin attached! (" + echotest.getPlugin() + ", id=" + echotest.getId() + ")");
            // Negotiate WebRTC
            var body = { "audio": true, "video": true };
            Janus.debug("Sending message (" + JSON.stringify(body) + ")");
            echotest.send({"message": body});
            Janus.debug("Trying a createOffer too (audio/video sendrecv)");
            echotest.createOffer(
                {
                    // No media provided: by default, it's sendrecv for audio and video
                    media: { data: true },  // Let's negotiate data channels as well
                    // If you want to test simulcasting (Chrome and Firefox only), then
                    // pass a ?simulcast=true when opening this demo page: it will turn
                    // the following 'simulcast' property to pass to janus.js to true
                    simulcast: doSimulcast,
                    success: function(jsep) {
                        Janus.debug("Got SDP!");
                        Janus.debug(jsep);
                        echotest.send({"message": body, "jsep": jsep});
                    },
                    error: function(error) {
                        Janus.error("WebRTC error:", error);
                        bootbox.alert("WebRTC error... " + JSON.stringify(error));
                    }
                });
            $('#start').removeAttr('disabled').html("Stop")
                .click(function() {
                    $(this).attr('disabled', true);
                    clearInterval(bitrateTimer);
                    janus.destroy();
                });
        },
           

在這個函數準備向伺服器發送相應的資訊連接配接請求。

發送音視訊資訊

var body = { “audio”: true, “video”: true };

echotest.send({“message”: body});

echotest.send 實際調用sendMessage

發送的請求為:

var request = { “janus”: “message”, “body”: message, “transaction”: transaction };

Sending message to plugin (handle=3650608414117457):

響應

webrtc伺服器janus echotest學習一

然後調用success函數

後面通過handleEvent 收到資訊,調用Onmessage函數。資訊如下:

webrtc伺服器janus echotest學習一

echotest.createOffer函數,實際調用prepareWebrtc

Trying a createOffer too (audio/video sendrecv

列印上面消息,并且調用httpAPICall來進行通信

function eventHandler()

作用是發出httpAPICall請求,然後請求成功執行handleEvent

handleEvent 收到資訊,調用Onmessage函數。

webrtc伺服器janus echotest學習一

建立offer資訊

調用echotest.createOffer,實際調用prepareWebrtc函數,其中getUserMedia

獲得本地流,并且調用streamsDone。代碼:

navigator.mediaDevices.getUserMedia(gumConstraints)
.then(function(stream) { 
pluginHandle.consentDialog(false); 
streamsDone(handleId, jsep, media, callbacks, stream); })
           

其中streamsDone 函數建立RTCPeerConnection連接配接,并且準備本地的sdp,并且調用onlocalstream把本地流顯示出來。代碼如下:

根據目前條件,選擇執行下面功能
config.pc = new RTCPeerConnection(pc_config, pc_constraints);
pluginHandle.onlocalstream(config.myStream);//顯示本地流
createOffer(handleId, media, callbacks);//調用函數 createOffe
config.pc.setRemoteDescription//如果已經有sdp資訊,遠端sdp,調用此處
           

在函數function createOffer(handleId, media, callbacks)中:

config.pc.createOffer 調用系統的函數,并且成功的話回調。
           

如果成功回調callbacks.success(jsep);即調用echotest.createOffer裡的時,成功回調,準備向伺服器發送sdp資訊:

success當,當收到本地sdp資訊時,成功回調,準備向伺服器發送sdp資訊:

success: function(jsep) {

Janus.debug(“Got SDP!”);

Janus.debug(jsep);

webrtc伺服器janus echotest學習一

echotest.send({“message”: body, “jsep”: jsep});

調用sendMessage用來發送消息,如果發送成功,會收到ack包。

webrtc伺服器janus echotest學習一

收到SDP資訊

當伺服器處理完成,主動向用戶端發這送sdp資訊,用戶端是通過handleEvent來處理。

else if(json["janus"] === "event") {
    Janus.debug("Got a plugin event on session " + sessionId);
    var callback = pluginHandle.onmessage;
    if(callback !== null && callback !== undefined) {
        Janus.debug("Notifying application...");            
        callback(data, jsep);//實際調用echotest.js中函數onmessage
    } 
           

收到消息,成功回調函數onmessage。收到遠端的SDP資訊。

webrtc伺服器janus echotest學習一

并且調用echotest.handleRemoteJsep({jsep: jsep});即執行prepareWebrtcPeer

prepareWebrtcPeer的作用是設定遠端的sdp資訊,用來建立p2p連接配接config.pc.setRemoteDescription。

回調streamsDone裡面的以下函數來獲得遠端流config.pc.ontrack,這個是webrtc自已的函數,可能是回調函數,這樣拿來顯示遠端流。

config.pc.ontrack = function(event) {

pluginHandle.onremotestream(config.remoteStream);

webrtc伺服器janus echotest學習一

并且回調onremotestream用來顯示遠端流。

繼續閱讀