主页

索引

模块索引

搜索页面

从 0 打造音视频直播系统

目录

备注

李超 前新东方音视频直播技术专家,前沪江音视频架构师

  • Blob: Binary Large Object(, js)

  • DSP: Digital Signal Processer(, webrtc)

  • ICE: Interactive Connectivity Establishment(交互式连接创建, webrtc)

  • RDP: Remote Desktop Protocal(远程桌面控制协议, protocal)

  • SDP: Session Description Protocal(, webrtc)

  • STUN: Simple Traversal of UDP over NATs(NAT的UDP简单穿越, webrtc)

  • TURN: Traversal Using Relay NAT(, webrtc)

  • VNC: Virtual Network Console(, 远程桌面控制协议, protocal)

  • MCU: Multipoint Conferencing Unit

  • RTCP: Real-time Control Protocol(实时传输控制协议)

  • RTP: Real-time Transport Protocol(实时传输协议)

  • SCTP: Stream Control Transport Protocol

  • SFU: Selective Forwarding Unit

  • SRTP: Secure RTP(安全实时传输协议, 安全)

  • SRTCP: Secure RTCP(安全实时传输控制协议, 安全)

  • GYP: Generate Your Projects(Python,Chromium)

  • SWIG: Simplified Wrapper and Interface Generator(C/C++ 接口转换脚本语言)

  • RTMP: Real Time Messaging Protocol(实时消息协议)

  • HLS: HTTP Live Streaming

  • PES: Packet Elementary Stream

  • ES: Elementary Stream(基流)

  • PTS: Presentation Tmestamp

  • WebRTC: Web Real-Time Communication(网页即时通信)

SWIG(Simplified Wrapper and Interface Generator ),是一个将 C/C++ 接口转换成其他脚本语言(如 JavaScript、Ruby、Perl、Tcl 和 Python)的接口转换器,可以将你想暴露的 C/C++ API 描述在一个后缀是 *.i 的文件里面,然后通过 SWIG 编译器就可以生成对应脚本语言的 Wrapper 程序了,这样对应的脚本语言(如 JavaScript)就可以直接调用 Wrapper 中的 API 了。

  • 对于娱乐直播都是使用 rtmp 协议,它的客户端包括 APP, PC…;

  • 对于音视频会议 / 在线教育这种场景,普遍都使用的 webrtc,在 webrtc 底层用的是 RTP/RTCP/UDP 协议

ffmpeg 和 webrtc 是做音视频两个最重要的库,ffmpeg 在处理音视频时有一套自己的流程,可以说这套流程的使用 ffmpeg 大大降低了人们利用音视频的难度。如果你熟练的撑握了 ffmpeg,就可以做出很多非常酷炫的事儿了。但学习这套流程本身就有难度;对于 webrtc 来讲也是如此,它最大的优势是在实时通信及音频通话方面。对于这两个库的学习其实不用专门学习数据知识的。 实际上音视频编解码在真正工作中的开发量并不大。对于音视频的应用而言,理解编解码的基本原理,熟悉它的 API 如何使用就可以了。像音视频的算法之类的工作,全世界也没有多少人在搞,除非你数学特别牛,算法特别牛,否则的话不建议去专门搞音视频算法。对于音视频的发展,目前业界有比较统一的观点,就是 WebRTC 会引领未来,现在几乎所有的大厂都在研究 WebRTC , 而 ffmepg 作为 WebRTC 处理音视的工具在 WebRTC 内部使用。所以你要想在音视频方面深入的话,这两个库是你必须要深入研究的。

WebRTC 1 对 1 通话 (23 讲)

01 | 原来通过浏览器访问摄像头这么容易

https://img.zhaoweiguo.com/knowledge/images/jikes/webRTCs/architect1.png

WebRTC 1 对 1 音视频实时通话过程示意图

从大的方面可以分为 3 部分:

1. WebRTC 终端
    负责音视频采集、编解码、NAT 穿越、音视频数据传输
2. Signal 服务器
    负责信令处理,如加入房间、离开房间、媒体协商消息的传递等
3. STUN/TURN 服务器
    负责获取 WebRTC 终端在公网的 IP 地址,以及 NAT 穿越失败后的数据中转

STUN 服务器是用于获主机的外网 IP 地址的,这样才能进行 NAT 穿越。但在国网 NAT 穿越的成功率还不到 50%。

音视频采集基本概念:

1. 摄像头
    用于捕捉(采集)图像和视频。
2. 帧率
    摄像头一秒钟采集图像的次数称为帧率。
    帧率越高,视频就越平滑流畅。
    然而,在直播系统中一般不会设置太高的帧率,
    因为帧率越高,占的网络带宽就越多。
3. 分辨率
    摄像头除了可以设置帧率之外,还可以调整分辨率。
    我们常见的分辨率有 2K、1080P、720P、420P 等。
    分辨率越高图像就越清晰,但同时也带来一个问题,即占用的带宽也就越多。
    所以,在直播系统中,分辨率的高低与网络带宽有紧密的联系。
    也就是说,分辨率会跟据你的网络带宽进行动态调整。
4. 宽高比
    分辨率一般分为两种宽高比,即 16:9 或 4:3。
    4:3 的宽高比是从黑白电视而来,而 16:9 的宽高比是从显示器而来。
    现在一般情况下都采用 16:9 的比例。
5. 麦克风
    用于采集音频数据。
    它与视频一样,可以指定一秒内采样的次数,称为采样率。
    每个采样用几个 bit 表示,称为采样位深或采样大小。
6. 轨(Track)
    WebRTC 中的 “轨” 借鉴了多媒体的概念。
    火车轨道的特性你应该非常清楚,两条轨永远不会相交。
    “轨” 在多媒体中表达的就是每条轨数据都是独立的,不会与其他轨相交,
    如 MP4 中的音频轨、视频轨,它们在 MP4 文件中是被分别存储的。
7. 流(Stream)
    可以理解为容器。
    WebRTC 中,“流” 可以分为媒体流(MediaStream)和数据流(DataStream)
    其中,媒体流可以存放 0 个或多个音频轨或视频轨;
    数据流可以存 0 个或多个数据轨。

ICE 服务:

ICE 服务是对 STUN  TURN 服务的整合
用于处理 peers 间的打洞和打洞不通的情况下的转发

02 | 如何通过 WebRTC 进行音视频设备检测呢

备注

模数转换使用的采集定理称为奈奎斯特定理:在进行模拟 / 数字信号的转换过程中,当采样率大于信号中最高频率的 2 倍时,采样之后的数字信号就完整地保留了原始信号中的信息。

人类听觉范围的频率是 20Hz~20kHz 之间。对于日常语音交流(像电话),8kHz 采样率就可以满足人们的需求。但为了追求高品质、高保真,你需要将音频输入设备的采样率设置在 40kHz 以上,这样才能完整地将原始信号保留下来。例如我们平时听的数字音乐,一般其采样率都是 44.1k、48k 等,以确保其音质的无损。

  • 音频设备:采集到的数据再经过量化、编码,最终形成数字信号

  • 视频设备:则与音频输入设备很类似。当实物光通过镜头进行到摄像机后,它会通过视频设备的模数转换(A/D)模块,即光学传感器, 将光转换成数字信号,即 RGB(Red、Green、Blue)数据。获得 RGB 数据后,还要通过 DSP(Digital Signal Processer)进行优化处理,如自动增强、白平衡、色彩饱和等都属于这一阶段要做的事情。通过 DSP 优化处理后,你就得到了 24 位的真彩色图片。因为每一种颜色由 8 位组成,而一个像素由 RGB 三种颜色构成,所以一个像素就需要用 24 位表示,故称之为 24 位真彩色。此时获得的 RGB 图像只是临时数据。因最终的图像数据还要进行压缩、传输,而编码器一般使用的输入格式为 YUV I420,所以在摄像头内部还有一个专门的模块用于将 RGB 图像转为 YUV 格式的图像。

备注

YUV 也是一种色彩编码方法,主要用于电视系统以及模拟视频领域。它将亮度信息(Y)与色彩信息(UV)分离,即使没有 UV 信息一样可以显示完整的图像,只不过是黑白的,这样的设计很好地解决了彩色电视机与黑白电视的兼容问题。

03 | 如何使用浏览器给自己拍照呢

从摄像头里采集的帧或通过解码器解码后的帧都是非编码帧。非编码帧的格式一般是 YUV 格式或是 RGB 格式。相对于非编码帧,通过编码器(如 H264/H265、VP8/VP9)压缩后的帧称为编码帧。

编码帧:经过 H264 编码的帧包括以下三种类型:

1. I 帧:关键帧
    压缩率低,可以单独解码成一幅完整的图像。
2. P 帧:参考帧
    压缩率较高,解码时依赖于前面已解码的数据。
3. B 帧:前后参考帧
    压缩率最高,解码时不光依赖前面已经解码的帧,而且还依赖它后面的 P 帧。
    换句话说就是,B 帧后面的 P 帧要优先于它进行解码,然后才能将 B 帧解码。

拍照的过程其实是从连续播放的一幅幅画面中抽取正在显示的那张画面。

备注

音视频包括音端和后端,前端主要责音视频的采集,编解码,传输,渲染。后端主要负责流的分发,选择最佳传输通道,信令控制等。

04 | 可以把采集到的音视频数据录制下来吗

实现录制功能的方式:

1. 服务端录制:
    优点是:
      不用担心客户因自身电脑问题造成录制失败(如磁盘空间不足),
      也不会因录制时抢占资源(CPU 占用率过高)而导致其他应用出现问题等;
    缺点是:
      实现的复杂度很高。
2. 客户端录制:
    优点是:
      方便录制方(如老师)操控,并且所录制的视频清晰度高,实现相对简单。
      一般客户端摄像头的分辨率都非常高的(如 1280x720),
        所以客户端录制可以录制出非常清晰的视频;
      但服务端录制要做到这点就很困难了,
        本地高清的视频在上传服务端时由于网络带宽不足,
        视频的分辨率很有可能会被自动缩小到了 640x360,
        这就导致用户回看时视频特别模糊,用户体验差。
    缺点是:
      录制失败率高。
      因为客户端在进行录制时会开启第二路编码器,这样会特别耗 CPU。
      而 CPU 占用过高后,就很容易造成应用程序卡死。
      除此之外,它对内存、硬盘的要求也特别高。

本地录制主要有以下三个重要的问题:

1. 录制后音视频流的存储格式是什么呢?
  比如,是直接录制原始数据,还是录制成某种多媒体格式(如 MP4 )
2. 录制下来的音视频流如何播放?
  是使用普通的播放器播放,还是使用私有播放器播呢?
3. 启动录制后多久可以回放呢
  a. 边录边看: 如:重大体育赛事
  b. 录制完立即回放: 如:直播课
  c. 录完后过一段时间可观看: 如:录制完成后要对音视频做剪辑、转码,制作各种不同的清晰度的回放

05 | 原来浏览器还能抓取桌面

共享桌面的基本原理:

1. 对于共享者
  每秒钟抓取多次屏幕(可以是 3 次、5 次等),
  每次抓取的屏幕都与上次抓取的屏幕比较,取它们的差值,然后对差值进行压缩;
  如果是第一次抓屏或切幕的情况:
    即本次抓取的屏幕与上一次抓取屏幕的变化率超过 80% 时,
      就做全屏的帧内压缩,其过程与 JPEG 图像压缩类似。
  最后再将压缩后的数据通过传输模块传送到观看端;
  数据到达观看端后,再进行解码,这样即可还原出整幅图片并显示出来。
2. 对于远程控制端
  当用户通过鼠标点击共享桌面的某个位置时,会首先计算出鼠标实际点击的位置,
  然后将其作为参数,通过信令发送给共享端。
  共享端收到信令后,会模拟本地鼠标,即调用相关的 API,完成最终的操作。
  当操作完成后,共享端桌面也发生了一些变化,此时就又回到上面共享者的流程

备注

总结:共享桌面的处理过程为:抓屏、压缩编码、传输、解码、显示、控制

远程桌面协议一般分为桌面数据处理与信令控制两部分:

1. 桌面数据
  包括了桌面的抓取 (采集)、编码(压缩)、传输、解码和渲染
2. 信令控制
  包括键盘事件、鼠标事件以及接收到这些事件消息后的相关处理等

备注

WebRTC 的远程桌面不需要远程控制,所以其处理过程使用了视频的方式,而非传统意义上的 RDP/VNC 等远程桌面协议。

第一个环节,共享端桌面数据的采集:

WebRTC 对于桌面的采集与 RDP/VNC 使用的技术是相同的,
  都是利用各平台所提供的相关 API 进行桌面的抓取。

以 Windows 为例,可以使用下列 API 进行桌面的抓取:
1. BitBlt:XP 系统下经常使用,在 vista 之后,开启 DWM 模式后,速度极慢
2. Hook:一种黑客技术,实现稍复杂
3. DirectX:由于 DirectX 9/10/11 之间差别比较大,容易出现兼容问题。
  最新的 WebRTC 都是使用的这种方
4. GetWindowDC:可以通过它来抓取窗口

第二个环节,共享端桌面数据的编码:

WebRTC 对桌面的编码使用的是视频编码技术,即 H264/VP8 等;
但 RDP/VNC 则不一样,它们使用的是图像压缩技术。
使用视频编码技术的好处是压缩率高,而坏处是在网络不好的情况下会有模糊等问题

第三个环节,传输:

编码后的桌面数据会通过流媒体传输协议发送到观看端。
对于 WebRTC 来说,当网络有问题时,数据是可以丢失的。
但对于 RDP/VNC 来说,桌面数据一定不能丢失。

第四个环节,观看端解码:

WebRTC 对收到的桌面数据通过视频解码技术解码,
而 RDP/VNC 使用的是图像解码技术(可对比第二个环节)。

第五个环节,观看端渲染:

一般会通过 OpenGL/D3D 等 GPU 进行渲染,
这个 WebRTC 与 RDP/VNC 都是类似的。

06 _ WebRTC中的RTP及RTCP详解

RTP

先给音视频数据加个 RTP 头,然后再交给 UDP 进行传输:

1. 序号:用于标识传输包的序号,这样就可以知道这个包是第几个分片了
2. 起始标记:记录分帧的第一个 UDP 包
3. 结束标记:记录分帧的最后一个 UDP 包
https://img.zhaoweiguo.com/knowledge/images/jikes/webRTCs/RTP1.png

RTP 协议规范图

RTP 协议关键字段:

1. sequence number:序号,用于记录包的顺序。
  这与上面我们自己实现拆包、组包是同样的道理。
2. timestamp:时间戳,同一个帧的不同分片的时间戳是相同的。
  这样就省去了前面所讲的起始标记和结束标记。
  一定要记住,不同帧的时间戳肯定是不一样的。
3. PT:Payload Type,数据的负载类型。
  音频流的 PT 值与视频的 PT 值是不同的,
  通过它就可以知道这个包存放的是什么类型的数据。
https://img.zhaoweiguo.com/knowledge/images/jikes/webRTCs/RTP2.png

RTP 协议头

RTCP

备注

RTCP 协议:在使用 RTP 包传输数据时,难免会发生丢包、乱序、抖动等问题,WebRTC 对这些问题在底层都有相应的处理策略,但在处理这些问题之前,它首先要让各端都知道它们自己的网络质量到底是怎样的,这就是 RTCP 的作用。

RTCP 有两个最重要的报文:RR(Reciever Report)和 SR (Sender Report)。通过这两个报文的交换,各端就知道自己的网络质量到底如何了。

https://img.zhaoweiguo.com/knowledge/images/jikes/webRTCs/RTCP1.png

RTCP 协议规范图

RTCP 协议关键字段:

1. V=2,指报文的版本。
2. P,表示填充位
    如果该位置 1,则在 RTCP 报文的最后会有填充字节(内容是按字节对齐的)。
3. RC,全称 Report Count,指 RTCP 报文中接收报告的报文块个数。
4. PT=200,Payload Type,也就是说 SR 的值为 200。
https://img.zhaoweiguo.com/knowledge/images/jikes/webRTCs/RTCP2.png

RTCP 协议头

SR 报文分成三部分:

1. Header 部分用于标识该报文的类型,比如是 SR 还是 RR
2. Sender info 部分用于指明作为发送方,到底发了多少包
3. Report block 部分指明发送方作为接收方时,它从各个 SSRC 接收包的情况
https://img.zhaoweiguo.com/knowledge/images/jikes/webRTCs/RTCP3.png

RTCP 协议PT类型

https://img.zhaoweiguo.com/knowledge/images/jikes/webRTCs/RTCP4.png

RTCP 协议PT类型:205 和 206 两种不同的反馈消息。UDP 丢包通过 RTCP 的 NACK 来解决

备注

SR 报文与 RR 报文无疑是 RTCP 协议中最重要的两个报文,不过 RTCP 中的其他报文也都非常重要的。比如,RTCP 类型为 206、子类型为 4 的 FIR 报文,其含义是 Full Intra Request (FIR) Command,即完整帧请求命令。它起的作用:在一个房间里有 3 个人进行音视频聊天,当第四个人加入到房间后,它首先发送 FIR 报文,当其他端收到该报文后,便立即产生各自的 IDR 帧发送给新加入的人

备注

在 WebRTC 中, RTP/RTCP 只是众多协议中的比较重要的两个,还有 SRTP/SRTCP、DTLS、STUN/TURN

  • FIR: Full Intra Request(, webrtc)

07 | SDP: 它可是WebRTC的驱动核心

标准 SDP 规范主要包括 SDP 描述格式和 SDP 结构,而 SDP 结构由会话描述和媒体信息描述两个部分组成。

媒体信息描述是整个 SDP 规范中最重要的知识,它又包括:

1. 媒体类型
2. 媒体格式
3. 传输协议
4. 传输的 IP 和端口
  1. SDP 的格式:

    SDP 是由多个 <type>=<value> 这样的表达式组成的。
    其中,<type>是一个字符,<value>是一个字符串。
    需要特别注意的是,“=” 两边是不能有空格的。
    
    该 SDP 描述中有两个媒体流,一个是音频流,另一个是视频流
    
  2. SDP 的结构:

    SDP 的结构由会话描述和媒体描述两部分组成。
    1)会话描述
      第一个,v=(protocol version,必选)
        例子:v=0 ,表示 SDP 的版本号,但不包括次版本号
      第二个,o=(owner/creator and session identifier,必选)
        例子:o=<username> <session id> <version> <network type> <address type> <address>
        该例子是对一个会话发起者的描述
        a. o= 表示的是对会话发起者的描述
        b. <username>: 用户名,当不关心用户名时,可以用 “-” 代替
        c. <session id>: 数字串,在整个会话中,唯一,建议使用 NTP 时间戳
        d. <version>: 版本号,每次会话数据修改后,该版本值会递增
        e. <network type>: 网络类型,一般为“IN”,表示“internet”
        f. <address type>: 地址类型,一般为 IP4
        g. <address>: IP 地址
      第三个,Session Name(必选)
        例子:s=<session name>,该例子表示一个会话,
        在整个 SDP 中有且只有一个会话,也就是只有一个 s=
      第四个,t=(time the session is active,必选)
        例子:t=<start time> <stop time>,
        该例子描述了会话的开始时间和结束时间
    
    2)媒体描述
      第一个,m=(media name and transport address,可选)
        例子:m=<media> <port> <transport> <fmt list>
        <media>:媒体类型,比如 audio/video 等
        <port>:端口
        <transport>:传输协议,有两种——RTP/AVP 和 UDP
        <fmt list>:媒体格式,即数据负载类型 (Payload Type) 列表
      第二个,a=*(zero or more media attribute lines,可选)
        例子:a=<TYPE>或 a=<TYPE>:<VALUES>
      第三个,rtpmap(可选)
        例子:a=rtpmap:<payload type> <encoding name>/<clock rate>[/<encodingparameters>]
        rtpmap 是 rtp 与 map 的结合,即 RTP 参数映射表
        <payload type> :负载类型,对应 RTP 包中的音视频数据负载类型
        <encoding name>:编码器名称,如 VP8、VP9、OPUS 等
        <sample rate>:采样率,如音频的采样率频率 32000、48000 等
        <encodingparameters>:编码参数,如音频是否是双声道,默认为单声道
      第四个,fmtp
        例子:a=fmtp:<payload type> <format specific parameters>。
        fmtp,格式参数,即 format  parameters;
        <payload type> ,负载类型,同样对应 RTP 包中的音视频数据负载类型;
        < format specific parameters>指具体参数
    

备注

SDP 是由一个会话层和多个媒体层组成的;而对于每个媒体层,WebRTC 又将其细划为四部分,即媒体流、网络描述、安全描述和服务质量描述。

08 _ 有话好商量, 论媒体协商

  • 创建连接,指的是创建 RTCPeerConnection,它负责端与端之间彼此建立 P2P 连接。

  • 信令,指的是客户端通过信令服务器交换 SDP 信息。

09 _ 让我们揭开WebRTC建立连接的神秘面纱

端对端的建立更主要的工作是 Candidate 的收集。WebRTC 将 Candidate 分为三种类型:

1. host 类型,即本机内网的 IP 和端口
2. srflx 类型,即本机 NAT 映射后的外网的 IP 和端口
3. relay 类型,即中继服务器的 IP 和端口

1. STUN 协议

RFC5389

https://img.zhaoweiguo.com/knowledge/images/jikes/webRTCs/NAT1.png

srflx 类型的 Candidate 实际上就是内网地址和端口经 NAT 映射后的外网地址和端口。NAT 的作用就是进行内外网的地址转换。

通过 STUN 协议,主机是如何获取到自己的外网 IP 地址和端口的:

a. 在外网搭建一个 STUN 服务器
b. 从内网主机发送一个 binding request 的 STUN 消息到 STUN 服务器
c. STUN 服务器收到该请求后,会将请求的 IP 地址和端口填充到 binding response 消息中,然后顺原路将该消息返回给内网主机

2. TURN 协议

  • RFC5766

relay 服务是通过 TURN 协议实现的。所以我们经常说的 relay 服务器或 TURN 服务器它们是同一个意思,都是指中继服务器。

NAT 打洞 /P2P 穿越

WebRTC 将 NAT 分类为 4 种类型:

1. 完全锥型 NAT
2. IP 限制型 NAT
3. 端口限制型 NAT
4. 对称型 NAT

ICE

ICE 就是上面所讲的获取各种类型 Candidate 的过程,也就是:在本机收集所有的 host 类型的 Candidate,通过 STUN 协议收集 srflx 类型的 Candidate,使用 TURN 协议收集 relay 类型的 Candidate。

other

prflx 类型与 srflx 类型的区别:

prflx 和 srflx 都是为了获取内网主机 IP 映射的公网 IP
srflx candidate 是通过信令方式向 STUN 服务器发送 binding request,通过该请求找到 NAT 映射后的地址(server 视角);prflx candidate 用于链接检查,当 A 按照优先级向目标 peer B 发送 binding request,B 收到 peer A 的连通性成功时获得的地址(peer 视角)

10 | WebRTC NAT 穿越原理

1. 完全锥型 NAT

https://img.zhaoweiguo.com/knowledge/images/jikes/webRTCs/NAT2.png

完全锥型 NAT 图

备注

完全锥型 NAT 的特点是,当 host 主机通过 NAT 访问外网的 B 主机时,就会在 NAT 上打个 “洞”,所有知道这个 “洞” 的主机都可以通过它与内网主机上的侦听程序通信。

这里所谓的 “打洞” 就是在 NAT 上建立一个内外网的映射表:

该映射表简单地认为是一个 4 元组,即:
{
  内网 IP,
  内网端口,
  映射的外网 IP,
  映射的外网端口
}

2. IP 限制锥型 NAT

https://img.zhaoweiguo.com/knowledge/images/jikes/webRTCs/NAT3.png

IP 限制锥型 NAT 图

备注

IP 限制锥型要比完全锥型 NAT 严格得多,它主要的特点是,host 主机在 NAT 上 “打洞” 后,NAT 会对穿越洞口的 IP 地址做限制。只有登记的 IP 地址才可以通过,也就是说,只有 host 主机访问过的外网主机才能穿越 NAT。而其他主机即使知道 “洞” 的位置,也不能与 host 主机通信,因为在通过 NAT 时,NAT 会检查 IP 地址,如果发现发来数据的 IP 地址没有登记,则直接将该数据包丢弃。注意:IP 限制型 NAT 只限制 IP 地址,如果是同一主机的不同端口穿越 NAT 是没有任何问题的。

IP 限制锥型 NAT 的映射表是一个 5 元组,即:

{
  内网 IP,
  内网端口,
  映射的外网 IP,
  映射的外网端口,
  被访问主机的 IP
}

3. 端口限制锥型

备注

端口限制锥型比 IP 限制锥型 NAT 更加严格,它主要的特点是,不光在 NAT 上对打洞的 IP 地址做了限制,而且还对具体的端口做了限制。

端口限制型 NAT 的映射表是一个 6 元组,其格式如下:

{
  内网 IP,
  内网端口,
  映射的外网 IP,
  映射的外网端口,
  被访问主机的 IP,
  被访问主机的端口
}

4. 对称型 NAT

https://img.zhaoweiguo.com/knowledge/images/jikes/webRTCs/NAT4.png

对称型 NAT 图

备注

对称型 NAT 是所有 NAT 类型中最严格的一种类型。host 主机访问 B 时它在 NAT 上打了一个 “洞”,而这个 “洞” 只有 B 主机上提供服务的端口发送的数据才能穿越,这一点与端口限制型 NAT 是一致的。它与端口限制型 NAT 最大的不同在于,如果 host 主机访问 A 时,它会在 NAT 上重新开一个 “洞”,而不会使用之前访问 B 时打开的 “洞”。也就是说对称型 NAT 对每个连接都使用不同的端口,甚至更换 IP 地址,而端口限制型 NAT 的多个连接则使用同一个端口,这对称型 NAT 与端口限制型 NAT 最大的不同。

NAT 类型检测

https://img.zhaoweiguo.com/knowledge/images/jikes/webRTCs/NAT5.png

NAT 类型检测图

说明:每台服务器都是双网卡的,而每个网卡都有一个自己的公网 IP 地址。有一个隐含条件:WebRtc 客户端与防火墙之间只有 1 个 NAT 映射,只有一个映射的情况是最简单的,如果有多个出口 IP 的话的,情况会更复杂。

第一步,判断是否有 NAT 防护:

1. 主机向服务器 #1 的某个 IP 和端口发送一个请求,服务器 #1 收到请求后,会通过同样的 IP 和端口返回一个响应消息。
2. 如果主机收不到服务器 #1 返回的消息,则说明用户的网络限制了 UDP 协议,直接退出。
3. 如果能收到包,则判断返回的主机的外网 IP 地址是否与主机自身的 IP 地址一样。
    如果一样,说明主机就是一台拥有公网地址的主机;
    如果不一样,就跳到下面的步骤 6。
4. 如果主机拥有公网 IP,则还需要进一步判断其防火墙类型。
    所以它会再向服务器 #1 发一次请求,此时,服务器 #1 从另外一个网卡的 IP 和不同端口返回响应消息。
5. 如果主机能收到,说明它是一台没有防护的公网主机;如果收不到,则说明有对称型的防火墙保护着它。
6. 继续分析第 3 步,如果返回的外网 IP 地址与主机自身 IP 不一致,说明主机是处于 NAT 的防护之下,
    此时就需要对主机的 NAT 防护类型做进一步探测。

第二步,探测 NAT 环境:

1. 在 NAT 环境下,主机向服务器 #1 发请求,服务器 #1 通过另一个网卡的 IP 和不同端口给主机返回响应消息。
2. 如果此时主机可以收到响应消息,说明它是在一个完全锥型 NAT 之下。
    如果收不到消息还需要再做进一步判断。
3. 如果主机收不到消息,它向服务器 #2(也就是第二台服务器)发请求,
    服务器 #2 使用收到请求的 IP 地址和端口向主机返回消息。
4. 主机收到消息后,判断从服务器 #2 获取的外网 IP 和端口与之前从服务器 #1 获取的外网 IP 和端口是否一致,
    如果不一致说明该主机是在对称型 NAT 之下。
5. 如果 IP 地址和端口一样,则需要再次发送请求。
    此时主机向服务器 #1 再次发送请求,服务器 #1 使用同样的 IP 和不同的端口返回响应消息。
6. 此时,如果主机可以收到响应消息说明是 IP 限制型 NAT,否则就为端口限制型 NAT。

备注

所以:对称型 NAT 与对称型 NAT 之间以及对称型 NAT 与端口限制型 NAT 之间无法打洞成功。在中国,P2P 成功率很低,尤其是移动互联网,成功率国内低于50%。对称型可以通过生日悖论来突破吧,只是要尝试的次数太多,时间延迟较大,而且在国内成功率不超过 60%

11 | 如何通过Node.js实现一套最简单的信令系统

WebRTC 规范中约束只针对于客户端,并没有对服务端做任何限制。

WebRTC 信令服务器至少要实现下面两个功能:

1. 房间管理。
  即每个用户都要加入到一个具体的房间里,
  比如两个用户 A 与 B 要进行通话,那么它们必须加入到同一个房间里。
2. 信令的交换。
  即在同一个房间里的用户之间可以相互发送信令。

12 _ RTCPeerConnection: 音视频实时通讯的核心

RTPPeerConnection 这个知识点是你掌握 WebRTC 开发的重中之重,抓住它你就抓住了学习 WebRTC 的钥匙(这里你一定要清楚,SDP 是掌握 WebRTC 运行机制的钥匙,而 RTCPeerConnection 是使用 WebRTC 的钥匙)

备注

可以简要地回答:RTCPeerConnection就是一个功能超强的 socket!如果你从使用的角度看,会觉得 RTCPeerConnection 是一个接口类;如果你从功能的角度看,它又是一个功能聚合类。

13 _ 在WebRTC中如何控制传输速率呢

对音视频服务质量产生影响的因素:

1. 网络质量,包括物理链路的质量、带宽的大小、传输速率的控制等
2. 数据,包括音视频压缩码率、分辨率大小、帧率等
  1. 物理链路质量:

    包括三个方面,即丢包、延迟和抖动
    对于实时通信来说,
      a. 200ms 以内的延迟是最好的,这样通话双方的感觉就像是在面对面谈话
      b. 如果延迟是在 500 ms 以内,通话双方的体验也还不错,有点像打电话的感觉
      c. 如果延迟达到 800ms,还能接受,但有明显的迟滞现像
      d. 但如果延迟超过 1 秒,那就不是实时通话了
    
  2. 带宽大小:

    1M 带宽是每秒钟可以传输 1M 个 bit 位,换算成字节就是 1Mbps/8 = 128KBps
    当带宽固定时核心在:充分利用带宽。即:把带宽尽量占满,但千万别超出带宽的限制
    
  3. 传输速率:

    与传输速率相关的有两个码率:音视频压缩码率和传输控制码率
    a. 音视频压缩码率:
      单位时间内音视频被压缩后的数据大小,或简单地理解为压缩后每秒的采样率。
      它与视频的清晰度是成反比的,也就是压缩码率越高,清晰度越低
      音视频编码被称为有损压缩,与有损压缩对应的是无损压缩,
        它是指数据解压后还能还原回来,像我们日常中用到的 Zip、RAR、GZ
    b. 传输控制码率:
      对网络传输速度的控制
      即:在要传输的数据大于带宽时,才需要对速度进行控制,以达到最快的传输速度
    
  4. 分辨率与帧率:

    分辨率越高,视频就越清晰
    
    例:1 帧未压缩过分辨率是 1280 * 720的视频帧:
    存成 RGB 格式,则这一帧的数据为 1280 * 720 * 3 * 8
      (3 表示 R、G、B 三种颜色,8 表示将 Byte 换算成 bit)
      约等于 22Mb;
    存成 YUV420P 格式则约等于 11Mb,即 1280 * 720 * 1.5 * 8
    

14 | 如何打开 / 关闭音视频

打开 / 关闭音视频流有下面几种需求:

1. 将远端的声音静音
2. 将自己的声音静音
3. 关闭远端的视频
4. 关闭自己的视频

15 | WebRTC 中的数据统计

  • chrome://webrtc-internals

17 _ 如何使用Canvas绘制统计图表

如果你想将一幅图在屏幕上显示出来,那么只需要将图形转换成像素图,这样就可以通过连接起来的像素将图像展示在显示器上。以上这个过程就是图像渲染的过程,它有一个专业术语,叫做光栅化。

https://img.zhaoweiguo.com/knowledge/images/jikes/webRTCs/canvas1.png

图形处理原理图:应用程序处理的图形数据都是保存在 System Memory 中的。需要硬件处理的时候,先将 System Memory 中的图形数据拷贝到 Graphic Memory 中。然后,通过 CPU 指令通知 GPU 去处理图形数据。GPU 收到指令后,从 Graphic Memory 读取图形数据,然后进行坐标变换、着色等一系列复杂的运算后形成像素图,也就是 Video Frame,会存储在缓冲区中。视频控制器从 Video Frame 缓冲区中获取 Video Frame,并最终显示在显示器上。

  • OpenGL(Open Graphic Library)是一个应用编程接口,用于 2D/3D 图形处理。最早是由 Silicon Graphics 公司提出的,目前是由 Khronos Group 维护。OpenGL 虽说是一个 API,但其实并没有代码实现,只是定义了接口规范。至于具体实现则是由各个显卡厂家提供的。OpenGL ES 规范是基于 OpenGL 规范的,主要用于嵌入式平台。目前 Android 系统上的视频 / 图像渲染都是使用的 OpenGL ES。当然,以前 iOS 也是使用 OpenGL ES 做视频 / 图像渲染,不过现在已经改为使用自家的 Metal 了。

  • WebGL 是用于在 HTML 页面上绘制 3D 图像的规范。它是基于 OpenGL 规范的。比如,WebGL 1.0 规范是基于 OpenGL 2.0 规范,WebGL 2.0 规范基于 OpenGL 3.0 规范。

19 _ WebRTC能不能进行文本聊天呢

WebRTC 的 RTCDataChannel 使用的传输协议为 SCTP,即 Stream Control Transport Protocol。

https://img.zhaoweiguo.com/knowledge/images/jikes/webRTCs/sctp1.png

在 TCP、UDP 及 SCTP 等不同传输模式下,数据传输的可靠性、传递方式、流控等信息的对比

22 _ 如何保证数据传输的安全

https://img.zhaoweiguo.com/knowledge/images/jikes/webRTCs/security1.png

WebRTC 安全序列图

https://img.zhaoweiguo.com/knowledge/images/jikes/webRTCs/DTLS1.png

DTLS 握手协议示意图

23 _ 实战演练: 通过WebRTC实现一个1对1音视频实时直播系统

https://img.zhaoweiguo.com/knowledge/images/jikes/webRTCs/signal_state1.png

信令状态机图

WebRTC 多人音视频实时通话 (7 讲)

24 | 多人音视频实时通讯是怎样的架构

多方通信架构无外乎以下三种方案:

1. Mesh 方案,即多个终端之间两两进行连接,形成一个网状结构。
  这种方案对各终端的带宽要求比较高。
2. MCU(Multipoint Conferencing Unit)方案
  该方案由一个服务器和多个终端组成一个星形结构。
  实际上服务器端就是一个音视频混合器,这种方案服务器的压力会非常大。
3. SFU(Selective Forwarding Unit)方案
  该方案也是由一个服务器和多个终端组成,
  但与 MCU 不同的是,SFU 不对音视频进行混流,
  收到某个终端共享的音视频流后,就直接将该音视频流转发给房间内的其他终端。
  它实际上就是一个音视频路由转发器。

Mesh 方案

https://img.zhaoweiguo.com/knowledge/images/jikes/webRTCs/multi-mesh1.png

Mesh 方案架构图:B1、B2、B3、B4 分别表示 4 个浏览器,它们之间两两相连,同时还分别与 STUN/TURN 服务器进行连接(此时的 STUN/TURN 服务器不能进行数据中转,否则情况会变得非常复杂),这样就形成了一个网格拓扑结构

这种结构的优势有如下: 不需要服务器中转数据,STUN/TUTN 只是负责 NAT 穿越,这样利用现有 WebRTC 通信模型就可以实现,而不需要开发媒体服务器。 充分利用了客户端的带宽资源。 节省了服务器资源,由于服务器带宽往往是专线,价格昂贵,这种方案可以很好地控制成本。 当然,有优势自然也有不足之处,主要表现如下: 共享端共享媒体流的时候,需要给每一个参与人都转发一份媒体流,这样对上行带宽的占用很大。参与人越多,占用的带宽就越大。除此之外,对 CPU、Memory 等资源也是极大的考验。一般来说,客户端的机器资源、带宽资源往往是有限的,资源占用和参与人数是线性相关的。这样导致多人通信的规模非常有限,通过实践来看,这种方案在超过 4 个人时,就会有非常大的问题。 另一方面,在多人通信时,如果有部分人不能实现 NAT 穿越,但还想让这些人与其他人互通,就显得很麻烦,需要做出更多的可靠性设计。

MCU 方案

MCU 主要的处理逻辑是:接收每个共享端的音视频流,经过解码、与其他解码后的音视频进行混流、重新编码,之后再将混好的音视频流发送给房间里的所有人。

备注

MCU 技术在视频会议领域出现得非常早,目前技术也非常成熟,主要用在硬件视频会议领域。

https://img.zhaoweiguo.com/knowledge/images/jikes/webRTCs/multi-MCU1.png

MCU 处理逻辑图

MCU 的优势有:

1. 技术非常成熟,在硬件视频会议中应用非常广泛
2. 作为音视频网关,通过解码、再编码可以屏蔽不同编解码设备的差异化,
    满足更多客户的集成需求,提升用户体验和产品竞争力
3. 将多路视频混合成一路,所有参与人看到的是相同的画面,客户体验非常好

MCU 也有一些不足:

1. 重新解码、编码、混流,需要大量的运算,对 CPU 资源的消耗很大
2. 重新解码、编码、混流还会带来延迟
3. 由于机器资源耗费很大,所以 MCU 所提供的容量有限,一般十几路视频就是上限

SFU 方案

SFU 的优势:

1. 由于是数据包直接转发,不需要编码、解码,对 CPU 资源消耗很小
2. 直接转发也极大地降低了延迟,提高了实时性
3. 带来了很大的灵活性,能够更好地适应不同的网络状况和终端类型

SFU 和不足:

1. 由于是数据包直接转发,参与人观看多路视频的时候可能会出现不同步;
    相同的视频流,不同的参与人看到的画面也可能不一致。
2. 参与人同时观看多路视频,在多路视频窗口显示、渲染等会带来很多麻烦,
    尤其对多人实时通信进行录制,多路流也会带来很多回放的困难。
    总之,整体在通用性、一致性方面比较差。

备注

SFU 方案时,包括 Simulcast 模式和 SVC 模式

1. Simulcast 模式

备注

所谓 Simulcast 模式就是指视频的共享者可以同时向 SFU 发送多路不同分辨率的视频流(一般为三路,如 1080P、720P、360P)。而 SFU 可以将接收到的三路流根据各终端的情况而选择其中某一路发送出去。例如,由于 PC 端网络特别好,给 PC 端发送 1080P 分辨率的视频;而移动网络较差,就给 Phone 发送 360P 分辨率的视频。

https://img.zhaoweiguo.com/knowledge/images/jikes/webRTCs/SFU-Simulcast1.png

Simulcast 模式示意图:Simulcast 模式对移动端的终端类型非常有用,它可以灵活而又智能地适应不同的网络环境。

2. SVC 模式

备注

SVC 是可伸缩的视频编码模式。它在视频编码时将视频分成多层 —— 核心层、中间层和扩展层。上层依赖于底层,而且越上层越清晰,越底层越模糊。在带宽不好的情况下,可以只传输底层,即核心层,在带宽充足的情况下,可以将三层全部传输过去。

https://img.zhaoweiguo.com/knowledge/images/jikes/webRTCs/SFU-SVC1.png

SVC 模式示意图:PC1 共享的是一路视频流,编码使用 SVC 分为三层发送给 SFU。SFU 根据接收端的情况,发现 PC2 网络状况不错,于是将 0、1、2 三层都发给 PC2;发现 Phone 网络不好,则只将 0 层发给 Phone。这样就可以适应不同的网络环境和终端类型了。

25 | 那些常见的流媒体服务器, 你该选择谁

  • SFU 方案开源项目包括 Licode、Janus-gateway、MediaSoup、Medooze

Licode

  • Licode 是由 C++ 和 Node.js 语言实现。 * 媒体通信部分由 C++ 语言实现 * 而信令控制、用户管理、房间管理用 Node.js 实现

  • 源码地址为:https://github.com/lynckia/licode

Licode 既可以用作 SFU 类型的流媒体服务器,也可以用作 MCU 类型的流媒体服务器。一般情况下,它都被用于 SFU 类型的流媒体服务器。Licode 不仅仅是一个流媒体通信服务器,而且还是一个包括了媒体通信层、业务层、用户管理等功能的完整系统,并且该系统还支持分布式部署。

https://img.zhaoweiguo.com/knowledge/images/jikes/webRTCs/opensource-Licode1.png

Licode 架构图

Licode 从功能层面来讲分成三部分:

1. Nuve 是一个 Web 服务
  用于管理用户、房间、产生 token 以及房间的均衡负载等相关工作。
  它使用 MongoDB 存储房间和 token 信息,但不存储用户信息。
2. ErizoController,用于管理控制,信令和非音视频数据都通过它接收
  它通过消息队列与 Nuve 进行通信,
  也就是说 Nuve 可以通过消息队列对 ErizoController 进行控制。
3. ErizoAgent,用于音视频流媒体数据的传输,可以分布式布署。
  ErizoAgent 与 ErizoController 的通信也是通过消息队列,
  信令消息通过 ErizoController 接收到后,再通过消息队列给 ErizoAgent
  从而实现对 ErizoAgent 进行控制。

Janus-gateway

https://img.zhaoweiguo.com/knowledge/images/jikes/webRTCs/opensource-Janus1.png

Janus 架构图

Janus 整体架构采用了插件的方案,这种架构方案非常优秀,用户可以根据自己的需要非常方便地在上面编写自己的应用程序。而且它目前支持的功能非常多,比如支持 SIP、 RTSP、音视频文件播放、录制等等,所以在与其他系统的融合性上有非常大的优势。另外,它底层的代码是由 C 语言编写的,性能也非常强劲。Janus 的开发、部署手册也非常完善。但它的架构设计比较复杂,对于初学者来说难度较大。

MediaSoup

https://img.zhaoweiguo.com/knowledge/images/jikes/webRTCs/opensource-MediaSoup1.png

Mediasoup 架构图

它与 Janus 相比,它更聚焦于数据传输的实时性、高效性、简洁性。所以对于想学习 WebRTC 流媒体服务器源码的同学来说,Mediasoup 是一个非常不错的项目。

Medooze

  • 不仅支持 WebRTC 协议栈,还支持很多其他协议,如 RTP、RTMP 等

  • https://github.com/medooze/media-server

  • Medooze 的控制逻辑层是通过 Node.js 实现的

  • Medooze 也是 C++ 开发的流媒体服务务器

https://img.zhaoweiguo.com/knowledge/images/jikes/webRTCs/opensource-Medooze1.png

Medooze 架构图

Medooze 与 Mediasoup 相比,两者在核心层实现的功能都差不多,但 Medooze 的功能更强大,包括了录制、推 RTMP 流、播放 FLV 文件等相关的操作,而 Mediasoup 则没有这些功能。它在接收 / 发送音视频包时性能比 Mediasoup 要稍差一些。

26 | 为什么编译 Medooze Server 这么难

media-server-node

源码分析:

1. src 目录中存放的是 C++ 语言实现的 Native 代码
    用于生成 JavaScript 脚本可以调用的 C++ 接口,
    使 JS 编写的业务层代码可以调用 Medooze 核心层的 C++ 代码;
2. lib 目录里存放的是在 Node.js 端执行的
    控制 Medooze 业务逻辑的 JavaScript 代码;
3. external 目录中存放的是 Medooze 使用的第三方库,如 MP4v2 和 SRTP
4. media-server 目录是一个比较重要的目录
    它里面存放的是 Medooze 的核心代码,即 C++ 实现的流媒体服务器代码

node-gyp & GYP

  • node-gyp 是一个由 Node.js 执行的脚本程序,是专门用于生成在 Node.js 中运行的 C/C++ Native 插件的工具。可以简单地将 node-gyp 认为是 gyp 和 Make/Ninja 工具的集合

  • GYP(Generate Your Projects)是 Chromium 团队使用 Python 语言开发的构建工具,它以 .gyp 为输入文件,可以产生不同平台的 IDE 工程文件,如 VS 工程;或产生各种编译文件,如 Makefile 。

27-28 _ 让我们一起探索Medooze的具体实现吧

  • SFU 模型

  • 录制回放模型

  • 推流模型

29 | 如何使用 Medooze 实现多方视频会议

支持上万人同时在线的直播系统 (8 讲)

31 | 一对多直播系统 RTMP/HLS, 你该选哪个

备注

在线教育、音视频会议这类直播属于实时互动直播,主要考虑传输的实时性,因此一般使用 UDP 作为底层传输协议;而娱乐直播对实时性要求不高,更多关注的是画面的质量、音视频是否卡顿等问题,所以一般采用 TCP 作为传输协议。我们称前者为实时互动直播,后者为传统直播。

30讲之前都是介绍实时互动直播的,这儿讲解传统直播技术。传统直播技术使用的传输协议是 RTMP 和 HLS。RTMP 是由 Adobe 公司开发的,虽然不是国际标准,但也算是工业标准,在 PC 占有很大的市场;而 HLS 是由苹果公司开发的,主要用在它的 iOS 平台,不过 Android 3 以后的平台也是默认支持 HLS 协议的。

https://img.zhaoweiguo.com/knowledge/images/jikes/webRTCs/live-stream1.png

传统直播基本架构图:传统直播架构由直播客户端、信令服务器和 CDN 网络这三部分组成。主播客户端在分享自己的音视频媒体流之前,首先要向信令服务器发送 “创建房间” 的信令(红圈标出的步骤 1);信令服务器收到该信令后,给主播客户端返回一个推流地址(CDN 网络源站地址);此时,主播客户端就可以通过音视频设备进行音视频数据的采集和编码,生成 RTMP 消息,最终将媒体流推送给 CDN 网络(红圈标出的步骤 2)。步骤 3、步骤 4 是移动端的步骤,与步骤 1、步骤 2 是一致的。观众端想看某个房间里的节目时,首先也要向信令服务器发消息“加入房间”,也就是步骤 5;服务端收到该信令后,会根据用户所在地区,分配一个与它最接近的 “CDN 边缘节点”;观众客户端收到该地址后,就可以从该地址拉取媒体流了,即步骤 6。在传统直播系统中,一般推流都使用的 RTMP 协议,而拉流可以选择使用 RTMP 协议或者 HLS 协议。

直播客户端

主要包括音视频数据的采集、编码、推流、拉流、解码与播放这几个功能。

客户端按用途可分为两类:

1. 一类是主播使用的客户端,包括音视频数据采集、编码和推流功能;
2. 另一类是观众使用的客户端,包括拉流、解码与渲染(播放)功能。

观众端要实现的就是一个播放器功能,目前开源界有两个比较有名而又成熟的开源项目 Ijkplayer 和 VLC

信令服务器

主要用于接收信令,并根据信令处理一些和业务相关的逻辑,如创建房间、加入房间、离开房间、送礼物、文字聊天等。

备注

在开发直播系统的信令服务器时,一定要关注和防止消息的洪泛。

CDN 网络

主要用于媒体数据的分发。

https://img.zhaoweiguo.com/knowledge/images/jikes/webRTCs/CDN1.png

CDN 网络:CDN 网络的构造十分复杂(如下图所示),一般情况下,它先在各运营商内构建云服务,然后再将不同运营商的云服务通过光纤连接起来,从而实现跨运营商的全网 CDN 云服务。

主播想将自己的音视频共享出去的时候,首先通过直播系统的信令服务器获取到可以推送媒体流的 CDN 源节点。CDN 网络从源节点接收到媒体数据后,会主动向各个主干结点传送流媒体数据,这样主干结点就将媒体数据缓存起来了。当然这个缓冲区的大小是有限的,随着时间流逝,缓冲区中的数据也在不断更替中。观众想看某个主播的节目时,会从直播系统的信令服务器获取离自己最近的 CDN 边缘节点,然后到这个边缘节点去拉流。由于他是第一个在该节点拉流的用户,因此该 CDN 边缘节点还没有用户想到的媒体流,要向主干结点发送请求。主干结点收到请求后,从自己的缓冲区中取出数据流源源不断地发给边缘节点,这时边缘节点再将媒体数据发给观众。当第二个观众再次到该 CDN 边缘节点接流时,该节点发现该流已经在自己的缓存里了,就不再向主干结点请求,直接将媒体流下发下去了。

CDN里面的节点按功能分为 3 类:

1. 源节点,用于接收用户推送的媒体流。
2. 主干结点,起到媒体数据快速传递的作用,比如与其他运营商传送媒体流。
3. 过缘节点,用于用户来主动接流。
  一般边缘节点的数量众多,但机子的性能比较低,
  它会被布署到各地级市,主要解决网络最后一公里的问题。

RTMP

全称 Real Time Messaging Protocol ,即实时消息协议。但它实际上并不能做到真正的实时,一般情况最少都会有几秒到几十秒的延迟,底层是基于 TCP 协议的。RTMP 的传输格式为 RTMP Chunk Format,媒体流数据的传输和 RTMP 控制消息的传输都是基于此格式的。

备注

在使用 RTMP 协议传输数据之前,RTMP 也像 TCP 协议一样,先进行三次握手才能将连接建立起来。当 RTMP 连接建立起来后,你可以通过 RTMP 协议的控制消息为通信的双方设置传输窗口的大小(缓冲区大小)、传输数据块的大小等。

  1. 优势:

    1. RTMP 协议底层依赖于 TCP 协议,不会出现丢包、乱序等问题,
        因此音视频业务质量有很好的保障。
    2. 使用简单,技术成熟。
        有现成的 RTMP 协议库实现,如 FFmpeg 项目中的 librtmp 库,方便。
        而且 RTMP 协议在直播领域应用多年,技术已经相当成熟。
    3. 市场占有率高。
        在日常的工作或生活中,我们或多或少都会用到 RTMP 协议。
        如常用的 FLV 文件,就是在 RTMP 消息数据的最前面加了 FLV 文件头。
    4. 相较于 HLS 协议,它的实时性要高很多。
    
  2. 劣势:

    1. 苹果公司的 iOS 不支持 RTMP 协议
        按苹果官方的说法, RTMP 协议在安全方面有重要缺陷。
    2. 在苹果的公司的压力下,Adobe 已经停止对 RTMP 协议的更新了。
    3. 不支持 h265
    

RTMP 协议已经失去了未来,只是由于目前没有更好的协议可以直接代替它,所以它还能 “苟延残喘” 存活几年。但它最终一定会消亡,这是毋庸置疑的。

HLS

全称 HTTP Live Streaming,是苹果公司实现的基于 HTTP 的流媒体传输协议。它可以支持流媒体的直播和点播,主要应用在 iOS 系统和 HTML5 网页播放器中。

备注

HLS 的基本原理非常简单,它是将多媒体文件或直接流进行切片,形成一堆的 ts 文件和 m3u8 索引文件并保存到磁盘。当播放器获取 HLS 流时,它首先根据时间戳,通过 HTTP 服务,从 m3u8 索引文件获取最新的 ts 视频文件切片地址,然后再通过 HTTP 协议将它们下载并缓存起来。当播放器播放 HLS 流时,播放线程会从缓冲区中读出数据并进行播放。

HLS 协议的本质就是通过 HTTP 下载文件,然后将下载的切片缓存起来。由于切片文件都非常小,所以可以实现边下载边播的效果。HLS 规范规定,播放器至少下载一个 ts 切片才能播放,所以 HLS 理论上至少会有一个切片的延迟。

  1. 优势:

    1. HLS 使用的是 HTTP 协议传输数据
        RTMP 协议没使用标准的 HTTP 接口传输数据,
          在一些有访问限制的网络环境下,比如企业网防火墙,是没法访问外网的,
          因为企业内部一般只允许 80/443 端口可以访问外网。
        HLS 协议天然就解决了这个问题。
    2. HLS 协议本身实现了码率自适应,
        不同带宽的设备可以自动切换到最适合自己码率的视频进行播放。
    3. 浏览器天然支持 HLS 协议
        而 RTMP 协议需要安装 Flash 插件才能播放 RTMP 流。
    
  2. 不足:

    HLS 最主要的问题就是实时性差。
      由于 HLS 往往采用 10s 的切片,所以最小也要有 10s 的延迟,
      一般是 20~30s 的延迟,有时甚至更差。
    

HLS 之所以能达到 20~30s 的延迟,主要是由于 HLS 的实现机制造成的。HLS 使用的是 HTTP 短连接,且 HTTP 是基于 TCP 的,所以这就意味着 HLS 需要不断地与服务器建立连接。TCP 每次建立连接时都要进行三次握手,而断开连接时,也要进行四次挥手,基于以上这些复杂的原因,就造成了 HLS 延迟比较久的局面。

备注

以 WebRTC 为代表的实时直播系统必然会成为未来的主流。另一方面,随着 5G 的落地与推广,带宽问题会得到极大的解决,因此人们在享受实时性、互动性便利的同时,音视频服务质量也会得到极大的改善,这将加速传统的基于 RTMP /HLS 的直播技术的淘汰。因为在大负载方面,使用 CDN 技术的传统直播目前还有一定优势,所以短期内可以考虑 WebRTC 的实时直播技术与使用 RTMP 协议为代表的传统直播技术相结合的方案,既可以满足用户对于实时性、互动性的需求,又可以满足大负载的需求,这也是各大厂积极推动的一套方案。

32 | HLS: 实现一对多直播系统的必备协议

https://img.zhaoweiguo.com/knowledge/images/jikes/webRTCs/HLS1.png

HLS 直播架构图:客户端采集媒体数据后,通过 RTMP 协议将音视频流推送给 CDN 网络的源节点(接入节点)。源节点收到音视频流后,再通过 Convert 服务器将 RTMP 流切割为 HLS 切片文件,即 .ts 文件。同时生成与之对应的 m3u8 文件,即 HLS 播放列表文件。切割后的 HLS 分片文件(.ts 文件)和 HLS 列表文件(.m3u8 文件)经 CDN 网络转发后,客户端就可以从离自己最近的 CDN 边缘节点拉取 HLS 媒体流了。在拉取 HLS 媒体流时,客户端首先通过 HLS 协议将 m3u8 索引文件下载下来,然后按索引文件中的顺序,将 .ts 文件一片一片下载下来,然后一边播放一边缓冲。

对于使用 HLS 协议的直播系统来说,最重要的一步就是切片。源节点服务器收到音视频流后,先要数据缓冲起来,保证到达帧的所有分片都已收到之后,才会将它们切片成 TS 流。

m3u8 格式

m3u8 格式分析:

#EXTM3U
#EXT-X-VERSION:3         // 版本信息
#EXT-X-TARGETDURATION:11 // 每个分片的目标时长
#EXT-X-MEDIA-SEQUENCE:0  // 分片起始编号
#EXTINF:10.922578,       // 分片实际时长
test000.ts               // 分片文件
#EXTINF:9.929578,        // 第二个分片实际时长
test001.ts               // 第二个分片文件
...

备注

RFC8216 规定,.m3u8 文件内容以#字母开头的行是注释和 TAG,其中 TAG 必须是#EXT 开头

TS 格式

TS 流最早应用于数字电视领域,其格式非常复杂,包含的配置信息表多达十几个。TS 流中的视频格式是 MPEG2 TS ,格式标准是在 ISO-IEC 13818-1 中定义的。苹果推出的 HLS 协议对 MPEG2 规范中的 TS 流做了精减,只保留了两个最基本的配置表 PAT 和 PMT,再加上音视频数据流就形成了现在的 HLS 协议。也就是说, HLS 协议是由 PAT + PMT + TS 数据流组成的。其中,TS 数据中的视频数据采用 H264 编码,而音频数据采用 AAC/MP3 编码。T

https://img.zhaoweiguo.com/knowledge/images/jikes/webRTCs/TS1.png

TS 数据流示意图:TS 数据流由 TS Header 和 TS Payload 组成。其中,TS Header 占 4 字节,TS Payload 占 184 字节,即 TS 数据流总长度是 188 字节。

https://img.zhaoweiguo.com/knowledge/images/jikes/webRTCs/TS2.png

TS 文件格式图:TS Payload 又由 PES Header 和 PES Payload 组成。其中,PES Payload 是真正的音视频流,也称为 ES 流。1. PES(Packet Elementary Stream)是将 ES 流增加 PES Header 后形成的数据包。2. ES(Elementary Stream),中文可以翻译成基流,是编码后的音视频数据。

https://img.zhaoweiguo.com/knowledge/images/jikes/webRTCs/TS3.png

PES 结构图:PES Packet 作为 TS 数据流的 Payload,也有自己的 Header

33 | FLV: 适合录制的多媒体格式

FLV 文件是一个流式的文件格式。FLV 文件相较于其他多媒体文件特别适合于在录制中使用。FLV 与 RTMP 协议的关系十分密切,在 RTMP 数据之上加个 FLV 头就成了 FLV 文件。

34 | 如何使用 Nginx 搭建最简单的直播服务器

  • 开源 RTMP 流媒体服务器:SRS,github 地址:https://github.com/ossrs/srs

  • SRS/nginx 是用于媒体分发的,是通过延迟换的服务质量,平均延迟是 3 秒左右;而 medooze 的目标是低延迟,注重的是实时性,延迟在测 500ms 以内。

35 | 如何构建云端一对多直播系统

  • 推流工具有 FFmpeg、OBS、自己通过 librtmp 库实现的推流客户端等

  • 拉流工具包括 VLC、FFplay、Flash、flv.js 、video.js

36 _ 如何使用 flv.js 播放 FLV 多媒体文件呢

flv.js 是由 bilibili 公司开源的项目。它可以解析 FLV 文件,从中取出音视频数据并转成 BMFF 片段(一种 MP4 格式),然后交给 HTML5 的 <video> 标签进行播放。通过这种方式,使得浏览器在不借助 Flash 的情况下也可以播放 FLV 文件了。

37 _ 如何使用 video.js 播放多媒体文件

video.js 对音量控制、进度条、菜单等 UI 相关逻辑做了统一处理,对媒体播放部分设计了一个插件框架,可以集成不同媒体格式的播放器进去。所以相比flv.js而言,video.js 更像是一款完整的播放器。

其他

RTSP 协议主要用的监控系统中,RTSP 用于信令控制,直正的数据传输还是用的 UDP/RTP,除了监控系统基本上没有其它行业使用该协议。

zoom 是 Zoom 公司开发的一款直播软件,它底层也用的 地 UDP 协议,他的老板袁征以前是 Webex 的高管。 Webex 是第一家在美国上市的,专门做音视频会议的公司。创建于 1996 年,2000 年左右在美国上市,后 2007 年被 cisco 公司收购。Webex 出走的人很多都创业做音视频相关的事情,像国内的 声网都是 Webex 的人创建的。

主页

索引

模块索引

搜索页面