一、使用ffmpeg推送RTMP流

使用以下命令用ffmpeg推流到wowza:

ffmpeg -i "D:\var\siren\event-20181227\_113720723.mp4" -vcodec copy -acodec copy -f flv rtmp://192.168.154.202/live/rtsptest.stream

二、wireshark抓包筛选RTMP协议

推流过程中使用wireshark抓包,利用过滤器筛选出协议为RTMP的包

wireshark如何识别出RTSP wireshark抓取rtp_物联网

三、结合wireshark抓包数据讲解RTMP

1. 简介

RTMP协议是Real Time Message Protocol(实时信息传输协议)的缩写,它是由Adobe公司提出的一种应用层的协议,用来解决多媒体数据传输流的多路复用(Multiplexing)和分包(packetizing)的问题。

Adobe的实时消息传递协议(RTMP)通过可靠的流传输提供双向消息多路复用服务,例如TCP [RFC0793],用于在一对通信对等体之间携带具有相关定时信息的视频,音频和数据消息的并行流。 实现通常为不同类别的消息分配不同的优先级,这可以影响在传输容量受限时消息被排队到基础流传输的顺序。

2. 定义

  • Payload(有效载荷):包中包含的数据,例如音频样本或压缩视频数据。
  • Packet(数据包):数据包由固定的头部和有效载荷数据组成。一些底层协议可能会要求对数据包定义封装。
  • Port(端口):“传输协议用于区分给定主机内多个目的地的抽象描述,TCP / IP协议使用小正整数识别端口。”OSI传输层使用的传输选择器(TSEL)等同于端口。
  • Transport address(传输地址):标识传输层端点的网络地址和端口的组合,例如IP地址和TCP端口。
  • Message stream(消息流):通信中消息流通的一个逻辑通道。
  • Message stream ID(消息流 ID):每条消息都有一个与之关联的ID,以标识它正在流动的消息流。
  • Chunk(块):消息的片段。在通过网络发送消息之前,消息被分成更小的部分并进行交错。这些块确保跨多个流的所有消息的按时间戳排序的端到端传送。
  • Chunk stream(块流):允许在特定方向上流动块的逻辑通信通道,块流可以从客户端传输到服务器并反向。
  • Chunk stream ID(块流ID):每个块都有一个与之关联的ID,以识别它正在流动的块流。
  • Multiplexing(合成):将单独的音频/视频数据制作成一个连贯的音频/视频流的过程,使得可以同时传输多个视频和音频。
  • DeMultiplexing(解复用):多路复用的逆过程,其中交织的音频和视频数据被组合以形成原始音频和视频数据。
  • Remote Procedure Call (RPC 远程方法调用):允许客户端或服务器在对等端调用子例程或过程的请求。
  • Metadata(元数据):有关数据的说明。 电影的元数据包括电影标题,持续时间,创建日期等。
  • Application Instance(应用实例):客户端通过发送连接请求连接的服务器上的应用程序实例。
  • Action Message Format (AMF 动作消息格式):一种紧凑的二进制格式,用于序列化ActionScript对象图。AMF有两个版本:AMF 0 [AMF0]和AMF 3 [AMF3]。

3. RTMP Chunk Stream

3.1. 消息格式

可以拆分为块以支持多路复用的消息格式取决于更高级别的协议。 但是,消息格式应该包含创建块所需的以下字段:

  • Timestamp:消息的时间戳。 该字段可以传输4个字节。
  • Length:消息有效负载的长度。 如果无法省略消息标题,则应将其包含在长度中。 该字段占用块头中的3个字节。
  • Type Id:类型ID的范围被保留用于协议控制消息。 这些传播信息的消息由RTMP Chunk Stream协议和更高级别的协议处理。 所有其他类型ID可供更高级别协议使用,并被RTMP Chunk Stream视为不透明值。 事实上,RTMP Chunk Stream中没有任何内容要求将这些值用作类型; 所有(非协议)消息可以是相同类型,或者应用程序可以使用此字段来区分同时跟踪而不是类型。 该字段在块头中占用1个字节。
  • Message Stream ID:消息流ID可以是任意值。 复用到同一块流上的不同消息流基于它们的消息流ID被多路分用。 除此之外,就RTMP Chunk Stream而言,这是一个不透明的值。该字段以小端格式占用块头中的4个字节。

3.2. 握手

RTMP连接以握手开始, 握手不同于协议的其余部分。它由三个静态大小的块组成,而不是由带有标题的可变大小的块组成。 客户端(已启动连接的端点)和服务器均发送相同的三个块。 对于展示,当客户端发送时,这些块将被指定为C0,C1和C2; S0,S1和S2由服务器发送。

3.2.1 握手顺序

  • 握手开始于客户端发送C0和C1块。
  • 在发送C2之前,客户端必须等待直到收到S1。
  • 在发送任何其他数据之前,客户端必须等待直到收到S2。
  • 在发送S0和S1之前,服务器必须等待直到收到C0,并且可以等到C1之后。 在发送S2之前,服务器必须等待直到收到C1。 在发送任何其他数据之前,服务器必须等待直到收到C2。

3.2.2 C0和S0格式

C0和S0数据包是单个八位字节,被视为单个8位整数字段:

wireshark如何识别出RTSP wireshark抓取rtp_字段_02


以下是C0 / S0数据包中的字段:

版本(8位):在C0中,此字段标识客户端请求的RTMP版本。 在S0中,该字段标识服务器选择的RTMP版本。 此规范定义的版本为3。值0-2是早期专有产品使用的弃用值;4-31保留用于将来的实现;不允许使用32-255(允许区分RTMP与基于文本的协议,后者始终以可打印字符开头)。 无法识别客户端请求的版本的服务器应该响应3。客户端可以选择降级到版本3,或放弃握手。

3.2.2 C1和S1格式

C1和S1数据包长度为1536个八位字节,由以下字段组成:

wireshark如何识别出RTSP wireshark抓取rtp_面试_03

  • Time (4 bytes):该字段包含一个时间戳,该时间戳应该用作从该端点发送的所有未来块的时间起点。 这可以是0,或某个任意值。 为了同步多个块流,端点可能希望发送另一个块流的时间戳的当前值。
  • Zero (4 bytes):该字段必须全为0。
  • Random data (1528 bytes):该字段可以包含任意值。 由于每个端点必须区分对其已启动的握手的响应和由其对等方发起的握手,因此该数据应该发送足够随机的内容。 但是不需要加密安全随机性,甚至动态值。