1.RTMP推流方案总结
2.rtmp协议详解中文版
RTMP推流方案总结
RTMP协议简介,源码其全称为Real Time Messaging Protocol,源码是源码由Adobe Systems公司为Flash播放器与服务器之间音频、视频和数据传输开发的源码私有协议。RTMP协议像一个容器,源码用于装载AMF格式的源码firefoxos源码数据或FLV中的视/音频数据,一个连接可通过不同的源码通道传输多路网络流,通道中的源码包遵循固定大小的传输规则。更多协议细节请参考《rtmp specification 1.0》。源码
RTMP服务器的源码选择有多种开源方案,如Nginx的源码rtmp插件,用于实时流推送,源码具体实现可参考另一篇博客。源码SRS(Simple RTMP Server)是源码一款国人开发的优秀开源流媒体服务器软件,使用C++开发,源码适用于直播、录播、视频客服等场景,提供丰富的接入方案和流变换功能,GitHub源码链接为:github.com/ossrs/srs。牛茅溯源码
crtmpserver是一款由C++语言编写的开源RTMP流媒体服务器,功能相对简单,与Flash Player的兼容性较差,但代码结构良好,适用于学习RTMP协议和服务器端编程。GitHub源码链接为:github.com/shiretu/crtm...。
livego是基于Go语言的RTMP直播服务器,Go语言为服务器性能而生,开发效率高于C/C++。GitHub源码链接为:github.com/gwuhaolin/liv...
基于Go的livego服务器解决了语言级别上的并发问题。node-rtsp-rtmp-server是使用Node.js实现的RTMP服务器,GitHub源码链接为:github.com/iizukanao/nod...
测试时,推荐使用大牛直播提供的推流工具,也可以使用FFmpeg进行推流。
RTMP推流器的选择同样多样,librtmp软件包含一个基本的客户端:rtmpdump,以及提供RTMP协议支持的库。FFmpeg也能实现RTMP推流,内部集成了librtmp,流光闪字源码官方给出了muxing.c源代码示例。srs-librtmp是srs提供的一个RTMP库,可以推送H数据,但在Windows环境下存在兼容性问题。
音视频开发相关教程与资料可免费订阅QQ群:,领取学习资源。
rtmp协议详解中文版
目前国内比较常见的三种直播协议 RTMP、HLS、HTTP-FLV,其中rtmp是Adobe公司为Flash播放器和服务器之间提供音视频数据传输服务而设计的应用层私有协议,也是目前各大云厂商直线直播业务所公用的基本直播推拉流协议。本文主要是学习rtmp(实时消息传输协议,Real-Time Messaging Protocol )的学习笔记,并结合livego的源码分析,和大家一起深入学习RTMP协议最核心的知识点。
RTMP关键概念
1.1 什么是Message和Chunk?
Message是RTMP协议中基本的数据单元,不同种类的消息包含不同的Message Type ID,代表不同的功能。RTMP协议中一共规定了十多种消息类型,java源码抖音分别发挥着不同的作用。
在网络上传输数据时,消息需要被拆分成较小的数据块,才适合在相应的网络环境上传输。RTMP协议中规定,消息在网络上传输时被拆分成消息块(Chunk)。
简单来说就是在一个 TCP 连接上,将需要传递的Message分成一个或者多个 Chunk,同一个Message 的多个Chunk 组成 ChunkStream,在接收端,再把 ChunkStream 中一个个 Chunk 组合起来就可以还原成一个完整的 Message
Message被拆分成一个或多个Chunk,然后在网络上发送
拆分的时候,默认的Chunk Size是字节,以Message大小为字节举例,进行拆分。
Message 拆分成 Chunk举例
1.2 Message
消息主要分为三类: 协议控制消息、数据消息、命令消息等。
协议控制消息
Message Type ID = 1 2 3 5 6 和 Message Type ID = 4 两大类,超凡娱乐棋牌源码主要用于协议内的控制,此部分后续详细分析。
数据消息
Message Type ID = 8 9
8: Audio 音频数据
9: Video 视频数据
: Metadata 包括音视频编码、视频宽高等信息。
命令消息
Command Message (, ) 此类型消息主要有NetConnection 和 NetStream两个类,两个类分别有多个函数,该消息的调用,可理解为远程函数调用。
常见消息格式
1.3 Chunk
Chunk格式
下面分别看看每个字段的含义
1.3.1 Basic Header
包含 chunk stream ID(流通道id)和chunk type(即fmt),chunk stream id 一般被简写为CSID,用来唯一标识一个特定的流通道,chunk type决定了后面Message Header的格式。Basic Header的长度可能是 1,2,或 3 个字节,其中 chunk type 的长度是固定的(占2位,单位是bit),Basic Header 的长度取决于 CSID 的大小,在足够存储这两个字段的前提下最好用尽量少的字节从而减少由于引入Header增加的数据量。RTMP协议支持用户自定义
之间的 CSID,0, 1, 2 由协议保留表示特殊信息。0 代表 Basic Header 总共要占用 2 个字节,CSID 在
之间; 1 代表占用 3 个字节,CSID 在
之间; 2 代表该 chunk 是控制信息和一些命令信息。
Basic Header:1 byte
0 1 2 3 4 5 6 7 - - - - - - - - |fmt| cs id | - - - - - - - -
Basic Header: 2 byte , csid == 0
CSID占bit,此时协议将于chunk type所在字节的其他bit都置为0,剩下的一个字节表示CSID - ,这样共有8个bit来存储 CSID,8 bit 可以表示
个数,因此这种情况下 CSID 在
,其中 = 。
0 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 - - - - - - - - - - - - - - - - |fmt| 0 | cs id - | - - - - - - - - - - - - - - - -
Basic Header: 3 bytes , csid == 1
CSID占bit,此时协议将第一个字节的
bit置1,余下的个bit表示CSID - ,这样共有个bit来存储CSID,bit可以表示
共 个数,因此这种情况下 CSID 在
,其中= ,需要注意的是,Basic Header是采用小端存储的方式,越往后的字节数量级越高,因此通过3个字节的每一个bit的值来计算CSID时,应该是: 第三个字节的值 * 第二个字节的值 。
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 - - - - - - - - - - - - - - - - - - - - - - - - |fmt| 1 | cs id - | - - - - - - - - - - - - - - - - - - - - - - - -
1.3.2 Message Header
包含了要发送的实际信息(可能是完整的,也可能是一部分)的描述信息。Message Header的格式和长度取决于Basic Header 的chunk type(即fmt)共有四种不同的格式。其中第一种格式可以表示其他三种表示的所有数据,但由于其他三种格式是基于对之前chunk的差量化的表示,因此可以更简洁地表示相同的数据,实际使用的时候还是应该采用尽量少的字节表示相同意义的数据。下面按字节从多到少的顺序分别介绍这四种格式的 Message Header。
Chunk Type(fmt) = 0: bytes
timestamp(时间戳)
:占用3个字节,因此它最多能表示到=0xFFFFFF=2^-1,当它的值超过这个最大值时,这三个字节都置为1,这样实际的timestamp会转存到 Extended Timestamp 字段中,接收端在判断timestamp字段个位都为1时就会去Extended Timestamp中解析实际的时间戳。
message length(消息数据长度
):占用3个字节,表示实际发送的消息的数据如音频帧、视频帧等数据的长度,单位是字节。注意这里是Message的长度,也就是chunk属于的Message的总长度,而不是chunk本身data的长度。
message type id(消息的类型id)
:1个字节,表示实际发送的数据的类型,如8代表音频数据,9代表视频数据。
message stream id(消息的流id)
:4个字节,表示该chunk所在的流的ID,和Basic Header 的CSID一样,它采用小端存储方式。
Chunk Type(fmt) = 1:7 bytes
type为1时占用7个字节,省去了表示message stream id的4个字节,表示此chunk和上一次发的 chunk 所在的流相同,如果在发送端和对端有一个流链接的时候可以尽量采取这种格式。
timestamp delta
:3 bytes,这里和type=0时不同,存储的是和上一个chunk的时间差。类似上面提到的timestamp,当它的值超过3个字节所能表示的最大值时,三个字节都置为1,实际的时间戳差值就会转存到Extended Timestamp字段中,接收端在判断timestamp delta字段个bit都为1时就会去Extended Timestamp 中解析实际的与上次时间戳的差值。
其他字段与上面的解释相同
.
Chunk Type(fmt) = 2:3 bytes
type 为 2 时占用 3 个字节,相对于 type = 1 格式又省去了表示消息长度的3个字节和表示消息类型的1个字节,表示此 chunk和上一次发送的 chunk 所在的流、消息的长度和消息的类型都相同。余下的这三个字节表示 timestamp delta,使用同type=1。
Chunk Type(fmt) = 3: 0 byte
type=3时,为0字节,表示这个chunk的Message Header和上一个是完全相同的。当它跟在type=0的chunk后面时,表示和前一个 chunk 的时间戳都是相同。什么时候连时间戳都是相同呢?就是一个 Message 拆分成多个 chunk,这个 chunk 和上一个 chunk 同属于一个 Message。而当它跟在 type = 1或 type = 2 的chunk后面时的chunk后面时,表示和前一个 chunk的时间戳的差是相同的。比如第一个 chunk 的 type = 0,timestamp = ,第二个 chunk 的 type = 2,timestamp delta = ,表示时间戳为 = ,第三个 chunk 的 type = 3,表示 timestamp delta = ,时间戳为 = 。