💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
[TOC] [TOC] ## RTMP 握手流程 ![](https://img.kancloud.cn/2b/da/2bda986bd54ac024693765ea8275ead5_495x599.png) 握手后走开始从 CONNECT 请求开始 ![](https://img.kancloud.cn/3f/f3/3ff3516df147e659d337a02f85366281_1186x700.png) 上面的c0、c1和s0、s1、s2都是有固定长度。简单握手中c1和s1从第9个字节开始都是**随机数**。**s2是c1的复制,c2是s1的复制** ## Message(消息) 与 Chunking(Message分块) ### Message(消息) 这⾥的Message(flv的tag需要封装成Message)是指满⾜该协议格式的、可以切分成Chunk发送的消息,消息包含的字段如下: 1. Timestamp(时间戳):消息的时间戳(但不⼀定是当前时间,后⾯会介绍),4个字节表示。 2. Length(⻓度):是指Message Payload(消息负载)即⾳视频等信息的数据的⻓度,3个字节表示。 3. TypeId(类型Id):消息的类型Id,1个字节。 4. Message Stream ID(消息的流ID):每个消息的**唯⼀标识**,划分成Chunk和还原Chunk为Message的时候都是根据这个ID来辨识是否是同⼀个消息的Chunk的,4个字节,并且以⼩端格式存储。 ### Chunking(Message分块) RTMP在收发数据的时候并不是以Message为单位的,⽽是把Message**拆分成Chunk**发送,⽽且必须在**⼀个Chunk发送完成之后**才能**开始发送下⼀个Chunk(一般不会交替发送)**。每个Chunk中带有**Message ID**代表属于哪个Message,接收端也会按照**这个id来**将chunk**组装成Message** 为什么要对Message 进行拆分 1. 分包能够减小延时和阻塞,更能适应复杂网络环境变化。 2. 通过拆分,数据量较⼤的Message可以被拆分成较⼩的“Message”,这样就可以避免优先级低(数据量大)的消息持续发送阻塞优先级⾼(数据量低)的数据 **分块设置** 1. Chunk的默认⼤⼩是128字节,在传输过程中,通过⼀个叫做Set Chunk Size的控制信息 2. 可以设置Chunk数据量的最⼤值,在发送端和接受端会各⾃维护⼀个Chunk Size(srs流媒体服务器默认是60000)可分别控制 #### Chunk Format(块格式) ![](https://img.kancloud.cn/ab/8d/ab8d836bceb1010b564d916ced3ee2a7_554x108.png) - ⼀个流当中可以交错传输多种消息类型的Chunk,通过Chunk Stream ID区分的,同⼀个Chunk Stream ID必然属于同⼀个Message - 不同的Message的**chunk Stream ID是不一样**,RTMP流中视频和⾳频拥有单独的Chunk Stream ID,⽐如⾳频的cs id=20,视频的cs id=21。接收端接收到Chunk之后,根据cs id分别将⾳频和视频“拼成成Message消息” > 每⼀种消息类型的起始chunk 的类型必须是 Type_0 类型的,表明我是⼀个新的消息的起始 **Basic Header(基本的头信息)** - chunk stream ID(流通道Id)和chunk type(chunk的类型) - RTMP协议最多⽀持65597个⽤户⾃定义chunk stream ID,范围为[3,65599] ,ID 0, 1, 2被协议规范直接使⽤,其中ID值为0, 1分表表示了Basic Header占⽤2个字节和3个字节 1. 当Basic Header为1个**字节**时,CSID占**6位**,其中⽤户可⾃定义的范围为 [3,63] ,实际是可以⽤2开始⽤ ![](https://img.kancloud.cn/ef/8c/ef8cc1e7e7753ee3e62008f2b785b432_397x204.png) chunk type 表示为 fmt 2. ID值0:代表Basic Header占⽤2个字节,CSID在 [64,319] 之间 ![](https://img.kancloud.cn/a4/7b/a47bae5a9ad05ca58a3fb692d4847f14_810x305.png) 第⼀个字节除chunk type占⽤的bit都置为0. 第⼆个字节⽤来表示CSID-64,8位可以表示 [0, 255] 共256个数 3. ID值1:代表Basic Header占⽤3个字节 ![](https://img.kancloud.cn/5c/19/5c196807c423e5fd73579af227d34e64_786x177.png) ### Message Header(消息的头信息) Message Header的格式和⻓度取决于Basic Header的**chunk type**,共有4种不同的格式 **Type=0: 占⽤11个字节** ![](https://img.kancloud.cn/d6/2d/d62dde13f185e85e45e9987a49af82ab_844x264.png) 1. timestamp(时间戳):占⽤3个字节,因此它最多能表示到16777215=0xFFFFFF=2^24-1, 当它的值超过这个最⼤值时,这三个字节都置为1,这样实际的timestamp会转存到Extended Timestamp字段中,接收端在判断timestamp字段24个位都为1时就会去Extended timestamp中解析实际的时间戳 2. message length和message length(cont)(消息数据的⻓度),占⽤3个字节,表示实际发送的消息的数据如⾳频帧、视频帧等数据的⻓度,单位是字节。注意这⾥是Message的⻓度,也就是chunk属于的Message的总数据⻓度,⽽不是chunk本身Data的数据的⻓度 3. message type id(消息的类型id):占⽤1个字节,表示实际发送的数据的类型,如8代表⾳频数据、9代表视频数据 4. msg stream id(消息的流id):占⽤4个字节,表示该chunk所在的流的ID,和Basic Header的CSID⼀样,它采⽤⼩端存储的⽅式 **Type = 1:占⽤7个字节** ![](https://img.kancloud.cn/41/cf/41cf33176fdf7150beb6520424e39d15_867x219.png) 1. timestamp delta:占⽤3个字节,注意这⾥和type=0时不同,存储的是和上⼀个chunk的时间差 **Type = 2:占⽤3个字节** ![](https://img.kancloud.cn/45/4c/454c01949e256295cc852eedbe3e7ae8_709x193.png) **Type = 3:占⽤0字节** 它表示这个chunk的Message Header和上⼀个是完全相同的,就不需要传输了 ### Extended Timestamp(扩展时间戳) chunk中会有时间戳timestamp和时间戳差timestamp delta,并且它们不会同时存在,只有这两者之⼀⼤于3个字节能表示的最⼤数值0xFFFFFF,会⽤这个字段来表示真正的时间戳