劳动节之一:SRS中RTC基于流的场景应用,RTC和RTMP流互相转换

2022-03-18 17:12:43 浏览数 (1)

大约在一年前,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的地址。比如:

代码语言:javascript复制
rtmp://192.168.3.6:1935/live/livestream

服务器的IP就是192.168.3.6,服务器的端口是1935。可以认为RTMP没有信令,只有媒体服务。实际上RTMP是能返回一个新地址,也是有RTMP 302的,只是目前用的比较少。而HTTP流的301/302就更常用一些:

代码语言:javascript复制
# 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中指定。也就是可以认为一定会做一次媒体的定向,哪怕是信令和媒体就是一台服务器:

代码语言:javascript复制
webrtc://localhost:1985/live/livestream

实际上这里的localhost:1985,只是RTC的API服务地址,而API服务的响应中会返回媒体服务的地址,可以查看HTTP请求的响应内容(下面是截取的一段包含媒体服务地址的内容):

代码语言:javascript复制
{    "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了。

0 人点赞