大约在一年前,SRS开始支持了WebRTC,这一年一直在持续的更新和收集大家的反馈,终于目前达到了基本可以的里程碑了,是时候总结下使用方法,更新Wiki和DEMO,方便大家用起来了。
SRS的RTC有很多种应用场景,这篇是基于流的场景的应用,后续会推出更多的场景。流是服务器最基本也是最基础的逻辑,是其他场景的基础。基础不牢,地动山摇,大家走过路过不要错过。
RTC的Wiki请点文末阅读原文,我们在这篇文章中,会重点说明一些背景、应用场景和便于理解的设计背景。Wiki侧重的是总结和结果,这个文章侧重的是为什么要这么做。
RTMP转RTC流
直播推流场景一般是RTMP,事实上的标准协议,因为各种系统之间对接都会支持RTMP协议,所以虽然RTMP很老吐槽很多,但是还是比较方便对接的协议,总不能为了技术上看起来不优美,就把所有系统都改造一遍的吧。
直播播放一般不用RTMP,可以选择的协议就很多了,比如HTTP-FLV、HLS、DASH、WS-FLV,这些协议的特点都是TCP协议,也方便CDN系统分发直播流。但是,TCP有网络问题:
- 互动:TCP在网络抖动时,延迟会变大。一般消息(弹幕)的延迟比较小,这时就会出现消息比画面更快的情况。
- 同步:不同客户端的播放进度不同步,有些延迟大,有些延迟小。比如直播答题,或者直播拍卖,需要同步播放器的场景,就会造成问题。
之前一篇文章,没有Flash如何做直播?,我们提到可以用WebRTC播放器做直播,SRS将RTMP流转成WebRTC流,提供给客户端。配置请参考: https://github.com/ossrs/srs/wiki/v4_CN_WebRTC#rtmp-to-rtc
这样可以做到较低延迟,请看视频号的视频:
同时,多个播放器之间的也比较同步:
WebRTC播放直播流,还有哪些应用场景?欢迎评论区留言交流。
RTC推拉流
WebRTC推流,WebRTC播放,这个也是基本的功能,不过一般比较少直接这么用。一般会有多个用户推流和拉彼此的流,比如一对一通话,就是两个用户,各自推自己的WebRTC流,然后播放对方的WebRTC流。
这次五一假期,会开始补齐这些场景的DEMO和Wiki,欢迎关注公众号推送的文章。目前SRS已经有了这些场景的能力,也可以自己多尝试。
WebRTC推流和播放,可以测量下H5的端到端延迟的极限值,本机测试在30ms左右,效果请看下图。配置请参考: https://github.com/ossrs/srs/wiki/v4_CN_WebRTC#rtc-to-rtc
WebRTC推流和播放,还有哪些应用场景?欢迎评论区留言交流。
RTC转RTMP流
WebRTC推流,RTMP播放,是非常重要的功能,每次SRS直播都会有很多朋友问这个功能的进展。目前已经合并到了4.0release分支,SRS 4.0.95支持了这个功能,PR在这里: https://github.com/ossrs/srs/pull/2303
为何这个功能这么重要?因为基于这个功能,可以做RTC录制、直播连麦、直播的RTC推流(这些场景后续会给出Demo和Wiki文档)。如下图所示:
WebRTC推流,RTMP播放的功能,打通了RTC到直播这条链路,效果请看下图,配置请参考: https://github.com/ossrs/srs/wiki/v4_CN_WebRTC#rtc-to-rtmp
WebRTC推流,转RTMP播放,还有哪些应用场景?欢迎评论区留言交流。
为什么是流
SRS的基本概念是流,而不是房间。有一个常见的问题就是:SRS是不是支持SFU?有很多SFU有房间概念,比如Janus的videoroom。房间是业务概念,并不是SFU必须有的概念,会造成SFU的信令比较复杂。
尽管没有房间概念,SRS是可以做SFU的,因为SFU是做流转发用的,而房间主要是做消息通知用,比如谁开始推流了,谁停止推流了,这些完全可以用HTTP Callback实现。这样可以非常方便的将SFU集成到现有系统。
当用户之间需要互动时,比如连麦,比如一对一通话,比如多人通话,就肯定需要一个信令服务,SRS不会实现业务信令,因为这块的实现方式有很多,比如通过WebScoket,或者QUIC,或者消息队列,但关键点还是不同的业务有完全不同的信令,所以这个一定是业务问题。SRS会提供一些不同场景的信令的DEMO,配合SRS使用。
SRS如何做SFU,如何支持房间和多人通话,后续会给出DEMO,请关注公众号的消息推送。
为什么叫Candidate
RTMP或HTTP-FLV流,都是客户端直接指定服务器的IP,访问流信息。服务器提供服务的IP,就是RTMP或HTTP-FLV的地址。比如:
rtmp://192.168.3.6:1935/live/livestream
服务器的IP就是192.168.3.6,服务器的端口是1935。可以认为RTMP没有信令,只有媒体服务。实际上RTMP是能返回一个新地址,也是有RTMP 302的,只是目前用的比较少。而HTTP流的301/302就更常用一些:
# curl -v http://localhost:1985/api/v1/tests/redirects< HTTP/1.1 301 Moved Permanently< Connection: Keep-Alive< Content-Length: 32< Content-Type: text/plain; charset=utf-8< Location: /api/v1/tests/errors< Server: SRS/4.0.91(Leo)
如果我们需要支持HTTP流的重定向,特别是Location中是完整的http地址,指向的是另外一个服务器,那对于直播流也需要配置一个可访问的IP地址。这种情况在开源不常用,在CDN服务中还挺常用的。
而RTC则不同,一般我们访问的是API的地址,或者说是信令交换SDP,而媒体的地址是在SDP中指定。也就是可以认为一定会做一次媒体的定向,哪怕是信令和媒体就是一台服务器:
webrtc://localhost:1985/live/livestream
实际上这里的localhost:1985,只是RTC的API服务地址,而API服务的响应中会返回媒体服务的地址,可以查看HTTP请求的响应内容(下面是截取的一段包含媒体服务地址的内容):
{ "code": 0, "server": "vid-10864-599", "sdp": "v=0rna=candidate:0 1 udp 2130706431 192.168.3.6 8000 typ host generation 0rn", "sessionid": "74305gk7:42aP"}
当API和媒体是一台服务器时,candidate是否可以用客户端请求的地址,比如上面是localhost呢?不行,可以把candidate配置成localhost或127.0.0.1试试,会发现ICE不通。
而除了本机部署,一般部署的方式是在云虚拟机,或者是Docker中部署,那么SRS完全不能知道客户端能访问到的地址是什么,必须配置正确的Candidate指定。
如果是在K8S中部署SRS,对外提供服务的IP是Service的地址,或者是SLB所绑定的IP,这个Candidate就只能通过业务系统才能获取到,当然如果流量不大则可以用一个IP或SLB。
如果是SLB后面挂多个SRS,还需要有一次客户端定位的过程,未来若API和媒体都是用QUIC协议,那么就可以准确定位到一个SRS了。