RTMP协议

news/2024/7/5 6:57:26/文章来源:https://www.cnblogs.com/duzhaoquan/p/18280524

     与RTSP 不同,RTSP(Real-Time Streaming Protocol)是一个控制协议,负责控制媒体流的传输,但不传输媒体数据本身。RTSP 可以通过 TCP 或 UDP 传输 RTP 包来传输音视频数据。                   

     RTMP(Real-Time Messaging Protocol)是一个综合性的协议,不仅可以传输音视频数据,还可以传输信令控制指令。RTMP 使用 TCP 作为传输协议,可以直接在 TCP 连接上传输音视频数据,也可以传输控制指令,实现了音视频流的实时传输和控制。

一.RTMP概述
      1.RTMP(Real Time Messaging Protocol)是Adobe公司提出的实时消息传输协议,用于传递带有时间信息的视频、音频和数据消息流。
     2.应用广泛于直播领域,常用于向云端推流。
     3.工作在TCP之上,默认端口为1935,基于TCP协议进行传输。
二. RTMP交互过程总结
    握手协议:建立TCP连接后,通过RTMP握手协议来完成RTMP的连接,包括客户端发送C0、C1、C2块,服务端发送S0、S1、S2块。
     RTMP分块(chunk):将RTMP消息(Message)拆分为多个块(Chunk)进行发送,每个Chunk包含音视频数据和信令。
     协议控制消息(Protocol Control Message):使用特殊值代表控制消息,如SetChunkSize、SetACKWindowSize、CreateStream等。
     RTMP消息格式(RTMP Message Format):包括消息头和有效负载,消息头包含消息类型、负载长度、时间戳和消息流ID
2.1 握手协议:
    一般的发送顺序如下:

    1:客户端向服务端同时发送C0+C1

    2:服务端确认版本号后,向客户端同时发送S0+S1+S2

    3:客户端接收到S2后发送C2到服务端

RTMP 协议的握手过程中,C0 和 S0 分别代表客户端和服务器端的版本号,是握手的第一步。

  • C0 包(Client to Server,客户端到服务器):C0 包是客户端发送给服务器的第一个字节,用于表示客户端请求的 RTMP 版本号。在规范最新定义中,C0 包的版本号为 3。当客户端发起连接时,它会将 C0 包发送给服务器,表明它所期望的 RTMP 协议版本。
  • S0 包(Server to Client,服务器到客户端):S0 包是服务器发送给客户端的第一个字节,用于表示服务器选择的 RTMP 版本号。同样,规范最新定义中,S0 包的版本号也为 3。服务器在接收到客户端的 C0 包后,会向客户端发送 S0 包,以通知客户端所采用的 RTMP 协议版本。

    这种简单的握手过程可以确保客户端和服务器端都采用相同的 RTMP 协议版本进行通信,避免版本不一致导致的通信问题。如果客户端和服务器端的版本号不匹配,可能会导致握手失败,从而终止连接或者降级到兼容的版本。

     C1 和 S1 是 RTMP 握手过程中的第二步,它们的长度为 1536 字节,用于在客户端和服务器之间进行密钥协商和安全通信设置。

  • C1 包(Client to Server,客户端到服务器):C1 包是客户端发送给服务器的,长度为 1536 字节,用于包含客户端的随机数据和时间戳。具体字段包括:

         时间戳:4 字节,用于标识 C1 包的创建时间。
         随机数据:1528 字节,用于在密钥协商过程中生成密钥。

  • S1 包(Server to Client,服务器到客户端):S1 包是服务器发送给客户端的,长度也为 1536 字节,包含服务器端的随机数据和时间戳。具体字段包括:

         时间戳:4 字节,用于标识 S1 包的创建时间。
         随机数据:1528 字节,用于在密钥协商过程中生成密钥。
     C1 和 S1 包的随机数据和时间戳字段将在后续的握手过程中用于生成密钥和验证连接的安全性。这些包是 RTMP 握手过程中的一部分,用于确保客户端和服务器之间的通信是安全可靠的。

2.2 RTMP分块(chunk)
    RTMP(Real-Time Messaging Protocol)传输的数据被称为消息(Message),这些消息可以包含音视频数据和信令。然而,RTMP 不会将整个消息作为一个单元进行传输,而是将消息分割成更小的单元,称为分块(Chunk),然后逐个发送这些分块。每个分块都带有一个 msg stream id,用于指示它属于哪个消息,接收端根据这个 id 来将分块组装成完整的消息。

RTMP 分块包含以下几个部分:

  • 基本头(Basic Header):基本头包含了分块的基本信息,如分块的类型和所属的消息流 id。基本头的长度可以是 1 到 3 个字节,具体取决于消息流 id 的大小。
  • 消息头(Message Header):消息头包含了分块的扩展时间戳(如果有的话)和分块的长度信息。消息头的长度也可变,最小为 0 字节,最大为 11 字节。
  • 扩展时间戳(Extended Timestamp):如果消息头中的时间戳字段取值为 0xFFFFFF,则表示时间戳需要通过扩展时间戳字段来进行传输。
  • 负载(Payload):负载部分包含了分块的实际数据,可能是音视频数据或控制信令。

 

2.3 协议控制消息(Protocol Control Message)
    在RTMP协议中,除了传输音视频数据外,还有一些专门用于控制协议行为的消息,称为协议控制消息。这些控制消息通常用一些特殊的值来标识,并且在传输过程中有一些固定的要求:

  1. Message Stream ID: 控制消息的 Message Stream ID 必须为 0,以表示这是用于控制流程的消息。
  2. Chunk Stream ID (CSID): 控制消息的 Chunk Stream ID 必须为 2,以标识这是一个用于传输控制消息的特殊 CSID。
  3. Message Type ID: 控制消息的 Message Type ID 可以是以下几种值:1、2、3、5、6。每种消息类型对应不同的控制操作。

      Message Type ID=1:设置chunk中Data字段所能承载的最大字节数,默认为128bytes,通信过程中可以通过发送该消息来设置chunk Size的大小(不得小于128bytes),该值将作用于后续的所有块的发送,直到收到新的通知,而且通信双方会各自维护一个chunkSize,两端的chunkSize是独立的

      Message Type ID=2:当一个Message被切分为多个chunk,接受端只接收到了部分chunk时,发送该控制消息表示发送端不再传输同Message的chunk,接受端接收到这个消息后要丢弃这些不完整的chunk。

      Message Type ID=3:当收到对端的消息大小等于窗口大小(Window Size)时接受端要回馈一个ACK给发送端告知对方可以继续发送数据。窗口大小就是指收到接受端返回的ACK前最多可以发送的字节数量,返回的ACK中会带有从发送上一个ACK后接收到的字节数。

      Message Type ID=5:发送端在接收到接受端返回的两个ACK间最多可以发送的字节数,客户端或服务端发送该消息来通知对方发送确认消息(ACK)所使用的窗口大小,并等待对方发送回确认消息(ACK),对方(接收端)在接收到窗口大小确认信息后必须发送确认消息(ACK)。

      Message Type ID=6:限制对端的输出带宽。接受端接收到该消息后会通过设置消息中的Window ACK Size来限制已发送但未接受到反馈的消息的大小来限制发送端的发送带宽。如果消息中的Window ACK Size与上一次发送给发送端的size不同的话要回馈一个Window Acknowledgement Size的控制消息。

       4.时间戳(Timestamp): 接收端在收到控制消息后会立即生效,不需要考虑消息中的时间戳。

总的来说,协议控制消息在 RTMP 协议中扮演着控制协议行为的重要角色,通过这些消息可以实现对协议的各种控制操作。

 

2.4 RTMP消息格式(RTMP Message Format)
      RTMP被设计成使用RTMP块流传输,但是它也可以使用其他传输协议来发送消息。RTMP块流协议和RTMP协议配合时,非常适合音视频应用,包括一对一和一对多实时直播、视频点播和视频互动会议等, RTMP协议使用块流传输数据,其中每个数据块由消息头和有效负载两部分组成。

    消息头(Message Header):消息头包含了关于数据块的一些重要信息,如消息类型、消息长度、时间戳和流ID等。这些信息用于确定如何处理数据块以及如何组装它们成为完整的消息。消息头通常包括以下字段:

  • 消息类型(Message Type):指示数据块的类型,如音频数据、视频数据、命令消息等。
  • 消息长度(Message Length):指示数据块有效负载的长度,即数据块中除了消息头之外的部分的长度。
  • 时间戳(Timestamp):表示数据块的时间戳,用于同步音视频数据的播放。
  • 流ID(Stream ID):标识数据块所属的流,用于在多个流中区分不同的数据。

   有效负载(Payload):有效负载是数据块的实际内容,可以是音频数据、视频数据或其他应用数据。有效负载的内容取决于消息类型,例如音频数据消息将包含音频数据,视频数据消息将包含视频数据。

        这里注意RTMP消息的头(RTMP Message Header,不是chunk头中的 Message Header,两个不是同一个东西)有自己的统一格式,

      消息头(RTMP Message Header)和数据块头(Chunk Header)是不同的内容,尽管它们都涉及到传输数据的控制,但是在实际的流媒体服务器中,通常只需要在Chunk中包含数据块头(Chunk Header),而消息头则不需要单独传输。

       具体来说,RTMP消息头包含了一些关于消息的重要信息,如消息类型、消息长度、时间戳和流ID等,这些信息用于确定如何处理数据块以及如何组装它们成为完整的消息。而数据块头(Chunk Header)也包含了类似的信息,例如消息类型和消息长度。在某些情况下,RTMP消息头中的信息与Chunk头中的信息重复,因此在发送RTMP消息时,流媒体服务器可以选择在Chunk中只包含数据块头而不包含RTMP消息头,以减少冗余信息的传输,提高传输效率。

      简而言之,消息头中的信息在Chunk头中也有所体现,而且这些信息在双方之间已经约定好了,因此在实际的流媒体传输过程中,通常只需要在Chunk中包含数据块头即可,而不需要额外传输消息头。

3. RTMP流媒体传输详解

  • RTMP推流:发布客户端通过握手协议、发送连接请求、创建流通道、发布命令消息、传输元数据和音视频数据等步骤完成推流。
  • RTMP拉流:客户端通过握手协议、发送创建流命令、播放命令等步骤完成拉流。

3.1 RTMP推流

 

  1. 握手协议(handshaking done):发布客户端和服务器之间进行握手,确保双方可以正常通信。
  2. 连接请求消息(Command Message(connect)):发布端向服务器发送连接请求消息,以建立与服务器的连接。
  3. 窗口应答大小确认信息(Window Acknowledgement Size):服务器接收到连接命令后,发送窗口应答大小确认信息,用于设置双方之间的窗口大小,以便控制数据流量。
  4. 配置对端带宽(Set Peer Bandwidth):服务器向客户端发送配置对端带宽的消息,以告知客户端服务器端的带宽情况。
  5. 用户控制协议(Stream Begin):服务器发送用户控制协议消息,通知客户端流开始信息,表示可以开始传输数据。
  6. 连接接收响应信息(_result-connect response):服务器向发布端发送连接接收响应信息,告知发布端连接已成功建立。
  7. 创建流通道(CreateStream):发布端发起创建流通道的请求,以便开始推送流数据。
  8. 响应创建流(_result-createStream response):服务器接收到创建流通道请求后,向发布端发送响应消息,告知创建流通道成功。
  9. 发布命令消息(Publish):发布端发起发布命令消息,以准备开始传输数据。
  10. 准备开始传输元数据消息(Metadata):发布端发送元数据消息,用于描述流数据的属性和格式。
  11. 准备开始传输音频数据(Audio data):发布端开始发送音频数据。
  12. 配置Chunk Size:发送端配置chunk size,用于控制数据传输的块大小。
  13. 开始发送视频数据:发布端开始发送视频数据。
  14. 返回发布结果信息:服务器接收到发布命令后,向发布端返回发布结果信息,表示开始接收音视频流数据。

     其上为官方规范文档中描述的流程,实际过程可能稍有不同,发送端和接收端主要对创建流、发布、和数据传输的消息比较关注,解析时一般按照规范顺序和格式解析,其他消息发送顺序并无特殊规定,消息较小时,可一次发送多个RTMP消息。
     命令消息/数据消息/共享消息,最常用的消息封装格式为AMF0~AMF3,示例中也是此方式编码,具体编码格式请查阅资料 ,rtmp数据如何封装 AMF的

3.2 RTMP 拉流

官方流程图如下:

 

  1. 握手协议(Handshaking):客户端和服务器之间进行握手,确保双方可以正常通信。
  2. 创建流命令(CreateStream):客户端向服务器发送创建流命令,请求服务器发送流数据。
  3. 响应命令(Response):服务器接收到创建流命令后,向客户端发送响应命令,表示已经准备好发送流数据。
  4. 命令消息(Play):客户端发送播放命令(Play),请求服务器开始发送流数据。
  5. 配置Chunk大小:服务器端在接收到播放命令后,配置chunk大小,以控制数据传输的块大小。 服务器端接收到播放命令play后,配置chunk大小,发送用户控制协议(StreamIsRecorded、StreamBegin)通知是否录制流,流已开启标志,之后发送播放命令响应消息(刷新当前状态、通知播放开始),这里如果play命令成功,服务端回复onStatus 命令消息 NetStream.Play.Start和NetStream.Play.Reset,其中NetStream.Play.Reset只有当客户端发送的play命令里设置了reset时才会发送,如果要播放的流没有找到,服务端会发送onStatus消息NetStream.Play.StreamNotFound。
  6. 用户控制协议(StreamIsRecorded、StreamBegin):服务器发送用户控制协议,通知客户端流是否已录制以及流已开始播放。
  7. 播放命令响应消息(Response):服务器接收到播放命令后,向客户端发送响应消息,通知播放已开始。
  8. 音视频消息发送:服务器开始向客户端发送音视频消息,客户端接收到消息后开始播放流数据。

     这个流程描述了RTSP的拉流过程,其中客户端主动请求服务器发送流数据,服务器根据请求准备好数据后发送给客户端,客户端接收数据并播放。

四:RTMP消息和Chunk之间的关系
    前文已经介绍了RTMP传输的单位不是massage,而是把massage拆分成一个或多个chunk来进行传输,可根据msg stream id判断是否属于同一个Massage,也就是

1:RTMP消息被拆分为Chunk进行传输,每个Chunk包含msgstreamid以标识属于哪个Message。

2:接收端根据chunk中的msgstreamid将Chunk组装成完整的Message

   与实际抓包示例的真实过程比较,可以看出,真实rtmp很多地方并没有与规范匹配,所以在进行rtmp音视频解析时,尽量只校验自己需要的数据,其他消息格式放宽校验,增加兼容性,有关AMF格式,可参照规范

原文链接:https://blog.csdn.net/xiaoshuaijinniu/article/details/137352785


 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/736498.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

yarn install 时显示 node_modules\esbuild: Command failed

可以找一找你的nodejs安装路径是不是中文的,如果是中文的换成英文应该就可以了(记得系统变量里也要改掉)

阿里云个人账号 创建docker仓库

1、创建阿里云账号 2、搜索“容器镜像服务”,进入,点击“管理控制台” 3、选择个人实例,这一步可能会让你创建registry密码(如果没有创建过的话),后面登录需要 4、创建命名空间5、创建镜像仓库 输入信息,点击下一步,选择本地仓库 6、进入管理页面 执行相关命令

Django3在网页上生成二维码

1.安装依赖包pip install django-qr-code2.在django,你项目的settings中,安装app 打开你项目的setting,找到INSTALLED_APPS ,在这里新加一条qr_code INSTALLED_APPS = [...,rest_framework,qr_code,... ] 3.在你打算渲染的html文档中,导入模板 {% load qr_code %}ps:如果…

Hackthebox bagel.dll 代码审计

利用ilspy将bagel.dll打开关于此目录有可以说的内容 目录解析 最上方的bagel是组装名字(assemble name) bagel_server 是命令空间(namespace) 下一级分支是类如File,Base,Handler,Orders等(class) 反序列化导致的命令执行漏洞代码审计思路 首先看主程序Bagel 1.通过明显的英…

2024/7/2 T1

题意:分析: 记 \(S_{i}\) 表示目前第 \(i\) 个集合里的元素个数。 集合之间互不区分,强制钦定必须满足 \(S_{i} \le S_{i+1}(i<k)\)。 经搜索发现,这样的状态数量最多约为 \(1.8 \times 10^5\)。 极差可以这样处理:将 \(a\) 排序,\(S_{i}\) 第一次加入某个元素 \(x\),…

Eplan插件 - 矩形修订云线

前言 在 CAD 中,矩形云线一直是设计师们用于标注修订区域或突出重要部分的得力工具。然而,在 Eplan 中,没有直接绘制矩形云线的功能。为了填补这一空白,开发了专门用于Eplan的矩形修订云线插件。 这款插件保留了Eplan绘制的习惯,可以简洁快速的框选出需要修订或者重点关注…

Nginx配置以及热升级

目录Nginx详解1. Nginx关键特性2. Nginx配置2.1 event2.2 http2.2.1 log_format2.2.2 sendfile2.2.3 tcp_nopush2.2.4 tcp_nodelay2.2.5 keepalive_timeout2.2.6 include2.2.7 default_type2.2.8 server3. 配置Nginx虚拟主机3.1 基于端口3.2 基于IP3.3 基于域名4. Location4.1 …

Python3学习之路~3.4 作业之对员工信息表实现增删改查操作

有以下员工信息表当然此表你在文件存储时可以这样表示1,Alex Li,22,13651054608,IT,2013-04-01 现需要对这个员工信息文件,实现增删改查操作可进行模糊查询,语法至少支持下面3种: select name,age from staff_table where age > 22 select * from staff_table where dep…

Python3学习之路~2.11 补充:Python输出字符串加颜色or背景色

格式:\033[二位数;1m字符串\033[0m 二位数为31-37,40-47(其他数字无效),其中:十位数3表示字颜色,4表示背景色个位数0-7分别表示 黑 红 绿 黄 蓝 紫 浅蓝 灰 示例代码:# 加颜色:31-37 print("\033[31;1mHello Python-31-红色字\033[0m") print("\033[32;…

【触想智能】工业平板电脑在新能源领域上的应用分析

工业平板电脑是一种具有高性能和稳定性的计算机设备,适用于在恶劣环境下进行数据采集、运营管理和现场操作。随着新能源技术的快速发展,工业平板电脑不断地得到应用,并且已成为新能源领域中的重要工具之一。本文将从四个方面探讨工业平板电脑在新能源领域中的应用。一、智能…

免费可视化工具在智慧物流中是如何被应用的?

在现代智慧物流中,免费可视化工具正扮演着越来越重要的角色。这些工具通过数据的可视化展示,使物流管理更加高效、透明和智能化。免费可视化工具可以将复杂的物流数据转换为直观的图表和图形,帮助管理者实时监控和分析物流运作情况,从而优化资源配置和提升物流效率。免费可…

一秒即懂财务报表勾稽关系

财务报表的勾稽关系!审计!审计试算平衡!算平衡表!项目经理!财务总监!会计!出纳6财务报表勾稽关系属于会计做账是否正确的要且快速的方法! 6财务人员对外提供报表是非常正常且频繁的情,股东要求,税局纳税申报,发行股票,发券,公司年度总结等等场合。 6而实际现状是,…

Redis Sentinal(哨兵模式详解)

参考文章 https://www.cnblogs.com/wzh2010/p/18030907 1、什么是哨兵模式 在实际生产环境中,服务器难免会遇到一些突发状况:服务器宕机,停电,硬件损坏等等,一旦发生,后果不堪设想。哨兵模式的核心还是主从模式的演变,只不过相对于主从模式,在主节点宕机导致不可写的情…

Profibus DP主站转Modbus网关连接智能化电表通讯

Profibus DP主站转Modbus网关(XD-MDPBM20),是实现不同工业通信协议之间互联互通的设备,主要将Profibus DP协议转换为Modbus协议,实现数据的双向传输。通过Profibus DP主站转Modbus网关(XD-MDPBM20),可以有效实现现场设备和控制系统之间的无缝连接,提高生产效率。Profi…

[XDCTF 2015]filemanager

[XDCTF 2015]filemanager ​/www.tar.gz​拿到源码 我直接在github上看了https://github.com/CTFTraining/xdctf_2015_filemanager common.inc.php将传入的所有参数使用addslashes转义函数 ​​ 然后分析upload.php 使用basename​函数确保文件名中没有目录路径,防止路径遍历攻…

解码未来城市:探秘数字孪生的奥秘

在科技日新月异的今天,"数字孪生"(Digital Twin)这一概念如同一颗璀璨的新星,照亮了智慧城市、智能制造等多个领域的前行之路。本文将深入浅出地解析数字孪生的定义、技术原理、应用场景及未来发展,带您一窥这股引领时代潮流的力量。数字孪生的定义数字孪生,简…

linux系统配置中文字体,playwright中文乱码

复制字段 从本地Windows (C:\Windows\Fonts ) 复制一个中文字体simsun.tcc 在Linux系统上安装字体 yum -y install fontconfig mkdir -p /usr/share/fonts/chinese cd /usr/share/fonts/chinese# 将simsun.tcc上传到/usr/share/fonts/chinese,并修改权限: chmod -R 755 /usr/…

transformer中的attention机制详解

transformer中用到的注意力机制包括self-attention(intra-attention)和传统的attention(cross-attention),本篇文章将在第一节简述这两者的差别,第二节详述self-attention机制,第三节介绍其实现 self-attention和attention的区别 传统attention机制 发生在decoder和enco…

Profibus转Modbus网关在智能化水处理系统优化改造的应用

Profibus协议和Modbus协议作为两种常见的工业通信协议,各自具有一定的优势和适用范围。而通过Profibus转Modbus网关(XD-MDPB100)的加入将两者结合使用,可以实现不同设备之间的无缝连接和数据传输,为罐内压载水处理系统的监控和控制提供了更为便利的解决方案。通过Profibus…

代码随想录算法训练营第四十四天 | 322.零钱兑换 279.完全平方数 139.单词拆分

322.零钱兑换 题目链接 文章讲解 视频讲解class Solution { public:int coinChange(vector<int>& coins, int amount) {// dp[j]: 表示能凑成面额j所需的最少硬币个数vector<int> dp(amount + 1, 0);// 递推公式: dp[j] = min(dp[j - coins[i]] + 1, dp[j])// …