rtmp是协议还是服务器,RTMP协议

一、简述及一些参考文档

RTMP(Real-Time Messaging Protocol,实时消息传输协议)是Adobe开发的一种用于实时数据通信的应用层网络协议,基于TCP传输。实际上是一个协议族,主协议是RTMP,包括RTMP基本协议及RTMPT/RTMPS/RTMPE/RTMFP等多种变种,其中RTMFP是RTMP基于UDP传输的一种协议,用于P2P通信。该协议主要用于解决多媒体数据传输流中的多路复用和分包问题。

二、RTMP一些基本点

目前国内RTMP协议主要用于直播推流端,在播放端的使用非常少。虽然RTMP是封闭协议,但实际上rtmpdump的开源库已经基本实现了这个协议,基于该开源项目进行二次开发,可以减少绝大部分工作量。相较于RTP协议,用RTMP推流时无论客户端还是服务端的开发工作都较为简单,在使用过程中也较为易于理解,可靠性更高但延迟会相对高一点。(建议快速上线使用RTMP,超低延迟直播或长远考虑用RTP)

RTMP协议中的分块(Chunk)可以用来实现流多路复用和分包,其中块大小是可以设置的。显然,将消息分块传输会带来额外开销,所以需要尽可能减少额外开销。块越小可能开销越大,块越大可能延迟越大(某些重要优先级的消息到达也缓慢)。

对于RTMP协议,实际上官方文档比较简短(我怀疑有些内容没写出来,哈哈),建议通读一遍。

RTMP协议中封装的数据包括AMF格式和普通的FLV音视频tag。AMF编码用于onMetaData中各个字段值的压缩(在FLV的Script tag里面)。

三、协议解析

时间戳单调递增且线性增长,超出时间戳(32bits)上限的需要客户端和服务端协商处理轮转。

对于多路复用和分包的处理,RTMP协议在传输时会用RTMP Message(消息)来封装数据,而每一条Message在发送端会被划分为一个或多个带有Message ID的Chunk(分块)。接收端根据约定格式和ID将Message还原。

Chunk格式:

633fa703173ca191601007cd833b09d9.png

图一、Chunk格式

如上图所示,Chunk的额外开销可以在1~18个字节之间。刚开始的Chunk开销会比较大,传输几个分块后会逐渐优化,开销可以仅剩Basic Header那部分。

RTMP消息格式:消息头和负载。消息头包括消息类型(Msg Type,第1-7位表示)、负载长度(Payload Length)、消息时间戳(Timestamp)、消息流ID(Msg Stream ID)。以上均设置为big-endian格式。如下图所示。

360781311d5b3ad14a7e6ed4d284b1be.png

图二、消息头格式

协议控制消息可以用于设置块大小(消息类型为1)、取消消息(2)、确认某次接收的数据(3)、发送用户控制事件(4)、确认窗口大小(5)、设置对等端带宽(6)。

客户端和服务端之间传递的常规消息包括——

消息种类

AMF0编码类型

AMF3编码类型

备注

命令消息

20

17

连接、创建流、发布、播放、暂停等

数据消息

18

15

发送元数据或用户数据

共享对象消息

19

16

用于在多个客户端、实例、服务端等之间同步。每个消息可以包含多个事件

音频消息

8

8

发送音频数据

视频消息

9

9

发送视频数据

聚合消息

22

22

含有一个消息列表,减少发送chunk开销

用户控制消息

4

4

流ID为0,块ID为2,属于协议控制消息的一类,发送用户控制事件

上表中命令消息中提到的命令,主要包括NetConnection和NetStream命令。(注:这部分使用详见协议文档,对每个命令的每种操作都有详细介绍)

NetConnection命令可以用于连接、调用、关闭、创建流操作;

NetStream命令是基于NetConnection对象的。一个NetConnection对象可以支持多个NetStream。该命令用于播放、播放2(一个连接上多个不同码率流)、删除流、接收音频、接收视频、发布、拖拽(seek)、暂停操作。

RTMP连接建立流程:

握手开始于客户端发送C0,C1块。

在发送C2之前客户端必须等待接收S1 。

在发送任何数据之前客户端必须等待接收S2。

服务端在发送S0和S1之前必须等待接收C0,也可以等待接收C1。

服务端在发送S2之前必须等待接收C1。

服务端在发送任何数据之前必须等待接收C2。

ef7c83c937b09a9cff69a0386a5d6596.png

图三、RTMP握手过程示意图

四、直播推流中使用RTMP协议

(1)客户端

这里指的是推流客户端。

Web端推流,目前能想到的就是在浏览器已经有flash插件的情况下,直接调用flash推流。

移动端推流可以使用rtmp库。Android端的音视频数据编码、封装如果在上层的话,需要通过JNI来调用rtmp库的接口;ios端OC可以和该库中的C语言直接混编调用。

需要注意的是,rtmp库中的很多参数都是默认设置,建议读一遍主要的代码,以便于进行超时、重试、重连等操作。

(2)流媒体服务器搭建

基于Nginx搭建RTMP流媒体服务器的文档,网上一大把一大把的,整体来说就是安装依赖环境并配置,其实算比较简单。

但是,考虑到服务器处理大量直播源流时的高并发要求,以及直播流的延迟控制等,个人不太建议直接从FFMPEG调用rtmp库,可以根据自己业务要求对rtmp库进行优化后再部署安装。

(3)延迟的控制

rtmp推流过程中,很容易出现延迟较大的情况(虽然名字上叫实时协议,但延迟高达10s不是梦啊......)。这主要来源于两部分——网络抖动和TCP重传(实际上工程应用中,还有音视频采集和编码模块的不稳定性、硬件设备受限等各种因素)。

RTMP协议内部以及rtmp库本身都没有适应网络抖动的策略,所以推流过程中,需要开发人员自己去增加这部分策略。若使用原生的协议和开源库,当带宽受限时数据包会累积在“待发送缓冲区”,延迟逐步增大。而且即使客户端上行带宽一直较为稳定,由于TCP传输的可靠性,总会有一些数据包重传,累积延迟进一步增大。这部分的优化可以考虑在推流端加入丢帧策略(千万注意不要导致花屏和跳播),加入带宽评估模块,在服务端优化网络环境,使用BGP机房,就近节点推流等。

(4)重连策略

RTMP默认的超时时间是比较长的,在实际应用场景中一般无法忍受。同样需要开发人员根据业务需求,修改配置并优化重连策略。

主要是针对移动网络下网络断开、延迟过大等情况,需要开发人员按需重连。

(5)流畅性保障

对于直播播放来说,音视频的流畅也尤为重要。在推流过程中的任意一个环节导致的音视频数据没有及时存储到源服务器(或分发到CDN节点),都会从源头上导致播放不流畅。

But,很显然我们无法要求网络一直稳定,也不敢说服务端的接收和分发就完全可靠,能做的只是尽可能减少副作用。如果是对延迟不太敏感的直播,最好的办法当然就是设立缓冲;如果是延迟比较敏感的直播,可以用抖动缓冲区,不断在延迟和流畅度之间找平衡;如果是延迟极为敏感的直播,建议直接要求推流用户自身保障设备在高速网络下不挪动(稳一点😓),或者换协议。在源流服务器和CDN分发部分,可以使用BGP机房,多机房及多CDN厂商之间调度。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值