本文首发于WebRTC中文网,转载请注明出处javascript
做者: 张鹏,资深音视频工程师html
janus是Meetecho开发的一个WebRTC网关,janus的主要做用就是它能够和你的内网设备和浏览器同时创建链接,并将浏览器发来的音视频数据包如rtp/rtcp包,经过自定义插件转发给你的内网设备,也能够将你发给janus的音视频数据包,加密后转发给浏览器。前端
这样就完成了内网音视频服务器和外网浏览器的互通。java
janus为咱们完成了与浏览器创建会话的复杂逻辑,而且提供给咱们简单的插件机制来处理音视频数据。python
对于PeerConnection链接的创建过程,涉及到复杂的NAT穿透的ICE协议的实现,SDP的交换,DTLS-SRTP的握手和数据包加密发送,数据包接收后解密的复杂逻辑。 janus将咱们从与浏览器交互的PeerConnection创建的过程当中解脱出来,更专一于音视频业务逻辑。git
janus基于插件思想,经过实现基础架构,完成了与浏览器连接的创建过程。github
janus的插件主要完成一些必须的函数实现,如RTP/RTCP数据的接收。web
咱们经过实现本身的插件,来完成在将浏览器RTP数据转发到内网服务器的业务逻辑。json
janus通常用于拓展已有视频会议系统,提供对浏览器客户端的支持。ubuntu
##janus的安装
按照官网的安装步骤能够顺利的完成安装。
本文在ubuntu16.04系统下测试。
首先安装全新虚拟机ubuntu16.04
下载源码,须要先安装git
git clone git@github.com:meetecho/janus-gateway.git
复制代码
而后安装janus依赖库
sudo apt-get install aptitute
sudo aptitude install libmicrohttpd-dev libjansson-dev libnice-dev \
libssl-dev libsrtp-dev libsofia-sip-ua-dev libglib2.0-dev \
libopus-dev libogg-dev libcurl4-openssl-dev liblua5.3-dev \
pkg-config gengetopt libtool automake
复制代码
安装libsrtp 2.0
wget https://github.com/cisco/libsrtp/archive/v2.0.0.tar.gz
tar xfv v2.0.0.tar.gz
cd libsrtp-2.0.0
./configure --prefix=/usr --enable-openssl
make shared_library && sudo make install
复制代码
编译安装janus
git clone https://github.com/meetecho/janus-gateway.git
cd janus-gateway
sh autogen.sh
./configure --prefix=/opt/janus
make
sudo make install
复制代码
到此为止,janus安装到了/opt/janus目录
##janus的配置文件
janus的运行须要进行一些配置
使用命令生成一些默认配置文件
cd janus-gateway
make configs
复制代码
对于最基本的演示用途,配置到此就结束了。
详细的配置能够打开文件/opt/janus/etc/janus/janus.cfg
按照注释进行配置。
直接启动janus的可执行程序便可前台运行janus
cd /opt/janus/bin
./janus
复制代码
咱们须要研究janus提供的demo,好比EchoTest。咱们须要在浏览器中打开测试网页才能够进行测试。因此,咱们须要一个http server
cd /opt/janus/share/janus/demos
python -m SimpleHTTPServer
命令行输出:Serving HTTP on 0.0.0.0 port 8000 ...
复制代码
这样就搭建了简单的http server,监听端口为8000
使用浏览器打开地址,假设ubuntu 16.04的ip为10.1.32.146
http://10.1.32.146:8000/
复制代码
便可看到janus的官网运行起来了。
首先确保你有摄像头和麦克风
选择Demos->Echo Test
点击start就可以正常运行演示程序。
Echo Test完成了将浏览器发来的音视频数据,发回给浏览器。
演示了会话创建,插件编写等基本功能。
Echo Test对应的插件源码为janus-gateway/plugins/janus_echotest.c
经过阅读janus-gateway/plugins/plugin.h
中的注释,能够基本了解插件编写的规则。
在echo test的例子中,前端部分使用了janus.js。janus.js是和janus服务器进行通讯的javascript库,经过使用janus.js简化了webrtc api的使用,以及前端与janus服务器创建链接,交换sdp等功能。若是你不依赖于janus.js你能够自行实现这些逻辑,不过会比较复杂。
整个会话创建的过程符合标准的webrtc peerconnection链接创建的过程。这里的janus服务器就像另外一个浏览器端同样。两端分别经过stun server拿到本身的外网地址,以及内网地址。推荐看一下ICE协议文档,深刻了解下NAT穿透的过程。
而后交换sdp方面。在生成sdp的过程当中,咱们能够经过设置须要使用的音视频编解码参数,来要求浏览器使用咱们但愿使用的音视频编码。
sdp交换后,双方进行连通性测试,即UDP打洞过程。因为echo test中咱们并无配置stun server,因此没法获取到外网IP。因此最终打洞成功的只有本地局域网地址。
janus的关键概念是它的插件机制。janus底层完成了链接创建的通用部分,而把具体业务部分做为插件来提供。对于会话的整个生命周期,都会有对应的插件回调产生。插件在本身的实现中,完成了须要的业务逻辑。如echo test就在它的业务逻辑中给浏览器原样返回了RTP数据。而咱们公司的业务就是将数据转发到媒体服务器的某个会议中。
在plugins.h头文件中,定义了插件结构体struct janus_plugin
。咱们只须要按照struct janus_plugin
中定义的函数,逐个实现,就能够完成插件的编写。
须要实现的接口有:
struct janus_plugin {
int (* const init)(janus_callbacks *callback, const char *config_path);
void (* const destroy)(void);
int (* const get_version)(void);
const char *(* const get_package)(void);
void (* const create_session)(janus_plugin_session *handle, int *error);
struct janus_plugin_result * (* const handle_message)(janus_plugin_session *handle, char *transaction, json_t *message, json_t *jsep);
void (* const setup_media)(janus_plugin_session *handle);
void (* const incoming_rtp)(janus_plugin_session *handle, int video, char *buf, int len);
void (* const incoming_rtcp)(janus_plugin_session *handle, int video, char *buf, int len);
void (* const incoming_data)(janus_plugin_session *handle, char *buf, int len);
void (* const destroy_session)(janus_plugin_session *handle, int *error);
...
};
复制代码
这些接口体现了整个会话的生命周期。对于incoming_rtp,incoming_rtcp,incoming_data来讲,分别表明收到的浏览器发来的rtp,rtcp,自定义数据。这是咱们媒体处理的重点。你能够根据业务需求去实现本身的逻辑。
当咱们但愿janus帮助咱们把数据发给对方时,咱们须要使用janus暴露给咱们的callback:
struct janus_callbacks {
void (* const relay_rtp)(janus_plugin_session *handle, int video, char *buf, int len);
void (* const relay_rtcp)(janus_plugin_session *handle, int video, char *buf, int len);
void (* const relay_data)(janus_plugin_session *handle, char *buf, int len);
void (* const close_pc)(janus_plugin_session *handle);
void (* const end_session)(janus_plugin_session *handle);
...
};
复制代码
其中relay_rtp,relay_rtcp,relay_data分别是用来发送rtp,rtcp,自定义数据的。 janus的插件都有惟一的标识符,如echo test插件的标识符为:
#define JANUS_ECHOTEST_PACKAGE "janus.plugin.echotest"
复制代码
在前端js中须要指定须要与哪一个插件创建会话,在调用janus.js的janus.attach接口时指定:
janus.attach({
plugin: "janus.plugin.echotest",
...
})
复制代码
本文介绍了janus的环境搭建,janus的设计思想,和插件的编写方法。阅读本文后,你可以对janus的使用有基本的认识。具体的细节能够经过阅读源码的方式继续深刻了解。