RTMP协议(五)命令消息

上篇我们对消息的格式和大部分的消息类型进行了梳理,本编主要对命令消息其中的定义进行梳理。

命令消息(Command Message) 用于在客户端和服务器端传输AMF编码的数据交换命令,客户端或者服务端可以通过命令消息和对端通信的流完成请求远程方法调用(RPC)。当消息使用 AMF0编码时,消息类型为20,使用AMF3编码时为17

命令消息使用场景基本都是——客户端请求,服务端响应

按来源分类

命令消息在客户端和服务端中来回传递,为了方便区分,我根据请求和响应根据场景将两端为区分请求者和响应者者。因此,请求者发出的就是请求命令信息,响应者发出的就是响应命令信息。

请求命令信息

请求者通过发送请求命令消息到对端,命令对端根据命令名执行远程方法调用。例如发送connect(连接)、createStream(创建流)、pulish(发布)、play(播放)和pause(暂停)等命令。由于其消息数据进行了 AMF 编码,因此下面表格通过字段展示的是请求命令的结构:

字段名(Field Name 类型(Type 描述(Description
Command Name String 命令名称,设置为指定的命令,取值为 connectcreateStreampulishplaypause等等
Transaction ID Number 事务ID,该命令需要响应则有指定ID,若不需要响应填 0 即可
Command Object Object / Null 命令对象,如果一些命令消息需要就用,否则置空即可
Others Unknow 额外的参数值或对象,根据特定的命令来配置。若不需要,则省略整个字段即可。

响应命令信息

响应者接收到请求命令消息后,会对其消息进行解析,并做相应的处理。根据不同命令的要求,响应者可能需要对请求者的请求进行响应。因此响应者将发送相应命令信息来完成响应操作。响应消息和请求消息类型,都是使用 AMF 编码,因此通过字段来表示其命令的结构:

字段名(Field Name 类型(Type 描述(Description
Command Name String 命令名称,取值为_result_erroronStatus
Transaction ID Number 事务ID,响应的目标请求的事务 ID
Command Object Object / Null 命令对象,如果一些命令消息需要就用,否则置空即可
Others Unknow 额外的参数值或对象,根据特定的命令来配置。如果这个是结果命令,则该字段是指定的结果;如果这个是错误命令,则该字段就是错误信息。

由此可见,响应命令其实就是一个结果命令错误命令状态命令

小结:命令消息通过Command Name进行区分,响应命令通过Transaction ID与请求命令进行关联。

发送命令消息的类对象

NetConnectionNetStream是命令中常用的类对象,其含义如下:

  • NetConnection:网络连接,服务端和客户端之间进行网络连接的一种高级表示形式。
  • NetStream:网络流,代表了发送音频流,视频流,或其他相关数据的频道。当然还有一些像播放,暂停之类的命令,用来控制数据流。

NetConnection 命令

NetConnection(网络连接)管理着客户端和服务端之间的双向连接,另外,它也支持远程方法的异步调用。NetConnection允许使用的命令如下:

  • connect(连接)
  • call(调用)
  • createStrem(创建流)
  • close(关闭)

对于NetConnection Command ,其响应请求命令为结果命令(_result)和错误命令(_error)。

connect 命令

客户端发送connect命令给服务器,来获取一个服务端应用实例的连接(connection)。

请求命令结构

字段名(Field Name 类型(Type 描述(Description
Command Name String 命令名称,设置为connect
Transaction ID Number 总是设置为 1
Command Object Object 具有键值对(name-value pairs)的命令信息对象,其结构见表格下方的ConnectInfo
Optional User Arguments Object 任意可选信息
ConnectInfo

connect命令的命令对象(Command Object)中的键值对说明:

属性(Property 类型(Type 描述(Description 范例(Example Value
app String 客户端连接到服务端应用的名字 live
flashver String Flash Player 版本号,和 ApplicationScript getversion ()方法返回的是用一个字符串 FMSc/1.0
swfUrl String 进行当前连接的 SWF 文件源地址 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 String SWF 文件所加载的网页 URL http://somehost/sample.html
objectEncoding Number AMF 编码方法 AMF3
audioCodecs

audioCodecs(音频编码属性)的可选值:原始 PCM,ADPCM,MP3,NellyMoser(5,8,11,16,22,44kHz),AAC,Speex

Codec Flag Usage Value
SUPPORT_SND_NONE Raw sound, no compression 0x0001
SUPPORT_SND_ADPCM ADPCM compression 0x0002
SUPPORT_SND_MP3 mp3 compression 0x0004
SUPPORT_SND_INTEL Not used 0x0008
SUPPORT_SND_UNUSED Not used 0x0010
SUPPORT_SND_NELLY8 NellyMoser at 8-kHz compression 0x0020
SUPPORT_SND_NELLY NellyMoser compression(5, 11, 22, and 44 kHz) 0x0040
SUPPORT_SND_G711A G711A sound compression(Flash Media Server only) 0x0080
SUPPORT_SND_G711U G711U sound compression(Flash Media Server only) 0x0100
SUPPORT_SND_NELLY16 NellyMouser at 16-kHz compression 0x0200
SUPPORT_SND_AAC Advanced audio coding (AAC) codec 0x0400
SUPPORT_SND_SPEEX Speex Audio 0x0800
SUPPORT_SND_ALL All RTMP-supported audio codecs 0x0FFF
videoCodecs

videoCodecs(视频编码属性)的可选值:Sorenson,V1,On2,V2,H264

Codec Flag Usage Value
SUPPORT_VID_UNUSED Obsolete value 0x0001
SUPPORT_VID_JPEG Obsolete value 0x0002
SUPPORT_VID_SORENSON Sorenson Flash video 0x0004
SUPPORT_VID_HOMEBREW V1 screen sharing 0x0008
SUPPORT_VID_VP6 (On2) On2 video (Flash 8+) 0x0010
SUPPORT_VID_VP6ALPHA(On2 with alpha channel) On2 video with alpha channel 0x0020
SUPPORT_VID_HOMEBREWV(screensharing v2) Screen sharing version 2 (Flash 8+) 0x0040
SUPPORT_VID_H264 H264 video 0x0080
SUPPORT_VID_ALL All RTMP-supported video codecs 0x00FF
videoFunction

videoFunction(视频函数属性)的可选值

Function Flag Usage Value
SUPPORT_VID_CLIENT_SEEK Indicates that the client can perform frame-accurate seeks. 1
objectEncoding

objectEncoding(编码属性)的可选值

Encoding Type Usage Value
AMF0 AMF0 object encoding supported by Flash 6 and later 0
AMF3 AMF3 encoding from Flash 9 (AS3) 3

响应命令结构

即服务器到客户端的命令结构:

字段名(Field Name 类型(Type 描述(Description
Command Name String 表示响应的是结果(result)还是错误(error),取值为_result_error
Transaction ID Number 对于connect响应,取值为 1
Properties Object 描述连接属性的键值对,其结构见表格下方的ConnectResp
Information Object 描述来自服务端的响应的键值对,即连接事件。包code,level,description,ObjectEncoding信息
ConnectResp
字段名(Field Name 类型(Type 描述(Description
fmsVer String Flash Media Server 版本号
capabilities Number 功能数量?

(※)命令执行消息流

connect命令执行过程中的消息流如下

    +--------------+                              +-------------+
    |    Client    |             |                |    Server   |
    +------+-------+             |                +------+------+
           |              Handshaking done               |
           |                     |                       |
           |                     |                       |
           |                     |                       |
           |                     |                       |
           |-----------1.Command Message(connect)------->|
           |                                             |
           |<-------2.Window Acknowledgement Size--------|
           |                                             |
           |<-----------3.Set Peer Bandwidth-------------|
           |                                             |
           |-------- Window Acknowledgement Size ------->|
           |                                             |
           |<------ User Control Message(StreamBegin) ---|
           |                                             |
           |<------------ Command Message ---------------|
           |       (_result- connect response)           |
           |                                             |
                 Message flow in the connect command
  1. 客户端发送connect命令到服务端以请求对服务端应用实例的连接
  2. 收到connect命令后,服务端发送协议消息“窗口确认大小”到客户端。同时,服务端也会连接到connect命令中提到的应用
  3. 服务端发送协议消息“设置对端宽带”到客户端
  4. 客户端在处理完协议消息“设置对端宽带”之后,发送协议消息“窗口确认大小”到服务端。
  5. 服务端发送用户控制消息(StreamBegin)类型的协议消息到客户端
  6. 服器端发送结果命令消息告知客户端连接状态 (success/fail),并携带指定信息。

call 方法

NetConnection对象的call方法执行接收端远程方法的调用(RPC),被调用的 RPC 名字作为一个参数传给调用命令。

请求命令结构

发送端发给接收端的命令结构如下:

字段名(Field Name 类型(Type 描述(Description
Procedure Name String 被调用远程程序的名字
Transaction ID Number 如果需要远程程序给予回复我们需要传递一个transaction Id,否则传0即可
Command Object Object 如果一些命令消息需要就用,否则置空即可
Optional Arguments Object 任意要提供的可选参数

响应命令结构

接收端回复的命令结构如下:

字段名(Field Name 类型(Type 描述(Description
Command Name String 命令的名字
Transaction ID Number 响应所属的命令的ID
Command Object Object 如果一些命令消息需要就用,否则置空即可
Response Object 调用方法的回复

createStream 命令

客户端发送这一命令到服务端为消息连接创建一条逻辑通道——消息流。音频、视频和元数据使用createStream命令创建的流通道传输。

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

请求命令结构

客户端发送给服务器端的命令结构如下:

字段名(Field Name 类型(Type 描述(Description
Command Name String 命令名,这里取值为createStream
Transaction ID Number 命令的事务 ID
Command Object Object 如果一些命令消息需要就用,否则置空即可

响应命令结构

服务端回复客户端的命令结构如下:

字段名(Field Name 类型(Type 描述(Description
Command Name String 表示响应的是结果(result)还是错误(error),取值为_result_error
Transaction ID Number 响应所属的命令的 ID
Command Object Object 如果一些命令消息需要就用,否则置空即可
Stream ID Number 返回值要么是一个流 ID,要么是一个错误信息对象

该处的流ID(Stream ID)表示的是NetConnection的流ID,与块流和消息流没有直接关系

NetStream 命令

NetStream(网络流)命令定义了传输通道,通过这个通道,音频流、视频流以及数据消息流可以通过连接客户端到服务端的NetConnection传输。以下命令可以由客户端使用 NetStream 往服务端发送

  • play(播放)
  • play2(播放2)
  • deleteStream(删除流)
  • closeStream(关闭流)
  • receiveAudio(接收音频)
  • receiveVideo(接收视频)
  • publish(发布)
  • seek(定位)
  • pause(暂停)

对于NetStream Command ,其响应请求命令为状态命令(onStatus

状态命令(响应)

对于NetStream命令,服务端使用onStatus命令向客户端发送NetStream状态:

字段名(Field Name 类型(Type 描述(Description
Command Name String 命令名,取值为onStatus
Transaction ID Number 事务ID,取值为 0
Command Object Null onStatus消息没有命令对象
Info Object Object 一个 AMF 对象至少要有“level”、“code”和“description”三个属性

AMF 对象属性字段要求

  • level(String):消息等级,取值为“warning”、“status”、“error”;
  • code(String):消息码,例如"NetStream.Play.Start";
    • 构成:类名.方法名.状态
  • description(String):关于这个消息的可读描述。

play 命令

客户端发送这一命令到服务端用来播放流,也可以多次使用这一命令创建一个播放列表。

如果你想要创建一个可以在不同的直播流或者录制流之间进行切换播放的动态的播放列表,那么你就需要多次调用play方法,并在每次调用时传递重置字段为false。相反的,如果你想要立即播放指定流,则需要将其他等待播放的流清空,并用true进行重置。

请求命令结构

客户端发送到服务端的命令结构如下:

字段名(Field Name 类型(Type 描述(Description
Command Name String 命令名,取值为“play”
Transaction ID Number 事务 ID,取值为 0
Command Object Null 该命令不存在命令信息,取值为“null”
Stream Name String 播放流的名字,其命名规则见表格下方
Start Number 表示开始的时间,以秒为单位,是一个可选参数。默认值为 -2,其值含义见表格下方
Duration Number 表示回放的持续时间,以秒为单位,是一个可选参数,默认值为 -1,其值含义见表格下方
Reset Boolean 表示重置操作,即是否对之前的播放列表进行flush操作,是一个可选参数。

Stream Name 规范

根据不同的文件播放需求,会有不同的 Stream 命名规范,如下:

  • 对于 FLV 文件(sample.flv):不需要文件扩展名,例如:sample
  • 对于 MP3 或 ID3 文件(sample.mp3):需要在名字前添加mp3:,例如:mp3:sample
  • 对于 H.264/ACC 文件(sample.m4v):需要在名字前添加mp4:,并且在名字后面指定文件扩展名,例如:mp4:sample.m4v

Start 含义

Start 表示流名(Stream Name)的播放方式,主要用于区分播放的是直播流还是录制流。

  • start = -2:表示用户首次尝试播放流名字段中定义的直播流
    • 如果没有此名的直播流,则会播放流名相同的录制流;
    • 如果没有此名的录制流,则会等待此名新的直播流。
  • start = 0:表示播放此流名指定的录制流
    • 如果没有此名的录制流,则会播放播放列表的下一项
  • start = -1:表示播放此流名指定的直播流

Duration 含义

默认值为 -1,表示直播流会播放至不可用,录制流会播放到结束;如果Duration值为 0,那么只会播放从录制流开始时间的一帧;如果Duration值为大于 0 的正数,那么NetStream将会变为可播放状态,或者播放指定的时间段内的录制流。(如果流在赋值的时间段内结束,那么回放也会随之结束);如果Duration为 -1 以外的负数,将会被当成 -1 处理。

Duration 表示回放的持续时间,其值的含义如下:

  • Duration = -1:表示直播流播到没有了,或录制流播放结束;
  • Duration = 0:表示只会播放从录制流开始时间的一帧;
  • Duration > 0:表示在指定的时间内播放直播流,或在指定的时间内播放录制流。
    • 如果该流在指定时间内结束,那么播放也会随之结束
  • Duration < 0 && Duration != -1:都会当作-1的情况处理

play 命令执行消息流

         +-------------+                            +----------+
         | Play Client |             |              |   Server |
         +------+------+             |              +-----+----+
                |        Handshaking and Application       |
                |             connect done                 |
                |                    |                     |
                |                    |                     |
                |                    |                     |
                |                    |                     |
       ---+---- |-----1.Command Message(createStream) ---->|
    Create|     |                                          |
    Stream|     |                                          |
       ---+---- |<---------- Command Message --------------|
                |     (_result- createStream response)     |
                |                                          |
       ---+---- |------2.Command Message (play)----------->|
          |     |                                          |
          |     |<------------3.SetChunkSize --------------|
          |     |                                          |
          |     |<----4.User Control (StreamIsRecorded)----|
     Play |     |                                          |
          |     |<----5.User Control (StreamBegin)---------|
          |     |                                          |
          |     |<--6.Command Message(onStatus-play reset)-|
          |     |                                          |
          |     |<--6.Command Message(onStatus-play start)-|
          |     |                                          |
          |     |<-------------Audio Message---------------|
          |     |                                          |
          |     |<-------------Video Message---------------|
          |     |                    |                     |
                                     |
             Keep receiving audio and video stream till finishes
                 Message flow in the play command
  1. 当客户端与服务端握手完成,并进行了连接建立后,客户端便发送createStream到客户端,请求创建一条新的块流。
  2. 当客户端从服务端接收到createStream命令的结果是success后,则发送play命令,请求后端开始播放。
  3. 一旦接收到play命令,服务端会先发送一个协议消息来设置块大小。
  4. 服务端随后发送用户控制消息,这个消息中定义了StreamIsRecorded事件和流ID。消息在前两个字节中保存事件类型,在后四个字节中保存流 ID。
  5. 服务端发送另一个用户控制消息,这一消息包含StreamBegin事件,用于发送给客户端的流的起点。
  6. 如果客户端play命令执行成功,服务端则发送两个onStatus命令消息,分别是NetStream.Play.StartNetStream.Play.Reset
    • 当客户端发送的play命令设置了reset时服务端才会发送NetStream.Play.Reset状态。
    • 如果要播放的流没有找到,服务端发送onStatus消息为NetStream.Play.StreamNotFound状态

之后,服务端开始发送视频和音频数据,客户端对其进行播放。

play2 命令(码表应用)

不同于play命令,play2命令可以在不改变播放的时间轴的情况下切换不同的比特率(即码率)。服务端维护了多个不同码率的文件,客户端可以通过play2命令来使用。

请求命令结构

客户端发给服务端的命令结构如下:

字段名(Field Name 类型(Type 描述(Description
Command Name String 命令名,取值为play2
Transaction ID Number 事务ID,取值为 0
Command Object Null 该命令不存在命令信息,取值为“null”
Command Object Object 一个 AMF 编码的对象,该对象的属性是为公开的flash.net.NetStreamPlayOptions ActionScript对象所描述的属性。

NetStreamPlayOptions对象的公开属性在ActionScript 3语言指南[AS3]中有所描述

play2 命令执行消息流

        +--------------+                          +-------------+
        | Play2 Client |              |           |    Server   |
        +--------+-----+              |           +------+------+
                 |      Handshaking and Application      |
                 |               connect done            |
                 |                    |                  |
                 |                    |                  |
                 |                    |                  |
                 |                    |                  |
        ---+---- |---- Command Message(createStream) --->|
    Create |     |                                       |
    Stream |     |                                       |
        ---+---- |<---- Command Message (_result) -------|
                 |                                       |
        ---+---- |------ Command Message (play) -------->|
           |     |                                       |
           |     |<------------ SetChunkSize ------------|
           |     |                                       |
           |     |<--- UserControl (StreamIsRecorded)----|
      Play |     |                                       |
           |     |<------- UserControl (StreamBegin)-----|
           |     |                                       |
           |     |<--Command Message(onStatus-playstart)-|
           |     |                                       |
           |     |<---------- Audio Message -------------|
           |     |                                       |
           |     |<---------- Video Message -------------|
           |     |                                       |
                 |                                       |
        ---+---- |-------- Command Message(play2) ------>|
           |     |                                       |
           |     |<------- Audio Message (new rate) -----|
     Play2 |     |                                       |
           |     |<------- Video Message (new rate) -----|
           |     |                    |                  |
           |     |                    |                  |
           |  Keep receiving audio and video stream till finishes
                                      |
                  Message flow in the play2 command

deleteStream 命令

当 NetStream 对象销毁时,NetStream 发送 deleteStream 命令。

客户端发送给服务端的命令结构如下:

字段名(Field Name 类型(Type 描述(Description
Command Name String 命令字,取值为“deleteStream”
Transaction ID Number 事务ID,取值为 0
Command Object Null 该命令不存在命令信息,取值为“null”
Stream ID Number 服务端需要销毁的流 ID

服务端不会发送任何回复

receiveAudio 命令

NetStream 通过发送 receiveAudio 消息来通知服务端是否发送音频到客户端

客户端发送给服务端的命令结构如下:

字段名(Field Name 类型(Type 描述(Description
Command Name String 命令字,取值为“receiveAudio”
Transaction ID Number 事务ID,取值为 0
Command Object Null 该命令不存在命令信息,取值为“null”
Bool Flag Boolean 表明客户端是否接受音频数据,取值 true 或 false
  • 如果发送来的receiveAudio命令Bool Flagfalse时,服务端不发送任何回复。
  • 如果发送来的receiveAudio命令Bool Flagtrue时,服务端会以状态消息NetStream.Seek.NotifyNetStream.Play.Start进行回复

NetStream.Seek.Notify:进度通知

NetStream.Play.Start:播放状态(是否开始)

receiveVideo 命令

NetStream 通过发送 receiveVideo 消息来通知服务端是否发送视频到客户端

客户端发送给服务端的命令结构如下:

字段名(Field Name 类型(Type 描述(Description
Command Name String 命令字,取值为“receiveVideo”
Transaction ID Number 事务ID,取值为 0
Command Object Null 该命令不存在命令信息,取值为“null”
Bool Flag Boolean 表明客户端是否接受视频数据,取值 true 或 false
  • 如果发送来的receiveVideo命令Bool Flagfalse时,服务端不发送任何回复。
  • 如果发送来的receiveVideo命令Bool Flagtrue时,服务端会以状态消息NetStream.Seek.NotifyNetStream.Play.Start进行回复

publish 命令

客户端通过发送给服务端这一命令来发布一个已命名的流。使用这个名字,任意客户端都可以播放这个流,并接受发布的音频、视频和数据消息。

客户端发送给服务端的命令结构如下:

字段名(Field Name 类型(Type 描述(Description
Command Name String 命令名,取值为“publish”
Transaction ID Number 事务ID,取值为 0
Command Object Null 该命令不存在命令信息,取值为“null”
Publishing Name String 发布的流的名字
Publishing Type String 表示发布类型,取值为“live”、“record”或者“append”

发布类型:

  • live:直播数据只被发布,并不对其进行录制
  • record:流被发布后,数据被录制到一个新的文件,新文件被存储在服务器上包含服务应用目录的子路径。如果文件已存在,则覆盖。
  • append:流被发布后,则添加数据到指定文件。如果文件不存在,则新建一个。

服务端回复onStatus命令以标注发布的起始位置

seek 命令

客户端通过发送seek命令查找一个多媒体文件或一个播放列表的偏移量,以毫秒为单位。

客户端发送给服务端的命令结构如下:

字段名(Field Name 类型(Type 描述(Description
Command Name String 命令字,取值为“seek”
Transaction ID Number 事务ID,取值为 0
Command Object Null 该命令不存在命令信息,取值为“null”
milliSeconds Number 查找的毫秒数

seek命令执行成功时服务端会发送一个状态消息NetStream.Seek.Notify,失败的话,服务端返回一个_error消息。

pause 命令

客户端通过发送pause命令告知服务端当前流是暂停还是重新播放。

客户端发送给服务端的命令结构如下:

字段名(Field Name 类型(Type 描述(Description
Command Name String 命令字,取值为“命令字,取值为“pause”
Transaction ID Number 事务ID,取值为 0
Command Object Null 该命令不存在命令信息,取值为“null”
Pause/Unpause Flag Boolean 表示暂停或重新播放,取值为"true"或"false"
milliSeconds Number 表示流暂停或者重新开始流所处的毫秒数。该值是客户端暂停的当前流时间,服务端会在重新播放的时候传"timestamps"更大的消息出来
  • 当流暂停时,服器端发一个NetStream.Pause.Notify 状态消息
  • 当流重新播放时,服器端发一个NetStream.Unpause.Notify` 状态消息
  • 失败的话,服器端返回一个_error消息

你可能感兴趣的:(RTMP协议(五)命令消息)