通过前面的章节,完成kurento-media-server服务端的搭建。同时通过js_client 完成对服务端的调用。之前忙着搭建环境,对整个调用过程不清楚,今天从表面调用顺序梳理过程中的交互逻辑。
先看一下kurento-media-server以及其客户端的组成。非常直观,通过PlayEndpoint 和 WebRtcEndpoint的连接,使得RTSP视频流最终在客户端展现。
把这个结构稍微再细化一下,把应用程序端再细化拆分,变成客户端和应用程序服务,也就是kurento server, application server, applications。客户端就是各种各样的浏览器,app,智能手机等。应用程序服务,类似http-server等。下面形象化的展示一下这种结构
然后通过一个前端js客户端调用RTSP视频流的过程,按照调用顺序梳理一下整个过程
以本地js 服务为例,详细梳理整个调用过程,首先启动 js服务,包括调用本地摄像头和用户自己输入rtsp地址的服务
- 服务启动通过kurento API 通过kurento-client 模块中的kurento-client.js 创建js 客户端。kurento-client-js,JavaScript客户端。
- start, 开始构建本地的SDP信息。SDP就是需要构建的多媒体会话描述信息。kurento-utils-js,用于简化WebRTC应用开发的JavaScript工具。同时开启websocket 与server.js 进行数据交互。
sendrecv 浏览器愿意在这个会话中发送和接收音频。 其他值可以是sendonly,recvonly和inactive,用于实现不同的场景,如将呼叫保持。直接影响传入的参数,需要传入对应输入或者输出的video element 元素中的内容。
- 简单理解,这一步操作如果成功,证明localVideo 和 remoteVideo 已经成功获取了视频流信息,开始生成会话信息。
onOffer, 通过websocket 向server.js 发送'start' 请求。
onIceCandidate
通过websocket 与 server.js 完成数据交互。
------------------------------ server.js --------------------------------------
接受到 js 客户端的 start 请求,然后开始调用start 函数,开始于kurento-media-server 进行一系列连接。可以认为是PlayEndPoint 于 WebrtcEndPoint的一些列交互。
function start(sessionId, ws, sdpOffer, callback) { if (!sessionId) { return callback('Cannot use undefined sessionId'); } getKurentoClient(function(error, kurentoClient) { if (error) { return callback(error); } kurentoClient.create('MediaPipeline', function(error, pipeline) { if (error) { return callback(error); } createMediaElements(pipeline, ws, function(error, webRtcEndpoint, filter) { if (error) { pipeline.release(); return callback(error); } if (candidatesQueue[sessionId]) { while(candidatesQueue[sessionId].length) { var candidate = candidatesQueue[sessionId].shift(); webRtcEndpoint.addIceCandidate(candidate); } } connectMediaElements(webRtcEndpoint, filter, function(error) { if (error) { pipeline.release(); return callback(error); } webRtcEndpoint.on('OnIceCandidate', function(event) { var candidate = kurento.getComplexType('IceCandidate')(event.candidate); ws.send(JSON.stringify({ id : 'iceCandidate', candidate : candidate })); }); webRtcEndpoint.processOffer(sdpOffer, function(error, sdpAnswer) { if (error) { pipeline.release(); return callback(error); } sessions[sessionId] = { 'pipeline' : pipeline, 'webRtcEndpoint' : webRtcEndpoint } return callback(null, sdpAnswer); }); webRtcEndpoint.gatherCandidates(function(error) { if (error) { return callback(error); } }); }); }); }); }); }
kurentoClient 创建管道media pipline, 返回pipline;
pipline 创建 PlayerEndpoint, 返回player;
pipline 创建WebRtcEndpoint, 返回webrtcendpoint, 并开始处理SDP请求,处理完向js Client 做应答;
player 连接 webrtcendpoint
会话建立完成后,可以进行视频流的交换
参考信息:
https://blog.gmem.cc/webrtc-server-basedon-kurento