流媒体协议之WebRTC服务实现20230725
流媒体协议之WebRTC服务实现
1.简介
1.1.WebRTC简介
WebRTC,中文全称网页即时通信(Web Real-Time Communication)的缩写,支持网页浏览器进行实时语音对话或视频对话。它于2011年6月1日开源并在Google、Mozilla、Opera支持下被纳入万维网联盟的W3C推荐标准。
WebRTC实现了基于网页的视频会议,标准是WHATWG 协议,目的是通过浏览器提供简单的javascript就可以达到实时通讯(Real-Time Communications (RTC))能力。
WebRTC(Web Real-Time Communication)项目的最终目的主要是让Web开发者能够基于浏览器(Chrome\FireFox\...)轻易快捷开发出丰富的实时多媒体应用,而无需下载安装任何插件,另外WebRTC还希望能够建立一个多互联网浏览器间健壮的实时通信的平台,形成开发者与浏览器厂商良好的生态环境。同时,Google也希望和致力于让WebRTC的技术成为HTML5标准之一。
WebRTC提供了视频会议的核心技术,包括音视频的采集、编解码、网络传输、显示等功能,并且还支持跨平台:windows,linux,mac,android
WebRTC官网https://webrtc.org/,源码的实现网址https://webrtc.googlesource.com/src。
1.2.WebRTC服务实现简介
由于官网上实现的WebRTC服务比较复杂,不便于移植,特别对于移植到嵌入式平台不太友好,所以本文所述的WebRTC服务是基于libnice以及SRTP库自己实现的,支持跨平台以及交叉编译。
基础功能与官方的WebRTC基本一致,可以实现客户端(可以是嵌入式也可以是linux平台的pc)推流,谷歌浏览器出流并播放。
实现过程简单来说是,通过建立stun服务器(信令服务器)完成了双方(offer端和answer端)SDP交互,从而建立p2p数据传输通道,然后使用srtp进行流数据传输,实现浏览器(answer端即拉流端)上播放webrtc服务(offer端即推流端)上的视频。
2.总体设计说明
2.1.offer端和answer端交互流程
2.2.程序组织结构
2.2.1.UML类图
2.2.2.代码目录
3.模块设计说明
3.1.候选地址收集
候选地址收集,即gathering candidate,流程图如下:
3.2.SDP数据交互
SDP数据产生流程如下:
Offer端SDP实例:
v=0
o=- 1690212703587649 1 IN IP4 0.0.0.0
s=ywf webrtc
t=0 0
a=group:BUNDLE 0
m=video 9 RTP/SAVPF 106
c=IN IP4 0.0.0.0
a=mid:0
a=sendonly
a=rtcp-mux
a=ice-ufrag:Kk6m
a=ice-pwd:IfY2xmVPD18gCPW4eWXBri
a=ice-options:trickle
a=fingerprint:sha-256 75:70:EB:3E:12:70:34:B2:5E:7D:56:7B:F0:6B:8A:09:73:F5:D8:11:3A:8A:96:0E:DA:E6:2C:9F:10:E8:15:0D
a=rtpmap:106 H264/90000
a=fmtp:106 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42C01F;sprop-parameter-sets=Z0LAH9kAUAW7/wEOAQMQAAA+kAALuADxgySA,AWjLjLI=
a=ssrc:573855352 msid:janus janusv0
a=setup:actpass
a=candidate:1 1 udp 2013266431 fe80::20c:29ff:febb:3472 40912 typ host
a=candidate:4 1 udp 2013266430 192.168.110.130 38939 typ host
answer端SDP实例:
v=0
o=- 3641150301993704510 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE 0
a=msid-semantic: WMS
m=video 9 RTP/SAVPF 106
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:le6a
a=ice-pwd:Z4VWItfG0eRzcu0GtQ/X5cn0
a=ice-options:trickle
a=fingerprint:sha-256 D1:A5:CE:E4:1F:EE:22:04:23:76:0D:12:AB:B4:5C:AA:78:EA:6A:77:C0:B6:C7:A6:82:4B:2E:40:08:9D:3F:7D
a=setup:active
a=mid:0
a=recvonly
a=rtcp-mux
a=rtpmap:106 H264/90000
a=fmtp:106 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
3.3.P2P链接建立
音视频数据P2P加密传输通道建立流程如下
4.调试问题汇总
4.1. Xxx.local问题
谷歌浏览器返回的candidate信息是xxx.local格式的,则需要在谷歌浏览器输入如下命令
chrome://flags/#enable-webrtc-hide-local-ips-with-mdns
然后设置为disabled就可以了
4.2.SetSink: ssrc:xxx nullptr
问题如下:
webrtc_video_engine.cc(1593)] SetSink: ssrc:573855352 nullptr
现象:没有画面,不出图
解析:
这个是SDP中的ssrc值和RTP包头中的SSRC值不一致导致的,修改为一致的就可以解决问题。
4.3.No PPS with id << 0 received
问题如下:
WARNING:h264_sps_pps_tracker.cc(86)] No PPS with id << 0 received
WARNING:video_receive_stream2.cc(851)] No decodable frame in 205038 us, requesting keyframe
现象:有画面,但是都是绿屏
解析:
这个是SDP中没有PPS和SPS字段导致的问题,需要加上这两个字段就可以解决问题。
4.4.Received H.264-IDR frame (SPS: 0, PPS: 0)
问题如下:
WARNING:packet_buffer.cc(331)] Received H.264-IDR frame (SPS: 0, PPS: 0). Treating as key frame since WebRTC-SpsPpsIdrIsH264Keyframe is disabled
现象:画面卡顿,并且会花屏
解析:
这个是H264文件不标准导致的,问题在于h264文件中I帧前面没有SPS和PPS包,换一个符合标准的H264文件就可以解决问题了
4.5.Video m= section '0' being rejected in answer
问题如下:
INFO:media_session.cc(2835)] Video m= section '0' being rejected in answer.
现象:有的H264文件完全不出图,有的H264文件播放卡顿
解析:
实际和h264的profile有关,使用Baseline流畅,main profile可以放但是卡顿(应当是代码中的payload和webrtc要求的不一致导致),high profile是完全不出图,webrtc对h264 profile要求列表如下:
[{payload_type: 96, payload_name: VP8, codec_params: {}}, {payload_type: 98, payload_name: VP9, codec_params: {profile-id: 0}},
{payload_type: 100, payload_name: VP9, codec_params: {profile-id: 2}},
{payload_type: 35, payload_name: VP9, codec_params: {profile-id: 1}},
{payload_type: 37, payload_name: VP9, codec_params: {profile-id: 3}},
{payload_type: 102, payload_name: H264, codec_params: {level-asymmetry-allowed: 1, packetization-mode: 1, profile-level-id: 42001f}},
{payload_type: 104, payload_name: H264, codec_params: {level-asymmetry-allowed: 1, packetization-mode: 0, profile-level-id: 42001f}},
{payload_type: 106, payload_name: H264, codec_params: {level-asymmetry-allowed: 1, packetization-mode: 1, profile-level-id: 42e01f}},
{payload_type: 108, payload_name: H264, codec_params: {level-asymmetry-allowed: 1, packetization-mode: 0, profile-level-id: 42e01f}},
{payload_type: 110, payload_name: H264, codec_params: {level-asymmetry-allowed: 1, packetization-mode: 1, profile-level-id: 4d001f}},
{payload_type: 39, payload_name: H264, codec_params: {level-asymmetry-allowed: 1, packetization-mode: 0, profile-level-id: 4d001f}},
{payload_type: 41, payload_name: H264, codec_params: {level-asymmetry-allowed: 1, packetization-mode: 1, profile-level-id: f4001f}},
{payload_type: 43, payload_name: H264, codec_params: {level-asymmetry-allowed: 1, packetization-mode: 0, profile-level-id: f4001f}},
{payload_type: 45, payload_name: AV1, codec_params: {}}, {payload_type: 47, payload_name: AV1, codec_params: {profile: 1}}],
5.程序使用示例
5.1.启动web服务器
一般第一次启动后,后面就不需要再次启动,开机自动运行的(如果提示未安装则安装即可)
源码路径:
https://github.com/fengweiyu/webrtc_server/tree/master/Apache24/bin
https://github.com/fengweiyu/webrtc_server/tree/master/webrtchtml
5.2.启动信令服务器
有32位和64位的,随便选一个能打开的,双击打开就行:
源码路径:
https://github.com/fengweiyu/webrtc_server/tree/master/webrtcgateway
5.3.启动offer端
offer端(StunIP StunPort 就是信令服务器webrtcgateway),即推流端
./webrtc StunIP StunPort SelfName VideoFile offer/answer
eg:
./webrtc 192.168.2.111 9898 ywf test.h264 offer
5.4.启动谷歌浏览器,即拉流端
输入第一步web服务器的ip地址访问网页,然后点击call出图:
5.5.查看WebRTC运行状态
5.5.1.本地日志信息
谷歌浏览器要想其生成日志,则启动时需要带参数:
这时候就会生成日志文件:
5.5.2.页面日志信息
页面上的日志信息有两种:
1.在访问服务器时,按f12会出现console里面的信息:
可以看到浏览器收到的SDP和candidate信息。
2.直接在地址栏输入:chrome://webrtc-internals/
就可以到webrtc运行相关信息:
对比火狐的浏览器则在地址栏输入about:webrtc:
6.源码路径
https://github.com/fengweiyu/webrtc_with_libnice_and_srtp