共计 13065 个字符,预计需要花费 33 分钟才能阅读完成。
作者:逸殊
审核:泰一
简介
RTMP 在牢靠流式传输(TCP)的根底上提供了双向的音讯多路复用服务,在通信单方之间传输与工夫相干的并行流数据,如音频,视频和数据音讯。协定实现方通常为不同的音讯类型指定不同的优先级,这样在网络带宽受限时能扭转底层传输程序。
定义
- 负载:包中所承载的数据。例如音频或视频数据。
- 包:一个数据包由固定头部和所承载的数据组成。一些底层协定可能须要定义数据包的封装格局。
- 端口:在一个计算机中用于辨别不同指标的形象定义。在 TCP/IP 协定中用一个小的正整数来示意端口。OSI 传输层的传输选择器就相当于端口。
- 传输地址:标识一个传输终端的网络地址和端口的组合,例如 IP 地址和 TCP 端口的组合。
- 音讯流:容许音讯流传的逻辑通道。
- 音讯流 ID:每个音讯都会有一个对应的 ID,用于标识其所在的音讯流。
- 块:音讯的一个片段。音讯在传输之前会被宰割成更小的片段,因为每一块都很小,以至于能够给不同的块指定各自的优先级,通过这种形式保障多个流中数据能够依照工夫戳的程序传输。
- 块流:块向某一确定方向流传的逻辑通道。能够是客户端到服务端,也能够是服务端到客户端。
- 块流 ID:每个块都会有一个对应的 ID,用于标识其所在的块流。
- 复用:将独立的音频 / 视频数据整合为对立的音视频流,能够使多个音视频流同步传输。
- 复用拆散:复用的逆向过程。将合并的音视频数据拆散为原始的音频和视频数据。
- 近程过程调用:客户端或服务端调用另一端的性能。
- 元数据:媒体数据的形容信息。
- 利用实例:服务器上能够和 Client 建设连贯的利用。
- 动作音讯格局:一个可用于序列化 ActionScript 对象图的紧凑的二进制格局。
- 字节序:字节的程序,即多字节类型的数据在内存中的寄存程序。TCP/IP 各层协定将字节序定义为大端字节序,因而 TCP/IP 协定中应用的字节序通常称之为网络字节序。
- 大字节序:高位字节排放在内存的低地址,低位字节排放在内存的高地址。
- 小字节序:低位字节排放在内存的低地址,高位字节排放在内存的高地址。
字节序,校准,工夫格局
所有整数都是以网络字节序来示意的。除非另行阐明,本文中的所有数字都是十进制数。
在没有非凡阐明的状况下,RTMP 中的数据都是字节对齐的。如果有填充的话,填充字节应该用 0。
RTMP 中的工夫戳是用一个整数来示意的,代表绝对于一个起始工夫的毫秒数。通常每个流的工夫戳都从 0 开始,但这不是必须的,只有通信单方应用对立的起始工夫就能够了。要留神的是,跨流的工夫同步(不同主机之间)须要额定的机制来实现。
因为工夫戳的长度只有 32 位,所以只能在 50 天内循环(49 天 17 小时 2 分钟 47.296 秒)。而流是能够一直运行的,可能多年才会完结。所以 RTMP 利用在解决工夫戳是应该应用间断的数字算法,并且应该反对回环解决。例如:一个利用能够假如所有相邻的工夫戳距离不超过 2^31-1 毫秒,在此基础上,10000 在 4000000000 之后,3000000000 在 4000000000 之前。
工夫戳增量也是以毫秒为单位的无符号整数。工夫戳增量可能会是 24 位长度也可能是 32 位长度。
RTMP 块流
块流为下层流媒体协定提供复用和分包的性能。RTMP 块流是为配合 RTMP 协定而设计,但它能够应用在任何发送音讯流的协定中。每个音讯蕴含工夫戳和负载类型信息。RTMP 块流和 RTMP 协定组合能够实用于多种音视频利用,从一对一或一对多直播到视频会议都能很好的满足。
当应用牢靠传输协定(如 TCP)时,RTMP 块流为所有音讯提供了牢靠的跨流端对端按工夫戳程序发送的机制。RTMP 块流不提供优先级管制,然而能够由下层协定提供这样的优先级。例如:当某个客户端网络比较慢时,可能会抉择摈弃一些视频音讯来保障声音音讯可能及时接管。
RTMP 块流除本身内置的协定管制音讯外,还为下层协定提供了用户管制音讯的机制。
音讯格局
音讯格局由下层协定定义,音讯能够被分成多个块以反对多路复用。音讯应该蕴含分块性能所需的所有字段,具体内容如下:
- 工夫戳(4-byte):音讯的工夫戳。
- 长度(3-byte):音讯无效负载的长度,如果音讯头不能被省略,则音讯头的长度也应该蕴含在长度中。
- 类型 ID(1-byte):音讯类型 ID。一些类型 ID 是为协定管制音讯保留的,这些音讯所示意的信息同时供 RTMP 块流协定和下层协定应用。所有其余类型 ID 都用于下层协定,RTMP 块流对这些 ID 做不通明解决。实际上,RTMP 块流不须要用这些值来辨别类型,所有音讯都能够是雷同的类型,利用也能够用本字段来辨别同步轨道而不是辨别类型。
- 音讯流 ID(4-byte):音讯流 ID 能够是任意值。被复合到同一个块流的音讯流,根据音讯流 ID 进行拆散。另外,就相干的块流而言,这个值是不通明的。这个字段应用小字节序。
握手
RTMP 连贯以握手开始,它的握手过程可能和其余协定不同,这里的握手由 3 个固定大小的块组成,而不是可变大小的块加上固定大小的头。
握手流程
握手由客户端发送 C0 和 C1 块开始。
客户端必须等接管到 S1 之后才能够发送 C2。客户端必须等接管到 S2 之后才能够发送其余数据。
服务器必须等接管到 C0 之后才能够发送 S0 和 S1,也可能接管到 C1 之后发送。服务器必须等接管到 C1 之后才能够发送 S2。服务器必须等接管到 C2 之后才能够发送其余数据。
C0 和 S0 格局
C0 和 S0 是独自的一个字节,能够当做一个 8bit 的整数字段来看待。
以下是 C0 和 S0 包的字段解释:
- 版本号(8 位):在 C0 包中,该字段示意客户端申请的 RTMP 版本。在 S0 中,该字段示意服务器抉择的 RTMP 版本。本标准所定义的版本是 3。可选值中,0-2 是晚期版本所用的,已被抛弃,4-31 保留在将来应用,32-255 不容许应用(为了辨别其余以某一可见字符开始的文本协定)。如果服务器不能辨认客户端申请的版本,应该返回 3,客户端可能抉择降级到版本 3,也可能放弃握手。
C1 和 S1 格局
C1 和 S1 包固定为 1536 字节,蕴含以下字段:
- 工夫戳(4 字节):该字段承载一个工夫戳,该工夫戳应该作为发送端点所有后续块的工夫戳起始工夫。能够是 0,也能够是其余的任意值。为了同步多个块流,端点可能会发送其余块流的以后工夫戳。
- 零值(4 字节):该字段所有值都必须为 0。
- 随机数据(1528 字节):该字段能够是任意值。通过这个字段来辨别本人和连贯的另一方,所以此数据应该有充沛的随机性,然而没必要应用加密平安的随机值或动静值。
C2 和 S2 格局
C2 和 S2 包的长度也为 1536 字节,基本上是 S1 和 C1 的回传,蕴含以下字段:
- 工夫戳(4 字节):该字段必须蕴含对端发来的工夫戳(对 C2 来说是 S1,对 S2 来说是 C1)。
- 工夫 2(4 字节):该字段必须蕴含先前发送的并被对端读取的包的工夫戳。(对 C2 来说是 C1,对 S2 来说是 S1)。
- 随机数据回显(1528 字节):该字段必须蕴含对端发送过去的随机数据字段值(对 C2 来说是 S1,对 S2 来说是 C1)。任何一端都能够用工夫戳和工夫戳 2 两个字段值和以后工夫戳来疾速的估算带宽和提早,但这样可能并不实用。
握手流程示意图
上图提到的状态的解释如下:
- Uninitialized:未初始化状态。在该阶段发送协定版本。客户端在 C0 包中发送 RTMP 协定版本,如果服务器反对此版本,服务器将在响应中发送 S0 和 S1。如果不反对,服务器采纳适当的行为作为响应,在 RTMP 标准中是终止连贯。
- Version Send:版本已发送状态。在未初始化状态之后客户端和服务端都进入版本已发送状态。客户端期待接管 S1 包,服务端期待接管 C1 包。收到所期待的包后,客户端发送 C2 包,服务端发送 S2 包。之后状态进入发送确认状态。
- Ack Send:客户端和服务端期待接管 S2 和 C2 包,收到后进入握手实现状态。
- Handshake Done:握手实现,客户端和服务端开始替换音讯。
分块
握手实现后,一个或多个块流可能会复用同一个连贯,每个块流承载来自同一个音讯流的同一类音讯。每个块都有一个惟一的块流 ID,这些块通过网络进行传输。在传输过程中,必须一个块发送结束之后再发送下一个块。在接收端,将所有块依据块中的块流 ID 组装成音讯。
分块将下层协定的大音讯宰割成小的音讯,保障大的低优先级音讯(比方视频)不阻塞小的高优先级音讯(比方音频或管制音讯)。
分块还能升高音讯发送的开销,它在块头中蕴含了压缩的本来须要在音讯中所蕴含的信息。
块大小是可配置的,这个能够通过一个设置块大小管制音讯进行设定批改。越大的块 CPU 使用率越低,然而在低带宽的状况下,大的写入会阻塞其余内容的写入。而小一些的块不适宜高比特率的流。
块格局
每个块由块头和数据组成,块头蕴含 3 局部:根本头、音讯头和扩大工夫戳。
- 根本头 (1-3 字节):块流 ID 和块类型,块类型决定了之后音讯头的编码格局。根本头的长度取决于块流 ID,当块流 ID 越大时所须要的字节数越多。
- 音讯头 (0,3,7 或 11 字节):所发送音讯的形容信息。该局部的长度取决于根本头中指定的块类型。
- 扩大工夫戳 (0 或 4 字节):该局部只有在某些非凡状况下才会应用,是否应用取决于工夫戳或工夫戳增量是否超出了块音讯头中相应字段的形容范畴。
- 块数据 (变长):块承载的无效数据,最大长度为配置的块大小。
根本头
根本头蕴含块流 ID 和块类型(在下图中用 fmt 字段示意),块类型决定了音讯头的编码格局,根本头长度可能是 1,2 或 3 字节,这取决于块流 ID 的长度。
协定实现方应该用可能用最短表示法来示意块流 ID。
RTMP 最多反对 65597 个流,ID 在 3-65599 范畴内,0,1,2 为保留值。如果 2~7 位代表的值为 0 示意块根本头占 2 个字节,并且块流 ID 范畴在 64-319 之间(第二个字节 + 64),如果 2~7 位代表的值为 1 示意块根本头占 3 个字节,并且 ID 范畴在 64-65599 之间(第三个字节 * 256 + 第二个字节 + 64),当 ID 在 3-63 之间时间接应用 2~7 位的值来示意流 ID。
2-63 范畴内的块流 ID 用 1 个字节来编码:
64-319 范畴内的块流 ID 用 2 个字节来编码,块流 ID 为计算所得,公式为:第二个字节值 + 64:
64-65599 范畴内的块流 ID 用 3 个字节来编码,块流 ID 为计算所得,公式为:第三个字节值 * 255 + 第二个字节值 + 64
上述图中各个局部的含意如下:
- cs id (6 位):该字段示意残缺的块流 ID,取值在 2-63 之间。0,1 两个值是保留值,用来示意根本头是 2 字节还是 3 字节长度。
- fmt:该字段表明了音讯头应用的格局。
- cs id – 64 (8 位或 16 位):该字段示意块流 ID,取值在 64-63399 之间。
64-319 范畴内的块流 ID 能够用 2 字节来示意,也能够用 3 字节示意。
音讯头
音讯头共有 4 种不同的格局,依据根本头中的 “fmt” 字段值来确定。协定实现方应该用最紧凑的格局来示意块音讯头。
类型 0
0 类型的块音讯头占 11 个字节长度,该类型必须用在一个块流的结尾,和每当块流工夫戳回退的时候(例如视频回退的操作)。
- timestamp (3 字节):对于 0 类型的音讯块,音讯的相对工夫戳在这里发送。如果工夫戳大于或等于 16777215 (0xFFFFFF),改字段值必须为 16777215,并且必须设置扩大工夫戳来独特编码 32 位的工夫戳。否则该字段就是残缺的工夫戳。
- message length (3 字节): 音讯长度,类型 0 和类型 1 的块蕴含此字段,示意音讯的长度。要留神的是,通常音讯长度与块长度并不相同。块长度除了最初一个块之外,都与块最大长度雷同。
- message type id (3 字节): 音讯类型 id,类型 0 和类型 1 的块蕴含此字段,示意音讯的类型。
- message stream id (4 字节): 音讯流 ID,类型 0 的块蕴含此字段,示意音讯流 ID。音讯流 ID 以小字节序存储。通常,雷同块流中的音讯属于用一个音讯流。尽管,不同的音讯流复用雷同的块流会导致音讯头无奈无效压缩,然而当一个音讯流已敞开,筹备关上另外一个音讯流时,就能够通过发送一个新的 0 类型块来实现复用。
类型 1
1 类型的块音讯头占用 7 个字节长度,不蕴含音讯流 ID,该块沿用上一个音讯的音讯流 ID。对于传输大小可变音讯的流(如少数视频格式),在发送第一个音讯之后的每个音讯都应该应用该类型格局。
- timestamp delta (3 字节): 工夫戳增量。类型 1 和类型 2 的块蕴含此字段,示意前一个块的 timestamp 字段和以后块 timestamp 间的差值。如果工夫戳增量大于或等于 16777215 (0xFFFFFF),该字段必须为 16777215,并且必须设置扩大工夫戳,来独特示意 32 位的工夫戳增量,否则该字段值就是理论的工夫戳增量。
类型 2
2 类型的块音讯头占用 3 个字节长度,不蕴含音讯流 ID 和音讯长度,沿用上一个块的音讯流 ID 和音讯长度。对于传输固定大小音讯的流(如音频和数据格式),在发送第一个音讯之后的每一个音讯都应该应用该类型格局。
类型 3
3 类型的块没有音讯头,音讯流 ID、音讯长度和工夫戳增量,该类型的块应用和上一个块雷同的头数据。当一个音讯被宰割成块时,除了第一个块,其余块都应该应用该类型。由雷同大小、音讯流 ID 和工夫距离的音讯组成的流,在类型 2 的块之后所有块都应该应用该类型格局。如果第一个音讯和第二音讯之间的工夫增量与第一个音讯的工夫戳雷同,则 0 类型的块之后能够马上发送 3 类型的块,而不用应用 2 类型的块来注册工夫增量。如果类型 3 的块跟在类型 0 的块前面,那么 3 类型块的工夫戳增量与 0 类型块的工夫戳雷同。
扩大工夫戳
扩大工夫戳用来辅助编码超过 16777215 (0xFFFFFF) 的工夫戳或工夫戳增量,也就说音讯头无奈用 24 位数字来示意工夫戳或工夫戳增量时,既 0 类型块的工夫戳字段或 1,2 类型的工夫戳增量字段值为 16777215 (0xFFFFFF)。当最近的属于雷同块流 ID 的 0 类型块、1 类型块或 2 类型块有此字段时有此字段时,3 类型块也应该有此字段。
示例
示例 1
这是一个简略的音频流音讯,这是示例示范了信息冗余。
下图展现该音讯流以块流模式发送。从 3 类型块开始了数据传输优化,之后的块只附加了一个字节。
示例 2
该示例展现了一个超过 128 字节长度的音讯,音讯被宰割成了数个块。
下图是被宰割成的块:
第一个块的头信息指明了音讯总大小为 307 字节。
留神这两个示例,3 类型块能够在两种状况下应用。第一种状况是音讯拆分成多个块,另一种状况是新音讯复用上一个音讯的所有头部内容。
协定管制音讯
RTMP 块流用音讯类型 1,2,3,5 和 6 来作为协定管制音讯,这些音讯蕴含 RTMP 块流协定所须要的信息。
这些协定管制音讯必须用 0 作为音讯流 ID (控制流 ID),并在 ID 为 2 的块流中发送。协定管制音讯收到后立刻失效,它们的工夫戳信息是被疏忽的。
设置块大小
协定管制音讯类型 1:设置块大小,用于告诉另一端新的最大块大小。
最大块大小默认为 128 字节,客户端或服务端能够批改此值,并用该音讯告诉另一端。例如,假如一个客户端想要发送 131 字节的音频数据,而最大块大小为 128。在这种状况下,客户端能够向服务端发送该音讯,告诉它最大块大小被设置为了 131 字节。这样客户端只用一个块就能够发送这些音频数据。
最大块大小不能小于 1 字节,通常应该不低于 128 字节。每个方向上的最大块大小是独立的。
- 0 (1 位): 该位必须为 0.
- chunk size (31 位): 该字段以字节模式保留新的最大块大小,该值将用于后续的所有块的发送,直到收到新的告诉。该值可取值范畴为 1-2147483647 (0x7FFFFFFF),然而所有大于 1677215 (0xFFFFFF) 的值都是视作是 16777215,因为任何块不可能比音讯大,而音讯长度不能大于 16777215 字节。
终止音讯
协定管制音讯类型 2:终止音讯,告诉正在期待音讯后续块的另一端,能够抛弃指定块流接管到的数据,块流 ID 为该音讯的载荷。利用可能在敞开的时候发送该音讯,用来表明前面的音讯没有必要持续解决了。
- chunk stream id (32 字节): 指定音讯的块流 ID。
确认音讯
客户端或服务器在收到数据总长和窗口大小相等时,通过它回复确认音讯。在连贯建设实现后,音讯的发送方会告诉接管方一个窗口的大小(指定一个长度),如果接管方收到指定长度的数据后没有发送回复音讯,发送方就不会再发送任何内容了。
- sequence number (32 字节): 到以后时刻为止接管到的字节总数。
确认窗口大小
客户端或服务端发送该音讯来告诉对端发送确认音讯所应用的视窗大小,并期待接收端发送确认音讯。接收端在接管到视窗大小后必须发送确认音讯。
设置对方传输带宽
客户端或服务端发送该音讯来限度对端的输入带宽。接收端收到音讯后,能够间接应用音讯中指定的窗口大小,而不须要期待收到确认音讯之后。如果视窗大小与上一个视窗大小不同,则该音讯的接收端应该向该音讯的发送端发送新的窗口大小音讯。这个音讯和上一个音讯都是调整窗口大小的,不同的中央是,这个音讯是接收者申请发送者,让它调整窗口大小,而上一个音讯是发送者被动设置了窗口大小,告诉数据接收者。
Limit Type(限度类型)有以下值:
- 0 – Hard: 应该将输入带宽限度为指定视窗大小。
- 1 – Soft: 应该将输入带宽限度为指定视窗大小和以后视窗大小中较小的值。
- 2 – Dynamic: 如果上一个音讯的限度类型为 Hard,则该音讯同样为 Hard,否则摈弃该音讯。
RTMP 音讯格局
尽管 RTMP 被设计成应用 RTMP 块流传输,然而它也能够应用其余传输协定来发送音讯,在这种状况下 RTMP 音讯的格局如下所示。值得一提的是,RTMP 块流协定和 RTMP 协定配合时,非常适合音视频利用,包含单播、一对多实时直播、视频点播和视频会议等。
格局
服务端和客户端通过在网络上发送 RTMP 音讯实现之间的交互,音讯包含音频、视频、数据等。
RTMP 音讯蕴含两局部,音讯头和无效负载。
RTMP 音讯头
音讯头蕴含以下信息:
- Message Type: 音讯类型,占用 1 个字节。1-6 的音讯类型 ID 是为协定管制音讯保留的。
- Length: 无效负载的字节数,占用 3 个字节。该字段是用大端序示意的。
- Timestamp: 工夫戳,占用 4 个字节,用大端序示意。
- Message Stream Id: 音讯流 ID,标识音讯所应用的流,用大端序示意。
音讯无效负载
音讯的另一部分就是无效负载,也是音讯蕴含的理论数据,能够是音频样本或者压缩的视频数据。
用户管制音讯
RTMP 协定将音讯类型 4 作为用户管制音讯 ID,这些音讯蕴含 RTMP 流所需的必要信息。音讯类型 1,2,3,5 和 6 由 RTMP 块流协定应用。
用户管制音讯应该应用 ID 为 0 的音讯流(控制流),并且通过 RTMP 块流传输时应用 ID 为 2 的块流。用户管制音讯收到后立刻失效,它们的工夫戳信息会被疏忽。
客户端或服务端通过发送该音讯告知对方用户管制事件。该音讯携带事件类型和事件数据两局部。
结尾的 2 个字节用于指定事件类型,紧跟着是事件数据。事件数据字段长度可变,然而如果用 RTMP 块流传输,则音讯总长度不能超过最大块大小,以使音讯能够应用一个独自的块进行传输。
RTMP 指令音讯
各种类型的音讯在客户端和服务端之间进行替换,包含用于发送音频数据的音频音讯,用于发送视频数据的视频音讯,用于发送任意用户数据的数据音讯,共享对象音讯和指令音讯等。共享对象音讯的主要用途是治理客户端和雷同服务器的共享数据。指令音讯发送的是客户端与服务端之间的 AMF 编码指令,客户端或服务端也能够通过指令音讯来实现近程过程调用(RPC)。
音讯类型
客户端和服务端通过在网络上发送音讯来实现交互,音讯能够是任意类型,包含音频音讯、视频音讯、指令音讯、共享对象音讯、数据音讯和用户管制音讯等。
指令音讯
指令音讯在客户端和服务端之间传递 AMF 编码的指令,音讯类型 20 代表 AMF0 编码,音讯类型 17 代表 AMF3 编码。发送这些音讯来实现连贯、创立流、公布、播放、暂停等操作。像状态、后果这样的指令音讯,用于告诉发送方申请的指令状态。一条指令音讯由指令名、事务 ID 和蕴含相干参数的指令对象组成。客户端或服务端还能够通过指令音讯来实现近程过程调用 (RPC)。
数据音讯
客户端或服务端通过该音讯来发送元数据或其余用户数据。元数据包含数据 (音频、视频) 的创立工夫、时长、主题等详细信息。音讯类型 18 代表 AMF0 编码,音讯类型 15 代表 AMF3 编码。
共享对象音讯
共享对象是在多个客户端之间同步的 Flash 对象 (键值对汇合)。音讯类型 19 代表 AMF0 编码,音讯类型 16 代表 AMF3 编码。每个音讯都能够蕴含多个事件。
反对以下事件类型:
- 创立(1):客户端向服务端发送,申请创立指定名称的共享对象。
- 开释(2):客户端告诉服务端,共享对象已在本地删除。
- 申请更新(3):客户端申请批改共享对象的属性值。
- 更新(4):告诉服务端向除本人外的其余客户端发送共享数据音讯,告诉它们有属性的值产生了变动。
- 胜利(5):“申请更新”事件被承受后,服务端向发送申请的客户端回复此事件。
- 发送音讯(6):客户端向服务端发送此事件,来播送一个音讯。服务端收到此事件后向所有客户端播送一条音讯,包含申请方客户端。
- 状态(7):服务端发送此事件来告诉客户端错误信息。
- 革除(8):服务端向客户端发送此事件,告诉客户端革除一个共享对象。服务端在回复客户端的“创立”事件时也会发送此事件。
- 移除(9):服务端发送此事件,使客户端删除一个插槽。
- 申请移除(10):客户端删除一个插槽时发送此事件。
- 创立胜利(11):当连贯胜利时服务端向客户端发送此事件。
音频音讯
客户端或服务端通过发送此音讯来发送音频数据给对方,音讯类型 8 是为音频音讯预留的。
视频音讯
客户端或服务端通过发送此音讯来发送视频数据给对方,音讯类型 9 是为视频音讯预留的。
组合音讯
组合音讯,是一个音讯蕴含多个子 RTMP 音讯,子音讯合乎 RTMP 音讯格局。音讯类型 22 用于组合音讯。
组合音讯的音讯流 ID 会笼罩其中子音讯的音讯流 ID。
组合音讯的工夫戳和其中第一个子音讯的工夫戳的差值,是用来将所有子音讯的工夫戳重整为流工夫的位移量。位移量会加到每一个子音讯的工夫戳上来换算出失常的流工夫。第一个子音讯的工夫戳应该与组合音讯的工夫戳雷同,所以位移量应该为 0。
Back Pointer (反向指针) 蕴含前一个音讯的长度(包含音讯头),这样合乎 flv 文件格式,可用于进行后退操作。
应用组合音讯有以下益处:
- 块流协定中,一个块最多只能发送一个音讯,这样就应用组合音讯,加大块大小,从而升高发送的块数量。
- 子音讯在内存中间断寄存,这样零碎调用网络发送数据的性能更高。
用户管制音讯事件
客户端或服务器通过该音讯发送用户管制事件。
用户管制音讯反对以下事件:
- 流开始(0):服务端发送该事件,用来告诉客户端一个流曾经能够用来通信了。默认状况下,该事件是在收到客户端连贯指令并胜利解决后发送的第一个事件。事件的数据应用 4 个字节来示意可用的流的 ID。
- 流完结(1):服务端发送该事件,用来告诉客户端其在流中申请的数据曾经完结了。如果没有额定的指令,将不会再发送任何数据,而客户端会抛弃之后从该流接管到的音讯。事件数据应用 4 个字节来示意回放实现的流的 ID。
- 流枯竭(2):服务端发送该事件,用来告诉客户端流中曾经没有更多的数据了。如果服务端在肯定工夫后没有探测到更多数据,它就能够告诉所有订阅该流的客户端,流曾经枯竭。事件数据用 4 个字节来示意枯竭的流的 ID。
- 设置缓冲区大小(3):客户端发送该事件,用来告知服务端用来缓存流中数据的缓冲区大小 (单位毫秒)。该事件在服务端开始解决流数据之前发送。事件数据中,前 4 个字节用来示意流 ID,之后的 4 个字节用来示意缓冲区大小(单位毫秒)。
- 流已录制(4):服务端发送该事件,用来告诉客户端指定流是一个录制流。事件数据用 4 个字节示意录制流的 ID。
- ping 申请(5):服务端发送该事件,用来探测客户端是否处于可达状态。事件数据是一个 4 字节的工夫戳,示意服务端散发该事件时的服务器本地工夫。客户端收到后用 ping 响应回复服务端。
- ping 响应(6):客户端用该事件回复服务端的 ping 申请,事件数据为收到的 ping 申请中携带的 4 字节的工夫戳。
指令类型
客户端和服务器替换 AMF 编码的指令。发送端发送一条指令音讯,其中蕴含了指令名称、解决 ID、以及含有相干参数的指令对象。例如,连贯指令音讯蕴含了’app’ 参数,以告知服务器客户端心愿连贯的目标程序。接收端解决这条指令并回复含有同样解决 ID 的响应。回复的字符串可能为_result、_error 或办法名。如 verifyClient 或 contactExternalServer.
_result 或_error 的指令字符代表一条响应,解决 ID 则表明回复是针对哪条指令的,这在 IMAP 或其余协定中是完全相同的。指令字符串中的办法名表明发送端心愿运行接收端上的一个办法。
指令音讯可分为如下两类:
- NetConnection:一个服务器和客户端之间连贯的高层表现对象。
- NetStream:一个音频流、视频流及其他相干数据传输流,咱们会发送如播放、暂停等指令来控制数据流动。
NetConnection 指令
NetConnection 治理着一个客户端程序和服务器之间的双向连贯,除此之外,它还提供了对异步近程办法调用的反对。
下列指令可通过 NetConnection 进行发送:
- Connect
- Call
- Close
- CreateStream
Connect
客户端发送 connect 指令至服务器端以申请连贯至某一服务器程序实例。
指令构造如下:
Connect 指令中会用到的键值对:
音频编码:
视频编码:
视频性能:
对象编码:
由服务器发送至客户端的指令构造如下:
指令执行流程:
指令执行的音讯流如下:
- 客户端发送 connect 指令至服务器以申请连贯至服务器端程序实例。
- 在收到连贯指令后,服务器端发送协定音讯 ‘Window Acknowledgement Size’ 给客户端。同时,服务器端还会连贯 connect 指令中提到的利用。
- 服务器端发送协定音讯‘Set Peer Bandwidth’至客户端。
- 客户端胜利解决‘Set Peer Bandwidth’后发送协定音讯‘Window Acknowledgement Size’ 给服务器端。
- 服务器端发送用户管制音讯(StreamBegin)协定音讯给客户端。
- 服务器端发送指令音讯以告诉客户端连贯状态(success/fail)。该指令中含有解决 ID (与 1 中收到雷同),该音讯同时还制订了局部属性,如 Flash Media Server 版本(string)。除此之外,它还指定了连贯响应相干的信息如 level (string),code (string),description (string),object-encoding (number) 等。
Call
NetConnection 对象的 call 办法用于近程调用接收端上的程序。须要近程调用的程序名称通过一个参数传递给 call 指令。
发送指令构造如下:
响应指令构造如下:
CreateStream
客户端发送该指令至服务器端以创立一条用于传递音讯的逻辑通道,从而能够利用已创立的流通道公布音频、视频和元数据。
NetConnection 是默认的通信通道,流 ID 为 0。协定和一些指令音讯,包含 createStream,应用默认通信通道。
客户端收回的指令构造如下:
服务器收回的指令构造如下:
NetStream 指令
基于 NetConnection 的客户端至服务器间连接,NetStream 定义了一条能够传递音频流、视频流以及音讯流的通道。NetConnection 对象反对多个 NetStreams 以传输多个数据流。
客户端可在 NetStream 中发送下列指令至服务器:
- Play
- Play2
- DeleteStream
- CloseStream
- ReceiveAudio
- ReceiveVideo
- Publish
- Seek
- Pause
服务器端通过“onStatus” 将 NetStream 的状态更新至客户端:
Play
客户端发送该指令值以播放一个流。屡次调用该指令也可创立一个播放清单。
如果你心愿创立一个在不同 live 或 recorded 流间切换的动静播放清单,须要屡次调用 play 并传递 false 以防止每次 reset。相同地,如果你心愿立刻播放某一指定流,传递 true 以革除期待播放队列中的所有其余流。
客户端发送的指令构造如下:
流程图如下:
指令执行期间的音讯流如下:
- 客户端在接管到来自服务器的 createStream 指令的胜利后果后发送 play 指令。
- 在接管到 play 指令后,服务器发送协定数据来设置块大小。
- 服务器发送一些另外一个协定数据 (用户管制),在这个音讯里蕴含事件“StreamIsRecord”和流 ID。这个音讯的前 2 个字节是事件类型随后的 4 字节是流 ID。
- 服务器向客户端发送另外一个协定音讯 (用户管制),这个音讯批示了“StreamBegin”事件,示意流开始了。
- 如果客户端向服务器发送的 play 指令胜利执行了,服务器会发送 onStatus 指令音讯蕴含 NetStream.Play.Start 或 NetStream.Play.Reset。仅当客户端发送的 play 指令中的设置了 reset 标记 NetStream.Play.Reset 才会被发送。如果播放的流不存在,服务器会在发送 onStatus 音讯中蕴含 NetStream.Play.StreamNotFound。随后,服务器就发送客户端播放的音频和视频数据。
Play2
不同于 play 指令,play2 能够切换码率而不扭转播放内容的时间轴。服务器为客户端能够在 play2 中申请的所有反对的码率保护多个字段。
客户端发送的指令构造如下:
该指令的音讯流程如下图:
DeleteStream
当 NetStream 对象将要被销毁时,它发送该 deleteStream 指令。
客户端发送的指令构造如下:
服务器不须要发送任何应答。
ReceiveAudio
NetStream 发送 ReceiveAudio 音讯告诉服务器是否发送或不发送音频到客户端。
客户端发送的指令构造如下:
如果 receiveAudio 指令发送带有 flase 的 bool flag,服务器不发送任何响应。如果这个标记被设置为 true,服务器应答 NetStream.Seek.Notify 和 NetStream.Play.Start 的状态音讯。
ReceiveVideo
NetStream 发送 ReceiveVideo 音讯告诉服务器是否发送或不发送视频到客户端。
客户端发送的指令构造如下:
如果 receiveVideo 指令发送带有 flase 的 bool flag,服务器不发送任何响应。如果这个标记被设置为 true,服务器应答 NetStream.Seek.Notify 和 NetStream.Play.Start 的状态音讯。
Publish
客户端发送 publish 指令将已命名的流公布到服务器上。应用这个名称,任何客户端都能够播放此流,并接管已公布的音频、视频和数据音讯。
客户端发送的指令构造如下:
服务器应答 onStatus 指令,以标记公布的开始。
Seek
客户端发送 seek 指令以定位媒体文件内或者播放列表的某个地位(以毫秒为单位)。
客户端发送的指令构造如下:
当定位胜利,服务器发送 NetStream.Seek.Notify 的状态音讯。失败的时候,它返回一个_error 的音讯。
Pause
客户端发送 pause 指令以通知服务器暂停或者开始播放。
客户端发送的指令构造如下:
当流被暂停,服务器发送一个 NetStream.Pause.Notify 的状态音讯。当一个流变成未暂停状态,NetStream.Unpause.Notify 被发送。失败的时候,它返回一个_error 的音讯。
音讯替换例子
这里是一些样例,以解释应用 RTMP 的音讯替换。
公布视频
这个例子阐明了一个发布者如何公布一个流并将视频流推到服务器上。其余客户端能够订阅这个已公布的流,并播放视频。
播送一个共享对象音讯
这个例子阐明了在创立和更改共享对象时所替换的音讯。它也阐明了共享对象音讯播送的过程。
公布媒体流元数据
这个例子形容了公布元数据的音讯替换。
参考内容
[1] RTMP 标准
[2] RTMP 协定标准翻译工作
[3] RTMP 协定标准 1.0 中文版
「视频云技术」你最值得关注的音视频技术公众号,每周推送来自阿里云一线的实际技术文章,在这里与音视频畛域一流工程师交换切磋。