一、RTMP区块流(RTMP Chunk Stream)
【1】消息格式(Message Format)
可以被分割成块以支持多路复用的消息格式取决于更高级别的协议。但是,消息格式应该包含以下字段,这些字段是创建块所必需的。
Timestamp:消息的时间戳。此字段可以传输4个字节。
Length:消息有效负载的长度。如果不能省略消息头,则应将其包含在长度中。此字段在块头中占用3个字节。
Type Id:为协议控制消息保留一系列类型id。这些传播信息的消息由RTMP块流协议和更高级别的协议处理。
所有其他类型id都可供更高级别的协议使用,并被RTMP Chunk Stream视为不透明值。事实上,RTMP Chunk Stream中没有任何东西要求将这些值用作类型;所有(非协议)消息可以是同一类型的,或者应用程序可以使用此字段来区分同时跟踪而不是类型。此字段在块头中占用1字节。
Message Stream ID:消息流ID可以是任意值。复用到同一块流上的不同消息流根据它们的消息流id被解复用。除此之外,就RTMP Chunk Stream而言,这是一个不透明的值。此字段在小端格式的块头中占用4个字节。
【2】握手(Handshake)
RTMP连接从握手开始。握手与协议的其他部分不同;它由三个静态(固定)大小的块组成,而不是由带有头的可变大小的块组成。
客户端(启动连接的端点)和服务器分别发送相同的三个数据块。为了说明,当客户端发送时,这些块将被指定为C0、C1和C2;服务器发送时为S0、S1和S2。
【A】握手顺序(Handshake Sequence)
(1)握手从客户端发送C0和C1块开始。客户机必须等到收到S1之后才能发送C2。在发送任何其他数据之前,客户端必须等到接收到S2。
(2)在发送S0和S1之前,服务器必须等到接收到C0,也可以等到C1之后。在发送S2之前,服务器必须等到接收到C1。在发送任何其他数据之前,服务器必须等待接收到C2。
【B】C0和S0格式(C0 and S0 Format)
C0和S0数据包是单个八位字节,被视为单个8位整数字段:
以下是C0/S0数据包中的字段:
版本(8位)[Version (8 bits)]:在C0中,此字段标识客户端请求的RTMP版本。在S0中,此字段标识服务器选择的RTMP版本。本规范定义的版本为3。0-2是早期专有产品使用的不推荐值;4-31为将来的实施预留;和32-255是不允许的(允许将RTMP与基于文本的协议区分开来,基于文本的协议总是以可打印字符开头)。无法识别客户端请求的版本的服务器应以3响应。客户端可以选择降级到版本3,或放弃握手。
【C】C1和S1格式(C1 and S1 Format)
C1和S1数据包的长度为1536个八位字节,由以下字段组成:
(1)时间(4字节)[Time (4 bytes)]:此字段包含一个时间戳,该时间戳应用作从此端点发送的所有未来块的历元(纪元)。这个值可以是0,也可以是任意值。要同步多个chunkstreams,端点可能希望发送另一个chunkstream的时间戳的当前值。
(2)零(4字节)[Zero (4 bytes)]:此字段必须全部为0。
(3)随机数据(1528字节)[Random data (1528 bytes)]:此字段可以包含任意值。由于每个端点必须区分它发起的握手和它的对等方发起的握手的响应,因此这些数据应该发送足够随机的内容。但不需要加密安全的随机性,甚至不需要动态值。
【D】C2和S2格式(C2 and S2 Format)
C2和S2数据包有1536个八位字节长,几乎是S1和C1(分别)的回声(响应),由以下字段组成:
(1)时间(4字节)[Time (4 bytes)]:此字段必须包含S1(对于C2)或C1(对于S2)中对等方发送的时间戳。
(2)Time2(4字节)[Time2 (4 bytes)]:此字段必须包含读取对等方发送的上一个数据包(s1或c1)的时间戳。
(3)随机回音(响应)(1528字节)[Random echo (1528 bytes)]:此字段必须包含S1(对于C2)或S2(对于C1)中对等方发送的随机数据字段。任何一个对等方都可以使用time和time2字段以及当前时间戳来快速估计连接的带宽和/或延迟,但这不太可能有用。
【E】握手示意图(Handshake Diagram)
握手示意图
以下描述握手图中提到的状态:
(1)未初始化[Uninitialized]:在此阶段发送协议版本。客户端和服务器都未初始化。客户端发送包C0中的协议版本。如果服务器支持该版本,则发送S0和S1作为响应。如果没有,服务器将采取适当的操作进行响应。在RTMP中,此操作是终止连接。
(2)已发送版本[Version Sent]:在未初始化状态之后,客户端和服务器都处于已发送版本状态。客户端正在等待分组S1,服务器正在等待分组C1。在接收到等待的分组时,客户端发送分组C2,服务器发送分组S2。然后状态变为Ack Sent。
(3)Ack发送[Ack Sent]:客户端和服务器分别等待S2和C2。
(4)握手完成[Handshake Done]:客户端和服务器交换消息。
【3】分块(Chunking)
1)握手之后,连接复用一个或多个块流。每个区块流携带来自一个消息流的一种类型的消息。创建的每个区块都有一个与之相关联的唯一ID,称为区块流ID。这些区块通过网络传输。传输时,必须在下一个数据块之前完整地发送每个数据块。在接收端,根据块流ID将块组装成消息。
2)分块允许将更高级别协议中的大消息分解成更小的消息,例如,以防止大的低优先级消息(例如视频)阻塞更小的高优先级消息(例如音频或控制)。
3)分块还允许以较少的开销发送小消息,因为分块头包含信息的压缩表示,否则必须包含在消息本身中。
4)块大小是可配置的。可以使用设置块大小控制消息来设置(第5.4.1节)。较大的块大小可以减少CPU使用量,但也会提交较大的写操作,这会延迟低带宽连接上的其他内容。较小的块不适合高比特率流。块大小在每个方向上都是独立的。
【A】块格式(Chunk Format)
每个区块由一个标头和数据组成。标头本身有三个部分:
1)基本头(1到3字节)[Basic Header (1 to 3 bytes)]:此字段对区块流ID和区块类型进行编码。块类型决定编码消息头的格式。长度完全取决于块流ID,它是一个可变长度字段。
2)消息头(0、3、7或11字节)[Message Header (0, 3, 7, or 11 bytes)]:此字段编码有关正在发送的消息的信息(无论是全部还是部分)。可以使用块头中指定的块类型来确定长度。
3)扩展时间戳(0或4字节)[Extended Timestamp (0 or 4 bytes)]:根据区块消息头中的编码时间戳或时间戳增量字段,此字段在某些情况下存在。详见第5.3.1.3节。
4)块数据(可变大小)[Chunk Data (variable size)]:此块的有效负载,最大为配置的最大块大小。
【A-1】区块基本标头(Chunk Basic Header)
1)Chunk Basic头 (The Chunk Basic Header) 对Chunk stream ID和Chunk type(由下图中的fmt字段表示)进行编码。块类型决定编码消息头的格式。Chunk Basic Header字段可以是1、2或3字节,具体取决于Chunk stream ID。
2)实现应该使用能够容纳ID的最小表示。
3)该协议最多支持65597个流,ID为3-65599。保留ID 0、1和2。值0表示2字节形式和64-319(第二个字节+64)范围内的ID。值1表示3字节形式和64-65599范围内的ID((第三个字节)*256+第二个字节+64)。3-63范围内的值表示完整的流ID。值为2的区块流ID保留用于低级协议控制消息和命令。
4)chunk basic头(The Chunk Basic Header)中的位0-5(最低有效)表示块流ID。
5)块流ID 2-63可以在该字段的1字节版本中编码。
6)区块流id64-319可以以头的2字节形式编码。ID计算为(第二个字节+64)。
7)块流ID 64-65599可以在此字段的3字节版本中编码。ID的计算公式为((第三个字节)*256+(第二个字节)+64)。
8)综上
1> cs id(6位)[cs id (6 bits)]:此字段包含区块流id,值为2-63。值0和1用于指示此字段的2字节或3字节版本。
2> fmt(2位)[fmt (2 bits)]:此字段标识“chunk message header”使用的四种格式之一。下一节将解释每个区块类型的“区块消息头”。
3> cs id-64(8或16位)[cs id - 64 (8 or 16 bits)]:此字段包含块流id减去64。例如,id 365将由cs id中的1表示,此处为16位301。
4> 值为64-319的区块流ID可以用头的2字节或3字节形式表示。
【A-2】区块消息头(Chunk Message Header)
区块消息头有四种不同的格式,由区块基本头中的“fmt”字段选择。
实现应该为每个区块消息头使用尽可能紧凑的表示。
【A-2-1】Type 0
类型0:类型0区块标头的长度为11字节。此类型必须在块流开始时使用,并且每当流时间戳向后移动时(例如,由于向后搜索)。
时间戳(3字节)[timestamp (3 bytes)]:对于类型0块,消息的绝对时间戳发送到这里。如果时间戳大于或等于16777215(十六进制0xFFFFFF),则此字段必须为16777215,表示存在(并使用)扩展的时间戳字段来编码完整的32位时间戳。否则,此字段(值)应为整个时间戳。
【A-2-2】Type 1
Type 1:类型1区块标头的长度为7字节。不包括消息流ID;此区块采用与前一区块相同的流ID。
具有可变大小消息的流(例如,许多视频格式)应在第一个消息之后的每个新消息的第一个块中使用此格式。
【A-2-3】Type 2
Type 2:类型2区块标头的长度为3字节。不包括流ID和消息长度;此区块与前一区块具有相同的流ID和消息长度。具有固定大小消息的流(例如,某些音频和数据格式)应在第一个消息块之后的每个消息块的第一个块中使用此格式。
【A-2-4】Type 3
Type 3:类型3块没有消息头。流ID、消息长度和时间戳增量字段不存在;此类型的块从前面的块中获取相同块流ID的值。当单个消息拆分为块时,除第一个消息外的所有消息块都应使用此类型。参考示例2(第5.3.2.2节)。由大小、流ID和时间间隔完全相同的消息组成的流应将此类型用于类型2块之后的所有块。请参阅示例1(第5.3.2.1节)。如果第一条消息和第二条消息之间的增量与第一条消息的时间戳相同,那么类型3的块可以紧跟类型0的块,因为不需要类型2的块来注册增量。如果类型3块跟随类型0块,则此类型3块的时间戳增量与类型0块的时间戳相同。
【A-2-5】Common Header Fields
公共头字段(Common Header Fields)
区块消息头中每个字段的说明:
1)timestamp delta(3字节):对于类型1或类型2块,前一块的时间戳和当前块的时间戳之间的差异发送到这里。如果增量大于或等于16777215(十六进制0xFFFFFF),则此字段必须为16777215,表示存在(并使用)扩展时间戳字段以编码完整的32位增量。否则,此字段(值)应为实际增量。
2)消息长度(3字节)[message length (3 bytes)]:对于类型0或类型1块,消息的长度在此处发送。请注意,这通常与块负载的长度不同。chunk payload length是除最后一个块以外的所有块的最大块大小,剩余的(对于小消息,可能是整个长度)是最后一个块的最大块大小。
3)消息类型id(1字节)[message type id (1 byte)]:对于类型0或类型1块,消息类型发送到这里。
4)消息流id(4字节)[message stream id (4 bytes)]:对于类型0块,存储消息流id。消息流ID以little endian格式存储。通常,同一块流中的所有消息都来自同一个消息流。虽然可以将不同的消息流多路复用到同一块流中,但这会破坏头压缩的好处。但是,如果一个消息流被关闭,而另一个消息流随后被打开,则没有理由不能通过发送新的类型0块来重用现有的块流。
【A-3】扩展时间戳(Extended Timestamp)
扩展时间戳[Extended Timestamp]:字段用于编码大于16777215(0xFFFFFF)的时间戳或时间戳增量;也就是说,对于不适合0、1或2块类型的24位字段的时间戳或时间戳增量。此字段对完整的32位时间戳或时间戳增量进行编码。通过将类型0块的时间戳字段或类型1或2块的时间戳增量字段设置为16777215(0xFFFFFF)来指示此字段的存在。当相同区块流ID的最新类型0、1或2区块指示存在扩展时间戳字段时,此字段出现在类型3区块中。
【4】协议控制消息(Protocol Control Messages)
RTMP区块流使用消息类型ID 1、2、3、5和6作为协议控制消息。这些消息包含RTMP块流协议所需的信息。
这些协议控制消息必须具有消息流ID 0(称为控制流),并以块流ID 2的形式发送。协议控制消息在收到后立即生效;它们的时间戳被忽略。
【A】设置块大小(1)(Set Chunk Size (1))
1)协议控制消息1,设置块大小,用于通知对等方一个新的最大块大小。
2)最大块大小默认为128字节,但客户端或服务器可以更改此值,并使用此消息更新其对等方。例如,假设一个客户机想要发送131字节的音频数据,而块大小是128。在这种情况下,客户机可以将此消息发送给服务器,通知它块大小现在是131字节。然后,客户机可以在单个块中发送音频数据。
3)最大块大小应至少为128字节,并且必须至少为1字节。每个方向的最大块大小是独立保持的。
“设置块大小”协议消息的有效负载
4)0:该位必须为零。
5)chunk size(31位):此字段保存新的最大块大小(以字节为单位),它将用于发送方的所有后续块,直到另行通知。有效大小为1到2147483647(0x7FFFFFFF),包括在内;但是,所有大于16777215(0xFFFFFF)的大小都是等效的,因为没有块大于一条消息,也没有消息大于16777215字节。
【B】中止消息(2)(Abort Message (2))
1)协议控制消息2,Abort message,用于通知对等方是否正在等待块来完成消息,然后通过块流丢弃部分接收的消息。对等方接收区块流ID作为该协议消息的有效负载。应用程序可以在关闭时发送此消息,以指示不需要对消息进行进一步处理。
“中止消息”协议消息的有效负载
2)区块流ID(32位)[chunk stream ID (32 bits)]:此字段保存区块流ID,其当前消息将被丢弃。
【C】确认(3)(Acknowledgement (3))
客户端或服务器必须在接收到等于窗口大小的字节后向对等方发送确认。窗口大小是发送方在不接收接收方确认的情况下发送的最大字节数。此消息指定序列号,即到目前为止接收到的字节数。
“确认”协议消息的有效负载
1)序列号(32位)[sequence number (32 bits)]:此字段保存到目前为止接收的字节数。
【D】窗口确认大小(5)(Window Acknowledgement Size (5))
客户端或服务器发送此消息以通知对等方在发送确认之间要使用的窗口大小。在发送方发送窗口大小字节后,发送方期望来自其对等方的确认。接收对等方必须在接收到自上次发送确认后指定的字节数后发送确认(第5.4.3节),如果尚未发送确认,则从会话开始发送确认。
“窗口确认大小”协议消息的有效负载
【E】设置对等带宽(6)
客户机或服务器发送此消息以限制其对等机的输出带宽。接收此消息的对等方通过将已发送但未确认的数据量限制在此消息中指示的窗口大小来限制其输出带宽。如果窗口大小与上次发送给此消息发送方的窗口大小不同,则接收此消息的对等方应使用窗口确认大小消息进行响应。
“设置对等带宽”协议消息的有效负载
1)限制类型( Limit Type)是以下值之一:
0-硬(0 - Hard):对等方应将其输出带宽限制为指定的窗口大小。
1-软(1 - Soft):对等方应将其输出带宽限制在此消息中指示的窗口或已生效的限制,以较小者为准。
2-动态(2 - Dynamic):如果以前的限制类型是硬的,则将此消息视为标记为硬的,否则忽略此消息。
二、RTMP消息格式(RTMP Message Formats)
1)本节指定使用较低级别传输层(如RTMP Chunk Stream)在网络上的实体之间传输的RTMP消息的格式。
2)虽然RTMP被设计为与RTMP块流一起工作,但它可以使用任何其他传输协议发送消息。RTMP Chunk Stream和RTMP一起适用于各种音频-视频应用,从一对一和一对多直播到视频点播服务,再到交互式会议应用。
【1】RTMP消息格式(RTMP Message Format)
1)服务器和客户机通过网络发送RTMP消息以相互通信。这些消息可以包括音频、视频、数据或任何其他消息。
2)RTMP消息有两个部分,一个报头和它的有效负载。
【A】消息头(Message Header)
消息头包含以下内容:
(1)消息类型[Message Type]:表示消息类型的一个字节字段。为协议控制消息保留一系列类型id(1-6)。
(2)长度[Length]:三字节字段,表示有效负载的大小(字节)。它以大端格式设置。
(3)Timestamp[Timestamp]:包含消息时间戳的四字节字段。
4个字节按大端顺序排列。
(4)消息流Id[Message Stream Id]:标识消息流的三字节字段。这些字节以big-endian格式设置。
【B】消息有效负载(Message Payload)
消息的另一部分是有效负载,它是消息中包含的实际数据。例如,它可以是一些音频样本或压缩视频数据。有效载荷的格式和解释超出了本文件(本RTMP协议文档)的范围。
【2】用户控制消息(4)(User Control Messages (4))
(1)RTMP对用户控制消息使用消息类型ID4【 message type ID 4】。这些消息包含RTMP流层使用的信息。
(2)RTMP区块流协议【RTMP Chunk Stream protocol】使用ID为1、2、3、5和6的协议消息(第5.4节)。
(3)用户控制消息应使用消息流ID 0(称为控制流),当通过RTMP区块流发送时,应在区块流ID 2上发送。用户控制消息在流中接收时有效;它们的时间戳被忽略。
(4)客户机或服务器发送此消息以通知对等机用户控制事件。此消息包含事件类型和事件数据。
“用户控制”协议消息的有效负载
(5)消息数据的前2个字节用于标识事件类型。事件类型后跟事件数据。事件数据字段的大小是可变的。但是,在消息必须通过RTMP块流层【 RTMP Chunk Stream layer】的情况下,最大块大小(第5.4.1节)应足够大,以允许这些消息适合单个块【a single chunk】。
(6)第7.1.7节列出了事件类型及其事件数据格式。
三、RTMP命令消息(RTMP Command Messages)
本节描述服务器和客户机之间交换的不同类型的消息和命令,以便彼此通信。
在服务器和客户机之间交换的不同类型的消息包括用于发送音频数据的音频消息、用于发送视频数据的视频消息、用于发送任何用户数据的数据消息、共享对象消息和命令消息。共享对象消息提供了一种通用的方法来管理多个客户端和服务器之间的分布式数据。命令消息在客户机和服务器之间携带AMF编码的命令。客户机或服务器可以通过流请求远程过程调用(RPC)【request Remote Procedure Calls (RPC) over streams】,这些流使用命令消息与对等机通信。
【1】消息的类型(Types of Messages)
服务器和客户机通过网络发送消息以相互通信。消息可以是包括音频消息、视频消息、命令消息、共享对象消息、数据消息和用户控制消息的任何类型。【includes audio messages, video messages, command messages, shared object messages, data messages, and user control messages.】
【A】命令消息(20,17)(Command Message (20, 17))
命令消息在客户机和服务器之间携带AMF编码【AMF-encoded commands】的命令。对于AMF0编码,这些消息的消息类型【message type value】值为20;对于AMF3编码,消息类型值【 message type value 】为17。发送这些消息是为了在对等机上执行一些操作,如connect、createStream、publish、play和pause。命令消息(如onstatus、result等)用于通知发送方所请求命令的状态(我的理解:通知接收方当前发送方所请求命令的状态)。命令消息由命令名、事务ID和包含相关参数的命令对象组成。客户机或服务器可以通过流请求远程过程调用(RPC),这些流使用命令消息与对等机通信。
【B】数据报文/数据消息(18、15)(Data Message (18, 15))
客户机或服务器发送此消息以将元数据或任何用户数据发送到对等机。元数据包括有关数据(音频、视频等)的详细信息,如创建时间、持续时间、主题等。这些消息已为AMF0分配消息类型【message type value】值18,为AMF3分配消息类型【message type value】值15。
【C】共享对象消息(19,16)(Shared Object Message (19, 16))
共享对象是跨多个客户端、实例等同步的Flash对象(名称-值对的集合)。AMF0的消息类型19和AMF3的消息类型16是为共享对象事件保留的。每条消息可以包含多个事件。
共享对象消息格式
支持以下事件类型:
Event | Description |
---|---|
Use(=1) | 客户端发送此事件以通知服务器已创建命名共享对象。 |
Release(=2) | 在客户端删除共享对象时,客户端将此事件发送到服务器。 |
Request Change(=3) | 客户端发送此事件以请求更改与共享对象的命名参数关联的值。 |
Change (=4) | 服务器发送此事件以通知所有客户端(发起请求的客户端除外)命名参数值的更改。 |
Success (=5) | 如果请求被接受,服务器将向请求客户端发送此事件,以响应RequestChange事件。 |
SendMessage(=6) | 客户端将此事件发送到服务器以广播消息。收到此事件后,服务器将向所有客户端(包括发送方)广播一条消息。 |
Status(=7) | 服务器发送此事件以通知客户端错误情况。 |
Clear (=8) | 服务器将此事件发送给客户端以清除共享对象。服务器还发送此事件以响应客户端在连接时发送的Use事件。 |
Remove(=9) | 服务器发送此事件以让客户端删除插槽。 |
Request Remove(=10) | 客户端发送此事件以让客户端删除插槽。 |
Use Success(=11) | 服务器在一个(or连接成功时,ps:到底谁连接谁,暂不清楚)成功连接时向客户端发送此事件。 |
【D】音频信息(8)(Audio Message (8))
客户端或服务器发送此消息以将音频数据发送到对等端。消息类型值8【 message type value】是为音频消息保留的。
【E】视频信息(9)(Video Message (9))
客户端或服务器发送此消息以将视频数据发送到对等端。消息类型值9【 message type value】是为视频消息保留的。
【F】 聚合消息(22)(Aggregate Message (22))
聚合消息是包含一系列RTMP子消息的单个消息,使用第6.1节中描述的格式。消息类型22【Message
type】用于聚合消息。
聚合消息格式
聚合消息体格式(or聚合邮件正文格式)
Back Pointer 0:返回指针0
聚合消息格式(如上图)
(1)聚合消息的消息流ID覆盖聚合内子消息的消息流ID。
(2)聚合消息和第一个子消息的时间戳之间的差异是用于将子消息的时间戳重新规范化为流时间尺度的偏移量。偏移量被添加到每个子消息的时间戳中,以到达标准化流时间。第一个子消息的时间戳应与聚合消息的时间戳相同,因此偏移量应为零。
(3)返回指针包含上一条消息的大小,包括其标题【header】。它被包括以匹配FLV文件的格式,并用于向后搜索。
(4)使用聚合消息有几个性能好处:
o1)区块流最多只能在区块内发送一条完整的消息。因此,增加块大小并使用聚合消息可以减少发送的块的数量。
o2)子消息可以连续存储在内存中。在进行系统调用以在网络上发送数据时效率更高。
【G】用户控制消息事件(User Control Message Events)
客户机或服务器发送此消息以通知对等机用户控制事件。有关消息格式的信息,请参阅第6.2节。
支持以下用户控件事件类型:
事件(Event) | 描述(Description) |
---|---|
Stream Begin(=0) | 服务器发送此事件以通知客户端某个流已起作用并可用于通信。默认情况下,在从客户端成功接收到应用程序连接命令(connect command)后,将在ID 0上发送此事件。事件数据是4字节的,它表示开始工作的流的流ID。 |
Stream EOF(=1) | 服务器发送此事件以通知客户机数据的回放已按此流上的请求结束。如果不发出额外的命令,就不会发送更多的数据。客户端丢弃为流接收的消息。4字节的事件数据表示播放结束的流的ID。 |
StreamDry(=2) | 服务器发送此事件以通知客户端流中没有更多数据。如果服务器在一段时间内没有检测到任何消息,它可以通知订阅的客户端流是干的。4字节的事件数据表示干流的流ID。 |
SetBuffer Length (=3) | 客户机发送此事件以通知服务器缓冲区大小(以毫秒为单位),该大小用于缓冲通过流的任何数据。此事件在服务器开始处理流之前发送。事件数据的前4个字节表示流ID,后4个字节表示缓冲区长度(以毫秒为单位)。 |
StreamIs Recorded (=4) | 服务器发送此事件以通知客户端该流是已记录的流。4字节的事件数据表示所记录流的流ID。 |
PingRequest (=6) | 服务器发送此事件以测试客户端是否可访问。事件数据是一个4字节的时间戳,表示服务器发出命令时的本地服务器时间。客户端在接收到MsgPingRequest时使用PingResponse进行响应。 |
PingResponse (=7) | 客户端将此事件发送到服务器以响应ping请求。事件数据是一个4字节的时间戳,与ping请求一起接收。 |
【2】命令类型(Types of Commands)
1)客户机和服务器交换AMF编码的命令。
2)发送方发送一条命令消息,该消息由命令名、事务ID和包含相关参数的命令对象组成。
3)例如,connect命令包含’app’参数,它告诉客户端连接到的服务器应用程序名称。接收器处理该命令并用相同的事务ID发回响应。响应字符串可以是 _result、 _error或方法名称,例如verifyClient或contactExternalServer。
4)包含结果或错误( _result or _error)的命令字符串表示响应。事务ID指示响应所引用的未完成命令。它与IMAP和许多其他协议中的标记相同。命令字符串中的方法名称表示发送方正试图在接收方运行方法。
5)以下类对象用于发送各种命令:
6)NetConnection是服务器和客户机之间连接的高级表示形式的对象。
7)NetStream表示音频流、视频流和其他相关数据通过的通道的对象。我们还发送诸如play、pause等控制数据流的命令。
【A】NetConnection命令(NetConnection Commands)
NetConnection管理客户端应用程序和服务器之间的双向连接。此外,它还支持异步远程方法调用。
可以在NetConnection上发送以下命令:
1)o连接( connect)
2)o呼叫( call)
3)o关闭( close)
4)o创建流( createStream)
【A-1】连接(connect)
客户机向服务器发送connect命令,请求连接到服务器应用程序实例。
从客户端到服务器的命令结构如下:
Field Name(字段名称) | Type(类型) | Description(说明) |
---|---|---|
Command Name(命令名) | String | 命令的名称。设置为“连接”。(Set to “connect”.) |
Transaction ID(事务ID) | Number | 始终设置为1。(Always set to 1.) |
Command Object(命令对象) | Object | 具有名称-值对的命令信息对象。 |
Optional User Arguments(可选用户参数) | Object | 任何可选信息 |
下面是connect命令的Command对象中使用的名称-值对的描述。
Property(字段名称) | Type(类型) | Description(说明) | Example Value(示例值) |
---|---|---|---|
app(命令名) | String | 客户端连接到的服务器应用程序名称。 | testapp |
flashver(flash版本) | String | Flash播放器版本。它与ApplicationScript getversion()函数返回的字符串相同。 | FMSc/1.0 |
swfUrl(命令对象) | String | 建立连接的源SWF文件的URL。 | file://C:/FlvPlayer.swf |
tcUrl(可选用户参数) | String | 服务器的URL。它有以下格式(protocol://servername:port/appName/appInstance ) | rtmp://localhost:1935/testapp/instance1 |
fpad(字段名称) | Boolean | 如果正在使用代理,则为True | true or false |
audioCodecs(音频编解码器) | Number | 指示客户端支持的音频编解码器。 | SUPPORT_SND_MP3 |
videoCodecs(视频编解码器) | Number | 指示支持哪些视频编解码器。 | SUPPORT_VID_SORENSON |
videoFunction(视频功能) | Number | 指示支持哪些特殊视频功能。 | SUPPORT_VID_CLIENT_SEEK |
pageUrl (页面URL) | String | 从中加载SWF文件的网页的URL。 | http://somehost/sample.html |
object Encoding(对象编码) | Number | AMF编码方法。 | AMF3 |
audioCodecs属性的标志值:
Codec Flag(编解码器标志) | Usage(用法) | Value(值) |
---|---|---|
SUPPORT_SND_NONE | 原始声音,无压缩 | 0x0001 |
SUPPORT_SND_ADPCM | ADPCM压缩 | 0x0002 |
SUPPORT_SND_MP3 | mp3压缩 | 0x0004 |
SUPPORT_SND_INTEL | 未使用 | 0x0008 |
SUPPORT_SND_UNUSED | 未使用 | 0x0010 |
SUPPORT_SND_NELLY8 | 8-kHz压缩时的NellyMoser(内利莫尔) | 0x0020 |
SUPPORT_SND_NELLY | NellyMoser压缩(5、11、22和44 kHz) | 0x0040 |
SUPPORT_SND_G711A | G711A声音压缩(仅限闪存媒体服务器) | 0x0080 |
SUPPORT_SND_G711U | G711U声音压缩(仅限闪存媒体服务器) | 0x0100 |
SUPPORT_SND_NELLY16 | 16 kHz压缩时的NellyMouser | 0x0200 |
SUPPORT_SND_AAC | 高级音频编码(AAC)编解码器 | 0x0400 |
SUPPORT_SND_SPEEX | Speex音频 | 0x0800 |
SUPPORT_SND_ALL | 所有支持RTMP的音频编解码器 | 0x0FFF |
videoCodecs属性的标志值:
Codec Flag(编解码器标志) | Usage(用法) | Value(值) |
---|---|---|
SUPPORT_VID_UNUSED | 废弃值(过时的价值) | 0x0001 |
SUPPORT_VID_JPEG | 废弃值(过时的价值) | 0x0002 |
SUPPORT_VID_SORENSON | (Sorenson)索伦森Flash视频 | 0x0004 |
SUPPORT_VID_HOMEBREW | V1屏幕共享 | 0x0008 |
SUPPORT_VID_VP6 (On2) | On2视频(Flash 8+) | 0x0010 |
SUPPORT_VID_VP6ALPHA(On2 with alpha channel) | 带alpha频道的On2视频 | 0x0020 |
SUPPORT_VID_HOMEBREWV(screensharing v2) | 屏幕共享版本2(Flash 8+) | 0x0040 |
SUPPORT_VID_H264 | H264视频 | 0x0080 |
SUPPORT_VID_ALL | 所有支持RTMP的视频编解码器 | 0x00FF |
videoFunction属性的标志值:
Function Flag(功能标志) | Usage(用法) | Value(值) |
---|---|---|
SUPPORT_VID_CLIENT_SEEK | 指示客户端可以执行帧精确查找。 | 1 |
对象编码属性的值:
Encoding Type(编码类型) | Usage(用法) | Value(值) |
---|---|---|
AMF0 | Flash 6及更高版本支持AMF0对象编码 | 0 |
AMF3 | 闪存9(AS3)的AMF3编码(from Flash 9 (AS3)) | 3 |
从服务器到客户端的命令结构如下:
Field Name(字段名称) | Type(类型) | Description(说明) |
---|---|---|
Command Name(命令名) | String | _result or _error; 指示响应是结果还是错误。 |
Transaction ID(事务ID) | Number | 连接响应的事务ID为1 |
Properties(属性) | Object | 描述连接属性(fmsver等)的名称-值对。 |
Information(信息) | Object | 描述服务器响应的名称-值对。“code”、“level”、“description”是这些信息中很少的名称。 |
connect命令中的消息流
命令执行期间的消息流为:
1.客户端向服务器发送connect命令,请求与服务器应用实例连接。
2.服务器收到connect命令后,向客户端发送协议消息“窗口确认大小”(’Window Acknowledgement Size’)。服务器还连接到connect命令中提到的应用程序。
3.服务器向客户端发送协议消息“设置对等带宽”(’Set Peer Bandwidth’)。
4.客户端在处理协议消息“设置对等带宽”后,向服务器发送协议消息“窗口确认大小”。
5.服务器向客户端发送另一个类型为用户控制消息(StreamBegin)的协议消息。
6.服务器发送结果命令消息,通知客户端连接状态(成功/失败)。该命令指定事务ID(对于connect命令总是等于1)。
该消息还指定属性,例如Flash Media Server version(string)。此外,它还指定了其他与连接响应相关的信息,如级别(string)、代码(string)、描述(string)、对象编码(number)等。
【A-2】呼叫(Call)
NetConnection对象的call方法在接收端运行远程过程调用(RPC)。被调用的RPC名称作为参数传递给call命令。
从发送方到接收方的命令结构如下:
Field Name(字段名称) | Type(类型) | Description(说明) |
---|---|---|
Procedure Name(程序名称) | String | 调用的远程过程的名称。 |
Transaction ID(事务ID) | Number | 如果需要响应,我们就给出一个事务Id。否则我们就传递一个值0 |
Command Object(命令对象) | Object | 如果存在任何命令信息,则将其设置为空类型。 |
Optional Arguments(可选参数) | Object | 提供任何可选参数 |
响应的命令结构如下:
Field Name(字段名称) | Type(类型) | Description(说明) |
---|---|---|
Command Name(命令名) | String | 命令的名称。 |
Transaction ID(事务ID) | Number | 响应所属的命令的ID。 |
Command Object(命令对象) | Object | 如果存在任何命令信息,则将其设置为空类型。 |
Response(响应/回应) | Object | 调用的方法的响应。 |
【A-3】创建流(createStream)
客户机将此命令发送给服务器,以创建用于消息通信的逻辑通道。音频、视频和元数据的发布通过使用createStream命令创建的流通道执行。
NetConnection是默认的通信通道,其流ID为0。协议和一些命令消息(包括createStream)使用默认的通信通道。
从客户端到服务器的命令结构如下:
Field Name(字段名称) | Type(类型) | Description(说明) |
---|---|---|
Command Name(命令名) | String | 命令的名称。设置为“createStream”。 |
Transaction ID(事务ID) | Number | 命令的事务ID。 |
Command Object(命令对象) | Object | 如果存在任何命令信息,则将其设置为空类型。 |
从服务器到客户端的命令结构如下:
Field Name(字段名称) | Type(类型) | Description(说明) |
---|---|---|
Command Name(命令名) | String | _result or _error; 指示响应是结果还是错误。 |
Transaction ID(事务ID) | Number | 响应所属的命令的ID。 |
Command Object(命令对象) | Object | 如果存在任何命令信息,则将其设置为空类型。 |
Stream ID(流ID) | Number | 返回值是流ID或错误信息对象。 |
【B】NetStream 命令(NetStream Commands)
NetStream定义了一个通道,通过这个通道,流式音频、视频和数据消息可以在连接客户机和服务器的NetConnection上流动。NetConnection对象可以为多个数据流支持多个NetStream。
客户端可以在NetStream上向服务器发送以下命令:
1)o播放(play)
2)o播放2(play2)
3)o删除流(deleteStream)
4)o关闭流(closeStream)
5)o接收音频(receiveAudio)
6)o接收视频(receiveVideo)
7)o发布(publish)
8)o寻找(seek)
9)o暂停(pause)
服务器使用“onStatus”命令向客户端发送NetStream状态更新:
Field Name(字段名称) | Type(类型) | Description(说明) |
---|---|---|
Command Name(命令名) | String | 命令名“onStatus”。 |
Transaction ID(事务ID) | Number | 事务ID设置为0。 |
Command Object(命令对象) | Null | onStatus消息没有命令对象。 |
Info Object(信息对象) | Object | 至少具有以下三个属性的AMF对象:(1)“级别(level)”(字符串[String]):此消息的级别,“警告(warning)”、“状态(status)”或“错误(error)”之一;(2)“代码(code)”(字符串[String]):消息代码,例如“NetStream.Play.Start”;和(3)“描述/说明(description)”(字符串[String]):一种人类可读的消息描述。Info对象可以包含其他适合于代码的属性。 |
NetStream状态消息命令(status message commands)的格式。
【B-1】播放(play)
1)客户端将此命令发送到服务器以播放流。也可以使用此命令多次创建播放列表。
2)如果您想创建一个动态播放列表,在不同的实时或录制流之间切换,请多次调用play,每次都传递false进行重置。相反,如果要立即播放指定的流,清除排队等待播放的任何其他流,请传递true进行重置。
从客户端到服务器的命令结构如下:
Field Name(字段名称) | Type(类型) | Description(说明) |
---|---|---|
Command Name(命令名) | String | 命令的名称。设置为“播放”。(Set to “play”) |
Transaction ID(事务ID) | Number | 事务ID设置为0。 |
Command Object(命令对象) | Null | 命令信息不存在。设置为空类型。(Set to null type) |
Stream Name (流名称) | String | 要播放的流的名称。要播放视频(FLV)文件,请指定不带文件扩展名的流的名称(例如,“sample”)。要播放MP3或ID3标记,必须在流名称前面加上MP3:(例如,“MP3:sample”)。要播放H.264/AAC文件,必须在流名称前面加上mp4:,并指定文件扩展名。例如,要播放sample.m4v文件,请指定“mp4:sample.m4v” |
Start(开始/启动) | Number | 一个可选参数,指定以秒为单位的开始时间。默认值为-2,这意味着订户(订阅者)首先尝试播放流名称字段中指定的实时流(the live stream)。如果找不到该名称的实时流,它将播放相同名称的录制流(the recorded stream)。如果没有使用该名称录制的流,订户将等待使用该名称的新实时流,并在可用时播放该流。如果在“开始”字段(Start field)中传递-1,则仅播放流名称(the Stream Name)字段中指定的实时流。如果在“开始”字段中传递0或正数,则从“开始”字段中指定的时间开始播放在“流名称”字段中指定的录制流。如果找不到录制的流,则播放列表中的下一项。 |
Duration(持续时间) | Number | 一个可选参数,指定以秒为单位的播放持续时间。默认值为-1,-1表示播放直播流(the live stream)直到不再可用,或者播放录制的流(the recorded stream)直到结束。如果传递0,则从记录流(录制的流)的开头开始播放自“开始”字段(the Start field)中指定的时间以来的单个帧。假设在“开始”字段中指定的值等于或大于0。如果传递正数,它将在“持续时间”字段中指定的时间段内播放实时流(a live stream)。之后,它变为可用或在持续时间字段中指定的时间内播放录制的流(如果流在“持续时间”字段中指定的时间之前结束,则播放将在流结束时结束。)如果在“持续时间”字段中传递的不是-1的其他负数,则会将该值解释为-1。 |
Reset (复位/重置) | Boolean | 一个可选的布尔值或数字,指定是否刷新以前的任何播放列表。 |
继续接收音频和视频流,直到完成
play命令中的消息流
命令执行期间的消息流为:
1.客户端在从服务器接收到createStream命令的结果success后发送play命令。
2.在接收到播放(play)命令时,服务器发送协议消息(protocol message)来设置块大小。
3.服务器发送另一个协议消息(protocol message)(用户控制),指定该消息中的事件“StreamIsRecorded”和流ID。消息在前2个字节中携带事件类型,在后4个字节中携带流ID。
4.服务器发送另一个协议消息(用户控制),指定事件“StreamBegin”,以向客户端指示流的开始。
5.如果客户端发送的播放命令是成功的,服务器将发送onStatus命令消息NetStream.Play.Start&NetStream.Play.Reset。只有当客户端发送的播放命令设置了重置标志(reset flag)时,服务器才会发送NetStream.Play.Reset。如果找不到要播放的流,服务器将发送onStatus消息NetStream.Play.StreamNotFound。
之后,服务器发送音频和视频数据,客户端播放这些数据。
【B-2】播放2(play2)
与play命令不同,play2可以切换到不同的比特率流,而无需更改播放内容的时间线。服务器为客户端可以在play2中请求的所有支持的比特率维护多个文件。
从客户端到服务器的命令结构如下:
Field Name(字段名称) | Type(类型) | Description(说明) |
---|---|---|
Command Name(命令名) | String | 命令的名称。设置为“播放2”。(Set to “play2”) |
Transaction ID(事务ID) | Number | 事务ID设置为0。 |
Command Object(命令对象) | Null | 命令信息不存在。设置为空类型。(Set to null type) |
Parameters(参数) | Object | AMF编码的对象,其属性是flash.net.NetStreamPlayOptions ActionScript对象的公共属性。 |
NetStreamPlayOptions对象的公共属性在actionscript3语言参考[AS3]中有描述。
命令的消息流如下图所示。
继续接收音频和视频流,直到完成
play2命令中的消息流
【B-3】删除流(deleteStream)
当NetStream对象(the NetStream object)被销毁时,NetStream发送deleteStream命令。
从客户端到服务器的命令结构如下:
Field Name(字段名称) | Type(类型) | Description(说明) |
---|---|---|
Command Name(命令名) | String | 命令的名称。设置为“删除流”。(Set to “deleteStream”) |
Transaction ID(事务ID) | Number | 事务ID设置为0。 |
Command Object(命令对象) | Null | 命令信息不存在。设置为空类型。(Set to null type) |
Stream ID(流ID) | Number | 在服务器上销毁的流的ID。 |
服务器不发送任何响应。
【B-4】接收音频(receiveAudio)
NetStream发送receiveAudio消息,通知服务器是否向客户端发送音频。
从客户端到服务器的命令结构如下:
Field Name(字段名称) | Type(类型) | Description(说明) |
---|---|---|
Command Name(命令名) | String | 命令的名称。设置为“接收音频”。(Set to “receiveAudio”) |
Transaction ID(事务ID) | Number | 事务ID设置为0。 |
Command Object(命令对象) | Null | 命令信息不存在。设置为空类型。(Set to null type) |
Bool Flag(Bool 标志) | Boolean | true或false表示是否接收音频。 |
如果发送receiveAudio命令时bool标志设置为false,则服务器不会发送任何响应。如果此标志设置为true,服务器将以状态消息(status messages)NetStream.Seek.Notify和NetStream.Play.Start响应
【B-5】接收视频(receiveVideo)
NetStream发送receiveVideo消息,通知服务器是否将视频发送到客户端。
从客户端到服务器的命令结构如下:
Field Name(字段名称) | Type(类型) | Description(说明) |
---|---|---|
Command Name(命令名) | String | 命令的名称。设置为“接收视频”。(Set to “receiveVideo”) |
Transaction ID(事务ID) | Number | 事务ID设置为0。 |
Command Object(命令对象) | Null | 命令信息不存在。设置为空类型。(Set to null type) |
Bool Flag(Bool 标志) | Boolean | true或false表示是否接收视频。 |
如果发送receiveVideo命令时bool标志设置为false,则服务器不会发送任何响应。如果此标志设置为true,服务器将以状态消息(status messages)NetStream.Seek.Notify和NetStream.Play.Start响应
【B-6】发布(publish)
客户机发送publish命令以将命名流(a named stream)发布到服务器。使用此名称,任何客户端都可以播放此流并接收已发布的音频、视频和数据消息。
从客户端到服务器的命令结构如下:
Field Name(字段名称) | Type(类型) | Description(说明) |
---|---|---|
Command Name(命令名) | String | 命令的名称。设置为“发布视频”。(Set to “publish”) |
Transaction ID(事务ID) | Number | 事务ID设置为0。 |
Command Object(命令对象) | Null | 命令信息不存在。设置为空类型。(Set to null type) |
Publishing Name(发布名称) | String | 用于发布流的名称 |
Publishing Type(发布类型) | String | 发布类型。设置为“live”、“record”或“append”。记录(record):流被发布,数据被记录到一个新文件中。该文件存储在服务器上包含服务器应用程序的目录中的一个子目录中。如果文件已存在,则会覆盖该文件。追加(append):发布流并将数据追加到文件中。如果找不到文件,则创建该文件。实时(live):发布实时数据(live data)时不将其记录在文件中。 |
服务器用onStatus命令响应以标记发布(publish)的开始。
【B-7】搜索/查找(seek)
客户端发送seek命令来查找媒体文件或播放列表(a media file or playlist)中的偏移量(the offset)(以毫秒为单位)。
从客户端到服务器的命令结构如下:
Field Name(字段名称) | Type(类型) | Description(说明) |
---|---|---|
Command Name(命令名) | String | 命令的名称。设置为“查找”。(Set to “seek”) |
Transaction ID(事务ID) | Number | 事务ID设置为0。 |
Command Object(命令对象) | Null | 命令信息不存在。设置为空类型。(Set to null type) |
milliSeconds(毫秒) | Number | 搜索播放列表的毫秒数。 |
服务器发送一条(status message)状态消息NetStream.Seek.Notify when Seek is successful。如果失败,它将返回一条错误消息( an _error message)。
【B-8】暂停(pause)
客户端发送pause命令来告诉服务器暂停或开始播放( pause or
start playing)。
从客户端到服务器的命令结构如下:
Field Name(字段名称) | Type(类型) | Description(说明) |
---|---|---|
Command Name(命令名) | String | 命令的名称。设置为“暂停”。(Set to “pause”) |
Transaction ID(事务ID) | Number | 此命令没有事务ID。设置为0。 |
Command Object(命令对象) | Null | 命令信息对象不存在。设置为空类型。(Set to null type) |
Pause/Unpause Flag(暂停/取消暂停标志) | Boolean | 对或错,表示暂停(pausing)或继续播放(resuming play) |
milliSeconds(毫秒) | Number | 暂停流(is paused)或继续播放(is play resumed)的毫秒数。这是暂停流(stream was paused)时客户端的当前流时间(current stream time)。恢复播放时(the playback is resumed),服务器将只发送时间戳(timestamps)大于此值的消息。 |
当流暂停时,服务器发送状态消息(status message)NetStream.Pause.Notify。NetStream.Unpause.Notify在流处于取消暂停状态时发送。如果失败,它将返回一条错误消息(an _error message)。
【3】消息交换示例(Message Exchange Examples)
消息交换示例
这里有几个例子来解释使用RTMP的消息交换。
(1)发布录制的视频
(2)广播共享对象消息
(3)从录制的流发布元数据