文章前放个广告,我个人采用Go语言编写的一个开源流媒体服务器,欢迎关注: lal (https://github.com/q191201771/lal)
chunk stream id
设计思想
按rtmp的设计思想,是可以在一条链路上传输多路流,比如最常见的一路音频流和一路视频流,音频流和视频流可独立打开关闭。
那么当某一路流中的message特别大时(比如视频的关键帧),可能会导致音频流的message需要等待这个特别大的message传输完毕后才能传输。
rtmp为了解决这个问题,选择将对应用层有意义的message切割成chunk,那么传输时就不需要一个message接一个message传输了,而可以一个chunk接一个chunk传输。
(注意,chunk必须是完整的,不能发送chunk1的前半部分再发chunk2然后再发送chunk1的后半部分)
接收端将chunk stream id
相同的chunk组合成完成的message再返回给应用层。
下面是一个简单的例子
1 | # 假设Video message 1很大 |
思考
那我们来思考一下,按现在常见的rtmp over tcp的方案,当应用层有一个message需要传输时,我们会将它切割成chunk,然后发送切割出的所有chunk,然后再循环处理下一个message。
(具体实现会跟网络io部分相关,但也是按message进入发送队列的)
事实上,一个message的chunk是连续的,并不会插入其他chunk。所以,并没有达到上面大message不阻塞其他stream的message的设计。
那么理论上rtmp的这个设计思路可不可行呢?是可行的,比如发送队列不使用FIFO的大buffer,而是以chunk组成的更细粒度的管理。或者使用UDP传输,一般都会按MTU切割应用层的message,基本和chunk的概念类似。
实践
下面是一些常见的rtmp项目使用chunk stream id的情况
obs推流
1 | csid 2 用于传输 SetChunkSize。 |
ffmpeg推流
1 | csid 2 SetChunkSize |
注意,ffmpeg推流时,是先发的connect,再发SetChunkSize,接收端在没有收到SetChunkSize时,应该假定对端的chunk size为128。
从nginx rtmp module拉流
1 | csid 2 Window ACk Size | SetPeerBandwidth | SetChunkSize |
可以看到,obs推流的音频和视频数据共用一个csid,ffmpeg则是两个csid,nginx rtmp module则是metaData也单独使用一个csid。
chunk stream id如何获取,message如何切割成chunk,chunk如何重组成message可以参见lal(https://github.com/q191201771/lal)的实现。
message stream id
obs推流
1 | msid 0 信令 |
ffmpeg推流
和obs一样
从nginx rtmp module拉流
1 | msid 0 信令 |
可以看到,三个项目都是使用msid 1传输音视频数据。
lal中,_result for createStream
的msid使用1,publish 和 play 使用_result
中返回msid
transaction id
command类型message中的一个字段。
尽管文档中将大部分message都定义为0了,比如:
1 | connect tid: 1 |
但是各rtmp软件的具体实现却不是这样,比如:
obs推流
1 | connect tid: 1 |
可以看到是自增的过程。
测试时服务端使用lal,lal是按照接收到的tid原样回复message。
ffmpeg推流
结果和obs推流一样
从nginx rtmp module拉流
1 | onBWDone tid: 0 |
测试时客户端使用lal,lal按递增的方式处理tid:
1 | connect tid: 1 |
message type id
这个是最简单的,标明应用层的message是什么类型,比如音频(8)、视频(9)、metadata(18)、特定信令(比如1是SetChunkSize)、Command类型的信令(20)等。
TODO
现在rtmp的使用场景基本上都是一个Connection对应一次推流或者拉流。
其实rtmp在flash中使用时,一个Connection对象上是可以打开、关闭多个Stream,这才是最贴合rtmp语义的用法。由于我手上没有合适的环境,暂时没有测试。
本文完,作者yoko,尊重劳动人民成果,转载请注明原文出处: https://pengrl.com/p/25610/