h5 rtmp推荐控件_RTMP H5 直播流技术解析

本文深入探讨了RTMP实时消息协议在H5直播中的应用,详细介绍了RTMP的握手过程、协议结构以及相关操作。通过实例展示了如何使用Buffer进行RTMP三次握手,同时讲解了RTMP协议的基础架构,包括Header、Message Body及其不同类型的Message。此外,还提到了RTMP在视频流传输中的音视频同步策略。
摘要由CSDN通过智能技术生成

上一篇文章简单阐述了,在 H5 中,做直播需要哪些技术知识点,有哪些直播流协议和技术。通过对比,本篇主要聚焦于 RTMP 直播协议的相关内容,也就是说,本篇将会直接进行实际操作 Buffer 的练习和相关的学习。

RTMP 是什么

RTMP 全称即是 Real-Time Messaging Protocol。顾名思义就是用来作为实时通信的一种协议。该协议是 Adobe 搞出来的。主要是用来传递音视频流的。它通过一种自定义的协议,来完成对指定直播流的播放和相关的操作。和现行的直播流相比,RTMP 主要的特点就是高效,这里,我就不多费口舌了。我们先来了解一下 RTMP 是如何进行握手的。

RTMP 握手

RTMP 是基于 TCP 三次握手之后的,所以,RTMP 不是和 TCP 一个 level 的。它本身是基于 TCP 的可靠性连接。RTMP 握手的方式如图:

(C 代表 Client,S 代表 Server)

它主要是通过两端的字段内容协商,来完成可信度认证的。基本过程如下:

client: 客户端需要发 3 个包。C0,C1,C2

server: 服务端也需要发同样 3 个包。 S0,S1,S2。

整个过程如上图所述,但实际上有些细节需要注意。

握手开始:

【1】 客户端发送 C0,C1 包

此时,客户端处于等待状态。客户端有两个限制:

客户端在未接受到 S1 之前不能发送 C2 包

客户端在未接收到 S2 之前不能发送任何实际数据包

【2】 服务端在接受到 C0,发送 S0,S1 包。也可以等到接受到 C1 之后再一起发送,C1 包的等待不是必须的。

此时,服务端处于等待状态。服务端有两个限制:

服务端在未接受到 C1 之前不能发送 S2.

服务端在未接收到 C2 之前不能发送任何实际数据包

【3】客户端接受到 S1/S0 包后,发送 C2 包。

【4】服务端接受到 C2 包后,返回 S2 包,并且此时握手已经完成。

不过,在实际应用中,并不是严格按照上面的来。因为 RTMP 并不是强安全性的协议,所以,S2/C2 包只需要 C1/S1 中的内容,就可以完成内容的拼接。

这么多限制,说白了,其实就是一种通用模式:

C0+C1

S0+S1+S2

C2

接下来,我们来具体看看 C/S 012 包分别代表什么。

C0 && S0

C0 和 S0 其实区别不大,我这里主要讲解一下 C0,就差不多了。首先,C0 的长度为 1B。它的主要工作是确定 RTMP 的版本号。

C0:客户端发送其所支持的 RTMP 版本号:3~31。一般都是写 3。

S1:服务端返回其所支持的版本号。如果没有客户端的版本号,默认返回 3。

C1 && S1

C1/S1 长度为 1536B。主要目的是确保握手的唯一性。格式为:

time: 发送时间戳,这个其实不是很重要,不过需要记住,不要超出 4B 的范围即可。

zero: 保留值 0.

random: 该字段长尾 1528B。主要内容就是随机值,不管你用什么产生都可以。它主要是为了保证此次握手的唯一性,和确定握手的对象。

C2 && S2

C2/S2 的长度也是 1536B。相当于就是 S1/C1 的响应值。上图也简单说明了就是,对应 C1/S1 的 Copy 值,不过第二个字段有区别。基本格式为:

time: 时间戳,同上,也不是很重要

time2: C1/S1 发送的时间戳。

random: S1/C1 发送的随机数。长度为 1528B。

这里需要提及的是,RTMP 默认都是使用 Big-Endian 进行写入和读取,除非强调对某个字段使用 Little-Endian 字节序。

上面握手协议的顺序也是根据其中相关的字段来进行制定的。这样,看起来很容易啊哈,但是,我们并不仅仅停留在了解,而是要真正的了解,接下来,我们来实现一下,如果通过 Buffer 来进行 3 次握手。这里,我们作为 Client 端来进行请求的发起,假设 Server 端是按照标准进行发送即可。

Buffer 实操握手

我们使用 Buffer 实操主要涉及两块,一个块是 request server 的搭建,还有一块是 Buffer 的拼接。

Request Server 搭建

这里的 Server 是直接使用底层的 TCP 连接。

如下,一个简易的模板:

const client = new net.Socket();

client.connect({

port: 1935,

host: "6721.myqcloud.com"},

()=>{

console.log("connected");

});

client.on('data',(data)=>{

client.write('hello');

});

不过,为了更好的进行实际演练,我们通过 EventEmitter 的方式,来做一个筛选器。这里,我们使用 mitt 模块来做代理。

const Emitter = require('mitt')();

然后,我们只要分析的就是将要接受到的 S0/1/2 包。根据上面的字节包图,可以清楚的知道包里面的详细内容。这里,为了简单起见,我们排除其他协议的包头,只是针对 RTMP 里面的包。而且,我们针对的只有 3 种包,S0/1/2。为了达到这种目的,我们需要在 data 时间中,加上相应的钩子才行。

这里,我们借用 Now 直播的 RTMP 流来进行相关的 RTMP 直播讲解。

Buffer 操作

Server 的搭建其实上网搜一搜,应该都可以搜索出来。关键点在于,如何针对 RTMP 的实操握手进行 encode/decode。所以,这里,我们针对上述操作,来主要讲解一下。

我们主要的工作量在于如何构造出 C0/1/2。根据上面格式的描述,大家应该可以清楚的知道 C0/1/2 里面的格式分别有啥。

比如,C1 中的 time 和 random,其实并不是必须字段,所以,为了简单起见,我们可以默认设为 0。具体代码如下:

class C {

constructor() {

this.time;

this.random;

}

C0() {

let buf = Buffer.alloc(1);

buf[0] = 3;

return buf;

}

C1() {

let buf = Buffer.alloc(1536);

return buf;

}

/**

* write C2 package

* @param {Number} time the 4B Number of time

* @param {Buffer} random 1528 byte

*/

produceC2(){

let buf = Buffer.alloc(1536);

// leave empty value as origin time

buf.writeUInt32BE(this.time, 4);

this.random.cop

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值