简介

RTMP 在可靠流式传输(TCP)的基础上提供了双向的消息多路复用服务,在通讯双方之间传输与时间相关的并行流数据,如音频,视频和数据消息。协议实现方通常为不同的消息类型指定不同的优先级,这样在网络带宽受限时能改变底层传输顺序。

定义字节序,校准,时间格式

所有整数都是以网络字节序来表示的。除非另行说明,本文中的所有数字都是十进制数。

在没有特殊说明的情况下,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 块流除自身内置的协议控制消息外,还为上层协议提供了用户控制消息的机制。

消息格式

消息格式由上层协议定义,消息可以被分成多个块以支持多路复用。消息应该包含分块功能所需的所有字段,具体内容如下:

握手

RTMP 连接以握手开始,它的握手过程可能和其他协议不同,这里的握手由 3 个固定大小的块组成,而不是可变大小的块加上固定大小的头。

握手流程

握手由客户端发送 C0 和 C1 块开始。

客户端必须等接收到 S1 之后才可以发送 C2。客户端必须等接收到 S2 之后才可以发送其他数据。

服务器必须等接收到 C0 之后才可以发送 S0 和 S1,也可能接收到 C1 之后发送。服务器必须等接收到 C1 之后才可以发送 S2。服务器必须等接收到 C2 之后才可以发送其他数据。

C0 和 S0 格式

C0 和 S0 是单独的一个字节,可以当做一个 8bit 的整数字段来对待。

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(1)

以下是 C0 和 S0 包的字段解释:

版本号(8 位): 在 C0 包中,该字段表示客户端请求的 RTMP 版本。在 S0 中,该字段表示服务器选择的 RTMP 版本。本规范所定义的版本是 3。可选值中,0-2 是早期版本所用的,已被丢弃,4-31 保留在未来使用,32-255 不允许使用(为了区分其他以某一可见字符开始的文本协议)。如果服务器不能识别客户端请求的版本,应该返回 3,客户端可能选择降级到版本 3,也可能放弃握手。

C1 和 S1 格式

C1 和 S1 包固定为 1536 字节,包含以下字段:

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(2)

C2 和 S2 格式

C2 和 S2 包的长度也为 1536 字节,基本上是 S1 和 C1 的回传,包含以下字段:

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(3)

相关视频推荐

音视频面试必问-RTSP/RTMP推流的各种坑分析_哔哩哔哩_bilibili

大型直播会议系统开发-webrtc-srs-rtmp-hls_哔哩哔哩_bilibili

学习地址:【免费】FFmpeg/WebRTC/RTMP/NDK/Android音视频流媒体高级开发-学习视频教程-腾讯课堂

需要更多ffmpeg/webrtc..音视频流媒体开发学习资料加群812855908领取

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(4)

握手流程示意图

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(5)

上图提到的状态的解释如下:

分块

握手完成后,一个或多个块流可能会复用同一个连接,每个块流承载来自同一个消息流的同一类消息。每个块都有一个唯一的块流 ID,这些块通过网络进行传输。在传输过程中,必须一个块发送完毕之后再发送下一个块。在接收端,将所有块根据块中的块流 ID 组装成消息。

分块将上层协议的大消息分割成小的消息,保证大的低优先级消息(比如视频)不阻塞小的高优先级消息(比如音频或控制消息)。

分块还能降低消息发送的开销,它在块头中包含了压缩的原本需要在消息中所包含的信息。

块大小是可配置的,这个可以通过一个设置块大小控制消息进行设定修改。越大的块 CPU 使用率越低,但是在低带宽的情况下,大的写入会阻塞其他内容的写入。而小一些的块不适合高比特率的流。

块格式

每个块由块头和数据组成,块头包含 3 部分:基本头、消息头和扩展时间戳。

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(6)

基本头

基本头包含块流 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 个字节来编码:

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(7)

64-319 范围内的块流 ID 用 2 个字节来编码,块流 ID 为计算所得,公式为:第二个字节值 64:

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(8)

64-65599 范围内的块流 ID 用 3 个字节来编码,块流 ID 为计算所得,公式为:第三个字节值 * 255 第二个字节值 64

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(9)

上述图中各个部分的含义如下:

64-319 范围内的块流 ID 可以用 2 字节来表示,也可以用 3 字节表示。

消息头

消息头共有 4 种不同的格式,根据基本头中的 “fmt” 字段值来确定。协议实现方应该用最紧凑的格式来表示块消息头。

类型 0

0 类型的块消息头占 11 个字节长度,该类型必须用在一个块流的开头,和每当块流时间戳回退的时候(例如视频回退的操作)。

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(10)

类型 1

1 类型的块消息头占用 7 个字节长度,不包含消息流 ID,该块沿用上一个消息的消息流 ID。对于传输大小可变消息的流(如多数视频格式),在发送第一个消息之后的每个消息都应该使用该类型格式。

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(11)

timestamp delta (3 字节): 时间戳增量。类型 1 和类型 2 的块包含此字段,表示前一个块的 timestamp 字段和当前块 timestamp 间的差值。 如果时间戳增量大于或等于 16777215 (0xFFFFFF),该字段必须为 16777215,并且必须设置扩展时间戳,来共同表示 32 位的时间戳增量,否则该字段值就是实际的时间戳增量。

类型 2

2 类型的块消息头占用 3 个字节长度,不包含消息流 ID 和消息长度,沿用上一个块的消息流 ID 和消息长度。对于传输固定大小消息的流(如音频和数据格式),在发送第一个消息之后的每一个消息都应该使用该类型格式。

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(12)

类型 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

这是一个简单的音频流消息,这是示例示范了信息冗余。

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(13)

下图展示该消息流以块流形式发送。从 3 类型块开始了数据传输优化,之后的块只附加了一个字节。

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(14)

示例 2

该示例展示了一个超过 128 字节长度的消息,消息被分割成了数个块。

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(15)

下图是被分割成的块:

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(16)

第一个块的头信息指明了消息总大小为 307 字节。

注意这两个示例,3 类型块可以在两种情况下使用。第一种情况是消息拆分成多个块,另一种情况是新消息复用上一个消息的所有头部内容。

协议控制消息

RTMP 块流用消息类型 1,2,3,5 和 6 来作为协议控制消息,这些消息包含 RTMP 块流协议所需要的信息。

这些协议控制消息必须用 0 作为消息流 ID (控制流 ID),并在 ID 为 2 的块流中发送。协议控制消息收到后立即生效,它们的时间戳信息是被忽略的。

设置块大小

协议控制消息类型 1:设置块大小,用于通知另一端新的最大块大小。

最大块大小默认为 128 字节,客户端或服务端可以修改此值,并用该消息通知另一端。例如,假设一个客户端想要发送 131 字节的音频数据,而最大块大小为 128。在这种情况下,客户端可以向服务端发送该消息,通知它最大块大小被设置为了 131 字节。这样客户端只用一个块就可以发送这些音频数据。

最大块大小不能小于 1 字节,通常应该不低于 128 字节。每个方向上的最大块大小是独立的。

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(17)

终止消息

协议控制消息类型 2:终止消息,通知正在等待消息后续块的另一端,可以丢弃指定块流接收到的数据,块流 ID 为该消息的载荷。应用可能在关闭的时候发送该消息,用来表明后面的消息没有必要继续处理了。

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(18)

chunk stream id (32 字节): 指定消息的块流 ID。

确认消息

客户端或服务器在收到数据总长和窗口大小相等时,通过它回复确认消息。在连接建立完成后,消息的发送方会通知接收方一个窗口的大小(指定一个长度),如果接收方收到指定长度的数据后没有发送回复消息,发送方就不会再发送任何内容了。

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(19)

sequence number (32 字节): 到当前时刻为止接收到的字节总数。

确认窗口大小

客户端或服务端发送该消息来通知对端发送确认消息所使用的视窗大小,并等待接收端发送确认消息。接收端在接收到视窗大小后必须发送确认消息。

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(20)

设置对方传输带宽

客户端或服务端发送该消息来限制对端的输出带宽。接收端收到消息后,可以直接使用消息中指定的窗口大小,而不需要等待收到确认消息之后。如果视窗大小与上一个视窗大小不同,则该消息的接收端应该向该消息的发送端发送新的窗口大小消息。这个消息和上一个消息都是调整窗口大小的,不同的地方是,这个消息是接收者请求发送者,让它调整窗口大小,而上一个消息是发送者主动设置了窗口大小,通知数据接收者。

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(21)

Limit Type(限制类型)有以下值:

RTMP 消息格式

虽然 RTMP 被设计成使用 RTMP 块流传输,但是它也可以使用其他传输协议来发送消息,在这种情况下 RTMP 消息的格式如下所示。值得一提的是,RTMP 块流协议和 RTMP 协议配合时,非常适合音视频应用,包括单播、一对多实时直播、视频点播和视频会议等。

格式

服务端和客户端通过在网络上发送 RTMP 消息实现之间的交互,消息包括音频、视频、数据等。

RTMP 消息包含两部分,消息头和有效负载。

RTMP 消息头

消息头包含以下信息:

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(22)

消息有效负载

消息的另一部分就是有效负载,也是消息包含的实际数据,可以是音频样本或者压缩的视频数据。

用户控制消息

RTMP 协议将消息类型 4 作为用户控制消息 ID,这些消息包含 RTMP 流所需的必要信息。消息类型 1,2,3,5 和 6 由 RTMP 块流协议使用。

用户控制消息应该使用 ID 为 0 的消息流(控制流),并且通过 RTMP 块流传输时使用 ID 为 2 的块流。用户控制消息收到后立即生效,它们的时间戳信息会被忽略。

客户端或服务端通过发送该消息告知对方用户控制事件。该消息携带事件类型和事件数据两部分。

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(23)

开头的 2 个字节用于指定事件类型,紧跟着是事件数据。事件数据字段长度可变,但是如果用 RTMP 块流传输,则消息总长度不能超过最大块大小,以使消息可以使用一个单独的块进行传输。

RTMP 指令消息

各种类型的消息在客户端和服务端之间进行交换,包括用于发送音频数据的音频消息,用于发送视频数据的视频消息,用于发送任意用户数据的数据消息,共享对象消息和指令消息等。共享对象消息的主要用途是管理客户端和相同服务器的共享数据。指令消息发送的是客户端与服务端之间的 AMF 编码指令,客户端或服务端也可以通过指令消息来实现远程过程调用(RPC)。

消息类型

客户端和服务端通过在网络上发送消息来实现交互,消息可以是任意类型,包括音频消息、视频消息、指令消息、共享对象消息、数据消息和用户控制消息等。

指令消息

指令消息在客户端和服务端之间传递 AMF 编码的指令,消息类型 20 代表 AMF0 编码,消息类型 17 代表 AMF3 编码。发送这些消息来完成连接、创建流、发布、播放、暂停等操作。像状态、结果这样的指令消息,用于通知发送方请求的指令状态。一条指令消息由指令名、事务 ID 和包含相关参数的指令对象组成。客户端或服务端还可以通过指令消息来实现远程过程调用 (RPC)。

数据消息

客户端或服务端通过该消息来发送元数据或其他用户数据。元数据包括数据 (音频、视频) 的创建时间、时长、主题等详细信息。消息类型 18 代表 AMF0 编码,消息类型 15 代表 AMF3 编码。

共享对象消息

共享对象是在多个客户端之间同步的 Flash 对象 (键值对集合)。消息类型 19 代表 AMF0 编码,消息类型 16 代表 AMF3 编码。每个消息都可以包含多个事件。

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(24)

支持以下事件类型:

音频消息

客户端或服务端通过发送此消息来发送音频数据给对方,消息类型 8 是为音频消息预留的。

视频消息

客户端或服务端通过发送此消息来发送视频数据给对方,消息类型 9 是为视频消息预留的。

组合消息

组合消息,是一个消息包含多个子 RTMP 消息,子消息符合 RTMP 消息格式。消息类型 22 用于组合消息。

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(25)

组合消息的消息流 ID 会覆盖其中子消息的消息流 ID。

组合消息的时间戳和其中第一个子消息的时间戳的差值,是用来将所有子消息的时间戳重整为流时间的位移量。位移量会加到每一个子消息的时间戳上来换算出正常的流时间。第一个子消息的时间戳应该与组合消息的时间戳相同,所以位移量应该为 0。

Back Pointer (反向指针) 包含前一个消息的长度(包括消息头),这样符合 flv 文件格式,可用于进行后退操作。

使用组合消息有以下好处:

用户控制消息事件

客户端或服务器通过该消息发送用户控制事件。

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(26)

用户控制消息支持以下事件:

指令类型

客户端和服务器交换 AMF 编码的指令。发送端发送一条指令消息,其中包含了指令名称、处理 ID、以及含有相关参数的指令对象。例如,连接指令消息包含了’app’ 参数,以告知服务器客户端希望连接的目标程序。接收端处理这条指令并回复含有同样处理 ID 的响应。回复的字符串可能为_result、_error 或方法名。如 verifyClient 或 contactExternalServer.

_result 或_error 的指令字符代表一条响应,处理 ID 则表明回复是针对哪条指令的,这在 IMAP 或其他协议中是完全相同的。指令字符串中的方法名表明发送端希望运行接收端上的一个方法。

指令消息可分为如下两类:

NetConnection 指令

NetConnection 管理着一个客户端程序和服务器之间的双向连接,除此之外,它还提供了对异步远程方法调用的支持。

下列指令可通过 NetConnection 进行发送:

Connect

客户端发送 connect 指令至服务器端以请求连接至某一服务器程序实例。

指令结构如下:

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(27)

Connect 指令中会用到的键值对:

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(28)

音频编码:

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(29)

视频编码:

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(30)

视频功能:

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(31)

对象编码:

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(32)

由服务器发送至客户端的指令结构如下:

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(33)

指令执行流程:

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(34)

指令执行的消息流如下:

Call

NetConnection 对象的 call 方法用于远程调用接收端上的程序。需要远程调用的程序名称通过一个参数传递给 call 指令。

发送指令结构如下:

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(35)

响应指令结构如下:

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(36)

CreateStream

客户端发送该指令至服务器端以创建一条用于传递消息的逻辑通道,从而可以利用已创建的流通道发布音频、视频和元数据。

NetConnection 是默认的通讯通道,流 ID 为 0。协议和一些指令消息,包括 createStream,使用默认通讯通道。

客户端发出的指令结构如下:

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(37)

服务器发出的指令结构如下:

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(38)

NetStream 指令

基于 NetConnection 的客户端至服务器间连接,NetStream 定义了一条可以传递音频流、视频流以及消息流的通道。NetConnection 对象支持多个 NetStreams 以传输多个数据流。

客户端可在 NetStream 中发送下列指令至服务器:

服务器端通过 “onStatus" 将 NetStream 的状态更新至客户端:

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(39)

Play

客户端发送该指令值以播放一个流。多次调用该指令也可创建一个播放清单。

如果你希望创建一个在不同 live 或 recorded 流间切换的动态播放清单,需要多次调用 play 并传递 false 以避免每次 reset。相反地,如果你希望立即播放某一指定流,传递 true 以清除等待播放队列中的所有其他流。

客户端发送的指令结构如下:

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(40)

流程图如下:

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(41)

指令执行期间的消息流如下:

Play2

不同于 play 指令,play2 可以切换码率而不改变播放内容的时间轴。服务器为客户端可以在 play2 中请求的所有支持的码率维护多个字段。

客户端发送的指令结构如下:

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(42)

该指令的消息流程如下图:

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(43)

DeleteStream

当 NetStream 对象将要被销毁时,它发送该 deleteStream 指令。

客户端发送的指令结构如下:

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(44)

服务器不需要发送任何应答。

ReceiveAudio

NetStream 发送 ReceiveAudio 消息通知服务器是否发送或不发送音频到客户端。

客户端发送的指令结构如下:

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(45)

如果 receiveAudio 指令发送带有 flase 的 bool flag,服务器不发送任何响应。如果这个标志被设置为 true,服务器应答 NetStream.Seek.Notify 和 NetStream.Play.Start 的状态消息。

ReceiveVideo

NetStream 发送 ReceiveVideo 消息通知服务器是否发送或不发送视频到客户端。

客户端发送的指令结构如下:

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(46)

​如果 receiveVideo 指令发送带有 flase 的 bool flag,服务器不发送任何响应。如果这个标志被设置为 true,服务器应答 NetStream.Seek.Notify 和 NetStream.Play.Start 的状态消息。

Publish

客户端发送 publish 指令将已命名的流发布到服务器上。使用这个名称,任何客户端都可以播放此流,并接收已发布的音频、视频和数据消息。

客户端发送的指令结构如下:

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(47)

​服务器应答 onStatus 指令,以标记发布的开始。

Seek

客户端发送 seek 指令以定位媒体文件内或者播放列表的某个位置(以毫秒为单位)。

客户端发送的指令结构如下:

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(48)

​当定位成功,服务器发送 NetStream.Seek.Notify 的状态消息。失败的时候,它返回一个_error 的消息。

Pause

客户端发送 pause 指令以告诉服务器暂停或者开始播放。

客户端发送的指令结构如下:

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(49)

​当流被暂停,服务器发送一个 NetStream.Pause.Notify 的状态消息。当一个流变成未暂停状态,NetStream.Unpause.Notify 被发送。失败的时候,它返回一个_error 的消息。

消息交换例子

这里是一些样例,以解释使用 RTMP 的消息交换。

发布视频

这个例子说明了一个发布者如何发布一个流并将视频流推到服务器上。其他客户端可以订阅这个已发布的流,并播放视频。

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(50)

广播一个共享对象消息

这个例子说明了在创建和更改共享对象时所交换的消息。它也说明了共享对象消息广播的过程。

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(51)

发布媒体流元数据

这个例子描述了发布元数据的消息交换。

rtmp协议详解中文版(超详细的流媒体传输协议之RTMP总结)(52)

,