阅读 1072

直播架构与流程与H5直播项目落地

直播发展历程和直播场景

  • 直播发展历程:从PC端直播开始,到浏览器PC端,再到移动端,再到现在的浏览器H5端,可以说是随着技术的发展而进化过来的。

直播形式也越来越多,从yy中的唱歌跳舞到游戏直播再到现在的秀场直播带货。

直播架构与流程

  • 直播架构:两端一服(推流端、拉流端、流媒体服务器)

在整个直播过程中,流贯穿始终,直播过程其实就是音视频流传输和转换的过程

  • 直播流程:音视频录制->音视频处理->音视频编码->推流->流媒体服务器->cdn分发->解码->流播放

下面对各个流程逐一解释:

  • 音频采集:通过设备将环境中的模拟信号采集成PCM编码的原始数据,然后编码压缩成MP3、 ACC、OGG等压缩格式分发出去。
  • 视频采集:视频的本质其实就是一连串的图片进行连续播放。图像的采集过程主要由摄像头等设备拍摄成 YUV 编码的原始数据,然后经过编码压缩成 H.264、MP4、FLV等格式的数据分发出去。采集方式有摄像头采集、录屏、直接推文件流。
  • 音视频处理:在音视频采集完成后,为了增加一些额外效果,一般会在编码压缩前进行处理,美颜、水印、声音特效等。
  • 编码和封装

视频编码是直播过程非常重要的一部分,对于流媒体传输来说,编码速度、编码压缩比会直接影响流媒体传输的效率。比如使用H.264编解码器进行编码的视频源数据可以从几百M压缩至几百k。压缩原理就是去除冗余信息:

  1. 空间冗余:图像相邻元素之间有关联规律。
  2. 时间冗余:相邻图像内容相似。
  3. 视觉冗余:人对某些细节不敏感,就可以进行压缩。
  4. 知识冗余:规律性的进行预判压缩(依照先前的图像内容)。

视频封装是在视频编码后对视频的存储,也可以理解为容器,它也为流媒体数据提供索引,直播中通常使用FLV格式和MPEG2-TS格式(简称TS格式)

  • 直播推拉流与推拉流协议
  1. RTMP(Real Time Messaging Protocol):RTMP 是实时消息传输协议的首字母缩写。基于TCP,现属于Adobe,这是一种用来进行实时数据传输的网络协议,主要用来在Flash平台和支持该协议的流媒体服务器间进行音视频传输和数据通信,是目前主流的流媒体传输协议。支持双端(推流端和拉流端)。协议特点:
  • 延迟低,1-2s;
  • 依赖flash,不支持H5
  1. HLS(HTTP Live Streaming):由苹果公司提出的流媒体传输协议,属于拉流协议,协议特点:
  • 对H5支持度高,兼容性好,PC端仅支持Safari;
  • 编码格式为H.264 + ACC;
  • 延迟高(20s左右);为什么延迟高?因为要等数据。
  • 缩短TS文件间隔和切片数量可以降低延迟,但是要考虑高频率的TS资源请求对服务器带来的压力,所以hls的优化需要找到平衡点,调整好分片的策略,在保证性能的同时达到延迟的平衡。切片好的ts文件长这样。 截屏2019-12-2113.15.27
  1. HTTP-FLV(Flash Video):这也是Adobe公司推出的,http+flv就是推流端将音视频数据封装成flv的格式,通过HTTP协议传输给客户端。特点:
  • 延迟低,可达到2s左右,不支持IOS9及以下;
  • 编码格式H.264+ACC;
  • 由于H5不支持Flash,需要使用Bilbli开源的js库flv.js,通过MSE封装成fMP4再喂给video;
  • 可行性方案:采用HTTP-FLV协议需要使用降级方案,并且需要引入flv.js,167kb,端内外各环境需要进行测试是否有兼容性问题。

MSE:就是video本不支持我们对视频流进行操作,MSE的出现,使我们可以对视频流进行操作。那么他是如何操作的。

他会把video的src替换成MediaSource对象和多个buffer对象。如果没有精确的控制时间、媒体质量和内存释放等需求,使用video和source标签是一个更加简单但够用的方案。但是IOS中MSE基本废掉,也就导致了flv.js对ios的兼容性变差。

可以看到源码里调用了几个MSE的API

H5直播项目落地实现

整体结构:最基础的也是最核心的包括两块,推拉流和长连接,也就是实时通信。

  • 直播间实时通信的实现 — WebSocket

通常我们想要和服务端进行实时的进行通信,有一种简单的方式就是轮询,但是高频率的请求,服务端压力较大,但是WebSocket可以解决这个问题, 它可以在单个TPC连接上进行全双工通信,也就是服务端和客户端可以相互推送数据,从而实现实时通信。

  • 但是仅依赖长连接这一次连接是不行的,因为理论上会一直保持连接的,但是类似断网、连接超时、进程杀死等情况,是不会自动检测到连接断开的,这个连接就会断开。
  • 于是就有了心跳机制,客户端需要告诉服务端我们在线,能接收到消息,这个俗称ping,服务端也要告诉客户端他在线,能接收消息,这个俗称pong
  • 长连接保活策略:
  1. 启动心跳定时器,每隔10秒发送一次消息,也就是ping
  2. ws.onopen() 时开启setInterval定时器,每隔一秒检测是否超过30秒未收到消息,如果超过,判断连接状态,如果断开,则重连
  3. 兜底策略,如果长连接多次连接失败,则启动ajax,并持续尝试长连接
let ws = new WebSocket(url);
// 连接成功
  ws.onopen = () => {
    loopCheckValid();
  }
// 接收到消息
  ws.onmessage = () => {
   this.receiveTime =Date.now()
  }
//  连接关闭
  ws.onclose = () => {
    reconnect();
  }
// 连接失败
  ws.onerror = () => {
    reconnect();
  }
  
  loop() {
    this.loopTimer = setInterval(() => {
      if (Date.now() - this.receiveTime >= 30) {
        handle();
      }
    }, 1000);
  }

复制代码
  • 另外一种策略
  1. 客户端每隔一段时间发生一个ping给服务器
  2. 客户端发包时启动定时器
  3. 服务器端接收到ping,会回应一个pong
  4. 如果客户端收到服务器的png,则说明连接正常,删除定时器
  5. 如果客户端的定时器超时,依然没有收到pong,则说明连接断了,进行重连

其他相关

其他直播场景还有例如连麦直播,使用webrtc这种,还有微信小程序中做直播,微信小程序也可以实现连麦直播,但是要受限于微信小程序的支持能力。

对于传播效果来说,其实最好的还是用H5直播,对于其他场景的投放,就省去了重复开发的成本。

文章分类
前端
文章标签