webrtc服务器janus echotest学习一
Echo测试演示的是发送给服务器网关的音频和视频,服务器会回传给你,效果如下图所示:
代码分析
创建线程
在janus = new Janus()时,调用Janus(gatewayCallbacks)在其中有函数createSession,并且传入下面的回调函数:
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等传入,如下图。
在函数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):
响应
然后调用success函数
后面通过handleEvent 收到信息,调用Onmessage函数。信息如下:
echotest.createOffer函数,实际调用prepareWebrtc
Trying a createOffer too (audio/video sendrecv
打印上面消息,并且调用httpAPICall来进行通信
function eventHandler()
作用是发出httpAPICall请求,然后请求成功执行handleEvent
handleEvent 收到信息,调用Onmessage函数。
创建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);
echotest.send({“message”: body, “jsep”: jsep});
调用sendMessage用来发送消息,如果发送成功,会收到ack包。
收到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信息。
并且调用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);
并且回调onremotestream用来显示远程流