前端应该了解的直播知识

在移动互联网时代,涌现了一大波视频直播平台,例如以淘宝、京东为代表的电商直播,以抖音、快手为代表的娱乐互动直播,以斗鱼、YY为代表的游戏直播,以猿辅导、作业帮为代表的教育直播……

无论是哪种形式的直播,对性能和交互体验的要求都极高。在技术选型上,采用native来落地直播终端也成了业内的默认选择。

来作业帮后也跟同事交流中,得知之前虽然也基于web实现过直播产品,但确实存在较大的性能问题,且出现问题后,由于没有日志,排查起来非常困难。

所以在直播这个领域,看起来确实没前端啥事。不过,在一些简单的场景下,web端直播还是有一定的应用空间的。例如端到端的音视频通话、简单的拉流播放场景。况且,身在一家有直播业务的公司,别人问起时,总也应该对直播能说上个七七八八。既然如此,那我们就一块儿看看直播是咋玩儿的吧。

直播架构

如图所示,一个直播平台包括三个必要部分:推流端、流媒体服务器和拉流端。推流端通过摄像头、麦克风等设备采集音视频数据后推送到流媒体服务器。流媒体服务器将收到的音视频流进行必要的处理后,将视频流传输到拉流端进行播放。

值得注意的是,在实际的应用场景下,为了保证高并发、低延迟和良好的互动体验,往往采用CDN加速。由流媒体源服务器将视频流分发至各级CDN节点,用户就近访问CDN节点获取视频流。

另一方面,底层的流媒体服务很简单,为了满足运营侧在业务层面各种花式玩法,如红包雨、实时讨论、实时弹幕等往往需要在流媒体服务之上进行业务层服务的整合。

采集

推流端第一步是进行视频的采集。视频的采集分为图像采集和音频采集。

图像的采集主要由摄像头等设备拍摄成 YUV 编码的原始数据。图像可以进行采集的源头一般有三种:摄像头、屏幕录制、本地视频文件。

音频的采集主要通过设备将环境中的模拟信号采集成 PCM 编码的原始数据。与图像的采集类似,音频也可以分别从麦克风、系统声音、本地音频文件中采集数据。

预处理

预处理基本成了直播领域的核心诉求了。常见的预处理功能有美颜、水印、滤镜、混音、降噪、特效等。以美颜为例,用户对美颜的有着强烈需求。借用直播从业者的一句话:“80%的主播没有美颜根本没法儿看!”

美颜的实现原理主要是通过「磨皮+美白」来达到整体美颜的效果。专业术语叫「去噪」,即对图像中的噪点进行去除或者模糊化处理。常见的去噪算法有均值模糊、高斯模糊和中值滤波等。由于脸部的每个部位不尽相同,脸上的雀斑可能呈现出眼睛黑点的样子,在对整张图像进行「去噪」处理的时候不能将眼睛也去掉,这个环节中还会涉及到人脸和皮肤检测技术。

视频编码

对原始视频数据进行预处理后,还需要对视频进行编码。编码简单理解就是压缩。因为原始数据非常大,一个时长15分钟的1080p视频,体积就可达到1.24G。直接进行推流的话,效率太低。

现在比较常用的视频编码的方式是H.264,比较常用的音频编码方式是AAC。

除了H.264外,也出现了H.265、VP9、AV1等新一代的编码方式。H.265号称可以在维持画质基本不变的情况下,让数据传输带宽减少至H.264的一半,但目前影响最大、使用最多的还是H.264标准。

视频封装

视频封装就是将所有的处理好的视频、音频或字幕都包装到一个文件容器内呈现给观众,这个包装的过程就叫封装。

为啥要封装?

主要是为了解决同步问题。如果视频中包含音频的话会变得很复杂,需要通过封装的方式给他们打上时间戳,让音频和视频能同步起来,声音对上嘴型。

有哪些封装方式?

视频的封装方式有很多种,像FLV,TS,MP4, MOV, AVI, WMV, MKV等。但在直播平台中,最常用的是FLV和TS。

推流

推流也就是将封装好的视频流传输到流媒体服务器。对于我们来说,需要了解推拉流过程中用到的三种传输协议:rtmp、http-flv和hls。一般情况下,上行推流时,使用rtmp。拉流时视情况采用不同的协议。可以通过下表来认识三种协议之间的不同:

流媒体服务器

流媒体服务器端提供的最核心功能是收集推流端的视频推流,并将其推送给所有观众端。

除此之外,要想适配各终端和平台,服务端还需要对流进行转码,如支持RTMP、HLS、FLV等格式拉流,支持一路转多路适配不同网络和分辨率的终端设备。

另外,为了安全考虑,直播鉴黄也是必不可少的功能。一般可以通过对视频进行截图,然后对图片内容进行分析,根据结果来控制视频流。

常见的流媒体服务器有:SRS、nginx-rtmp、red5等。搭建一个流媒体服务器并不复杂,基于nginx和它的rtmp扩展就可以实现。

在实际场景下,为了高并发和低延迟,流媒体服务源服务器并不直接处理用户请求,而是将视频流分发到遍布世界各地的各级CDN节点。最终由末端的CDN节点来相应用户的请求。

拉流播放

播放端核心功能是去流媒体服务器拉流,选择适合的播放器进行解码播放。对移动端的播放器组件不熟,这里重点说下前端怎么做。

hls协议传输的视频文件是.ts格式的,浏览器video标签可以直接进行播放。如果播放端使用的是hls协议拉流,播放比较简单。针对部分pc下Chrome浏览器不支持hls的情况,可以使用hls.js插件来兼容。

由于http-flv和rtmp这两种协议传输的视频流是.flv格式,浏览器video标签是不能直接播放的。如果播放端使用的http-flv和rtmp进行拉流,可以使用video.js插件来播放。

demo

讲完了直播的核心流程,来做一个简单的demo。

  • 推流端,可以在网上随便找一个视频文件作为视频流数据源。然后使用ffmpeg来推流。

  • 流媒体服务器,使用nginx和rtmp扩展模块来实现,同时支持rtmp和hls协议拉流。

  • 播放端,针对hls协议使用video标签直接播放,针对rtmp协议,使用video.js进行播放。

关于nginx和rtmp模块的安装,假定你已经弄好了,这里不展开去说了。

1)编辑nginx的配置文件,添加如下内容:

http {
    location /hls {
        # Serve HLS fragments
        types {
            application/vnd.apple.mpegurl m3u8;
        }
        root /tmp;
        add_header Cache-Control no-cache;
        # To avoid issues with cross-domain HTTP requests (e.g. during development)
        add_header Access-Control-Allow-Origin *;
    }
}
rtmp {
    server {
        listen 1935;
        ping 30s;
        notify_method get;

        application myapp {
            live on;
            # 启用hls拉流
            hls on;
            # m3u8和ts文件的存储目录
            hls_path /tmp/hls;
            # ts文件切片大小
            hls_fragment 5s;
        }
    }
}

2)检查配置文件,然后重启nginx。

3)推流工具这里使用ffmpeg。关于工具的安装,请按照官方文档进行自行解决,这里不展开说明。在终端执行如下命令进行推流:

ffmpeg -re -i /path/to/your/video.mp4 -c copy -f flv -flvflags no_duration_filesize rtmp://your_ip:1935/myapp/mystream
  • -re : 表示使用文件的原始帧率进行读取,因为ffmpeg读取视频帧的速度很快,如果不使用这个参数,ffmpeg可以在很短时间就把video.mp4中的视频帧全部读取完并进行推流,这样就无法体现出视频播放的效果了

  • -i :这个参数表示输入 ,后面 /path/to/your/video.mp4 就是输入文件

  • -vcodec copy : -vcodec表示使用的视频编解码器 ,前缀v表示video。后面紧跟的copy 表示复制使用源文件的视频编解码器,比如原文件的编解码器(codec)是h264,则这里就使用h264。

  • -acodec copy : -acodec表示使用的音频编解码器,前缀a表示audio。后面的copy 表示使用源文件的音频编解码器。

  • -f flv : -f表示format ,就是强制输出格式为flv,这一步其实也叫封装(mux),封装要做的事就是把视频和音频混合在一起,进行同步。紧跟在后面的 rtmp://your_ip:1935/myapp/mystream 表示输出的"文件名",这个文件名可以是一个本地的文件,也可以指定为rtmp流媒体地址。指定为rtmp流媒体地址后,则ffmpeg就可以进行推流。

4)写一个简单的HTML文件,代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>直播demo</title>
</head>
<body>
    <video src="http://your_ip:8080/hls/mystream.m3u8" autoplay controls></video>
</body>
</html>

5)在浏览器中访问该文件,就可以看到直播效果了。

前文已经介绍,由于Chrome浏览器不支持hls协议,请使用Safari浏览器进行体验。demo为了省事儿,没添加hls.js进行兼容,大家可以自行兼容。

rtmp协议的直播也比较简单,大家使用video.js来实现,这里不再赘述。提示,rtmp协议的拉流地址为:rtmp://your_ip:1935/myapp/mystream

注意,需要开始推流后再访问页面才可以看到直播画面。因为未开始推流前,文件mystream.m3u8还没生成。

总结

以上就是本次分享的全部内容,总结一下有四点:

  • 核心流程为:采集、预处理、编码、封装、推流、流媒体服务、分发、拉流、解码、播放

  • 常见直播协议有:RTMP、HTTP-FLV、HLS

  • 常见封装格式有:FLV、TS

  • 常见编码格式有:H.264、H.265、VP9、AV1

希望大家有所收获~

推荐阅读

好文我在看????


版权声明:本文为weixin_48109878原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。