大家好,我是编程小6,很高兴遇见你,有问题可以及时留言哦。
大前端这几年算是一个热词,对于前段来说如果不是大前端,技术相对来说就已经算是落后了。如果还停留在对ES6
,Vue
这些基本技能的学习只能说处于一个及格线。
如果想做的卓越必须必备另一些大前端技能,比如说NodeJS
,express.js
,koaJs
服务类,或者three.js
这类3d
数据图像,还有二维图像处理,比如d3
,raphael
,echart
, 最后hls
,flv
视频行业。
如果只会ES6
,Vue
,React
,Webpack
这只能算是前端,大前端是至少要掌握上面的一项技能的。这篇文章就是介绍大前端领域中的视频直播。
本文主要讲述的是H5
前端部分,视频音频采集部分后面会但开篇章来讲。首先带领大家快速实现一个直播系统,然后再讲解其中的重要概念,话不多说,直接开撸。
这里首先讲述mac系统的操作方法,windows
系统安装方式在下面。需要的工具我已经传到的github
上,可以自行下载。git地址
server
是推流工具,tools
里面有下面需要安装的工具。
首先需要安装YASM
,如果没有安装yasm
的话,会报FFmpeg yasm/nasm not found or too old. Use --disable-yasm for a crippledbuild
这个问题,如果没有安装sdl
的话,安装完FFmpeg
之后,bin
目录下没有ffplay
这个文件。
安装yasm
yasm;
# 可以在h5live中找到yasm
cd /h5live/tools/yasm-1.3.0
# 配置
./configure
# 编译 & 安装
make
sudo make install
安装sdl
sdl;
# 切可以在h5live中找到sdl目录
cd /h5live/tools/SDL2-2.0.8
# 配置
./configure
# 编译 & 安装
make -j 16
sudo make install
安装ffmpeg
ffmpeg;
# 切可以在h5live中找到ffmpeg,prefix为要安装到的位置
cd /h5live/tools/ffmpeg-4.3
# 配置
./configure --prefix=/usr/local/ffmpeg --enable-debug=3 --enable-shared --disable-static
# 编译 & 安装
make -j 4
sudo make install
设置ffmpeg
软连接, 相当于环境变量,目的是为了在任何目录都可以使用ffmpeg
命令,/usr/local/ffmpeg-4.3/ffmpeg
是安装的路径
ln -s /usr/local/ffmpeg-4.3/ffmpeg /usr/local/bin/ffmpeg
FFmpeg
程序进行各种媒体格式的转换,使得它们可以在不同设备上播放。该程序只有命令行模式,因此将它安装到计算机中看上去有点麻烦,但是只要根据本指南的方法,你只需要几分钟就可以将FFmpeg
安装成功!
下载ffmpeg
:
访问下载页面时,你将看到很多不同下载选项。你可以根据自己的操作系统选择下载最新的32位或64位静态程序版本。
安装:
点击开始菜单,然后点击计算机。选择安装Windows
系统的磁盘(一般是C:
)。在C:
盘的根目录下(该目录下有名为Windows
和Program Files
文件夹),右击并在弹出菜单中选择新建文件夹。将新文件夹命名为ffmpeg
。将下载的ffmpeg
压缩包解压到这个文件夹中。
在环境变量中加入ffmpeg
的启动命令,c:\ffmpeg\bin
, 俗称配置环境变量。
打开命令提示符窗口,输入命令ffmpeg –version
。如果命令提示窗口返回FFmpeg
的版本信息,那么就说明安装成功了,你可以在命令提示行中任意文件夹下运行FFmpeg
。
如果你收到libstdc++ -6 is missing
的错误消息,那么你可能需要安装Microsoft Visual C++ Redistributable Package
,该软件包可以在微软网站免费获取。
很简单,进入从github
中获取到的h5live
中server
所在的目录,运行server
程序即可。
cd /h5live/server
open server
可以看到这里提供了三种协议的路径,分别是rtmp
协议的1935
接口,http-flv
协议的7001
端口和hls
的7002
端口。
找一个mp4
格式的视频文件,假设这个文件叫1.mp4
,可以在1.map
所在的文件夹下执行下面的命令。
ffmpeg -re -i 1.mp4 -c copy -f flv rtmp://127.0.0.1:1935/live/movie
出现下图的效果就表示1.MP4
这个视频开始进行流推送了。
上面已经说了server
工具提供三种协议的视频流,分别是rtmp
,http-flv
以及hls
。
可以使用VLC
播放器验证rtmp
协议的视频流。
在里面粘贴入rtmp://127.0.0.1:1935/live/movie
然后就可以看到直播的效果了。
下载VLC
播放器:
Mac OS X
Windows
hls
协议的流媒体可以使用Safari
浏览器直接打开观看。可以直接把http://127.0.0.1:7002/live/movie.m3u8
放到Safari
浏览器的地址栏中查看效果。
至此推流就做完了,在H5
的直播开发中,这些工作都是服务器,之所以演示这些是为了在实际的开发中可以懂得直播的过程,可以快速的给出直播的解决方案。最主要的在服务还没有开发完成之前可以通过这样的方式快速搭建一个推流系统,前端先开发起来。
# RTMP,可以使用VLC播放器
rtmp://127.0.0.1:1935/live/movie
# FLV
# HLS 可以使用Safari浏览器访问
http://127.0.0.1:7002/live/movie.m3u8
这里才是前端真正需要关心的部分,主要介绍如何用js
去写一个直播的播放器,选择一些已有的最佳实践是最稳妥的,这样可以快速的满足业务需求,这里会介绍三款播放器,以及他们的使用。同样这些代码我也传到了github
上。
video.js是国外比较流行的视频框架,他的特长是做了非常好的自定义ui,符合线上成品的场景,除了自定义ui
,还提供了很多插件,比如弹幕,快捷键,hls
支持等等。他是一个比较完整的js
框架,点播、直播都很合适,缺点是文件较大。
hls.js适合做hls
协议的一款小巧的框架,同样也是点播直播都可以。缺点是需要自己书写UI样式。video.js
可以支持hls也是因为插件是基于hls.js
flv.js是B
站开源的flv
格式的播放器,如果是http-flv
协议的直播用它是非常合适的。
至于rtmp
在H5
的直播中是不常用的,所以这里就不讲了。
在github
找到videojs, 可以在这个网址中找到下面的两个文件,下载下来放在本地。
在Video.js
的插件文档中存在大量的插件,可以从中找到自己需要的。https://videojs.com/plugins/
videojs-contrib-hls
是一个支持hls
直播的video
插件。找到cdn
, 将js
保存到本地。使用方式很简单,只需要把插件的js
引入进来就可以了。
将video.min.js
和videojs-contrib-hls.js
以及video-js.min.css
引入到页面中,source
标签的地址写上hls
的m3u8
后缀地址。就可以了。
注意这里需要在服务器环境查看。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="video-js.min.css">
</head>
<body>
<video id=example-video width=600 height=300 class="video-js vjs-default-skin" controls>
<source src="http://127.0.0.1:7002/live/movie.m3u8" type="application/x-mpegURL">
</video>
<script src="video.min.js"></script>
<script src="videojs-contrib-hls.js"></script>
<script> var player = videojs('example-video'); player.play(); </script>
</body>
</html>
可以看到videojs
帮处理好了ui
问题。是一款可以快速使用矿建。
需要下载对应hls
代码,可以去github
中寻找,https://github.com/video-dev/hls.js
。
使用方式也很简单,因为hls.js
并没有为提供UI
样式,所以只需要引入js
即可。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<video id="video" controls width="400" height="300"></video>
<script src="hls.js"></script>
<script> var video = document.getElementById('video'); var videoSrc = 'http://127.0.0.1:7002/live/movie.m3u8'; if (Hls.isSupported()) { var hls = new Hls(); hls.loadSource(videoSrc); hls.attachMedia(video); } else if (video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoSrc; } </script>
</body>
</html>
flv.js
是B
站开源的一款flv
播放器,可以说是国人的骄傲,同样使用起来非常简单。也是引入flv.js
。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="flv.js"></script>
<video id="videoElement" controls width="400" height="300"></video>
<script> if (flvjs.isSupported()) { var videoElement = document.getElementById('videoElement'); var flvPlayer = flvjs.createPlayer({ type: 'flv', url: 'http://127.0.0.1:7001/live/movie.flv' }); flvPlayer.attachMediaElement(videoElement); flvPlayer.load(); flvPlayer.play(); } </script>
</body>
</html>
这里讲述的是小程序的直播,默认我这里认为大家是有小程序开发经验的,所以如何创建小程序,安装开发者工具,调试等内容就不说了。
微信小程序直播使用的是媒体组件的live-player
,并且他仅支持flv
或者rtmp
格式,这一点在前后端确认技术方案时尤为重要。还有就是他只针对对应行业开放。可以查看这里连接https://developers.weixin.qq.com/miniprogram/dev/component/live-player.html
符合上述类目的小程序开放,需要先通过类目审核,再在小程序管理后台,「开发
」-「接口设置
」中自助开通该组件权限。
打开这个权限之后,就可以使用小程序的live-player
组件进行直播开发了。他的使用也非常简单。
<live-player src="https://domain/pull_stream" mode="RTC" autoplay bindstatechange="statechange" binderror="error" style="width: 300px; height: 225px;" />
Page({
statechange(e) {
console.log('live-player code:', e.detail.code)
},
error(e) {
console.error('live-player error:', e.detail.errMsg)
}
})
这里需要注意的是,开发者工具不能进行直播调试,只能使用远程调试。连接手机查看效果。live-player
默认宽度300px
、高度225px
,可通过wxss
设置宽高。
至此H5
和小程序的直播开发就说完了,以上内容已经足够大家完成工作中的直播开发任务和可能出现的直播业务了。
接着会介绍一下直播的流程、协议以及基于nginx
搭建一个直播服务。后面的内容偏理论和服务。和前端关系不大可以跳过。
对于一个直播流程来说首先是视频音频等媒体的采集,一般采集方有三种,PC端
,安卓端
以及IOS端
,他们的工作也都是依赖摄像头
和麦克风
的。一般直播的人会选择购买专业的摄像头和麦克风。这里收集到的数据是流的格式,也就是二进制的数据,这里的数据会经过socket
或者http
上传至服务器。
信息源采集之后第一个步骤是进行编码,因为采集到的原始流是不能直接被客户端进行播放的,必须采用一定的协议去做编码,一般视频编码采用H.264
,音频编码一般是AAC
。这两种是直播行业最常见的编码格式。
编码之后一般可能会伴随着字幕的叠加,当然这个是不必须的是一个可有可无的过程。这里要说的其实是对视频的一些处理,可能添加水印之类的二次加工。
视频和音频处理之后就要进行推流,也就是把视频和音频推送到服务器中,也就是上面使用ffmpeg
将1.mp4
推送的过程。
工作中服务器会将推送过来的流媒体经过部署再把资源推到CDN
上,一般静态的资源或者多媒体资源都会发布到CDN
来保证用户体验和拉取的速度。
对于客户端来说是直接访问CDN
的地址的,同样这里的客户端可能是PC
,安卓
或者IOS
的播放器。
以上就是一个简单的直播处理过程。
一般常见的视频格式是mp4
,他的兼容性非常好,谷歌,火狐,苹果,IE等浏览器都是支持的。webm
是一种流式的视频格式,常见于youtube
网站,但是这种格式只有谷歌和火狐浏览器支持。
hls
严格来说他不是视频格式,他是一种视频协议,他的视频格式是ts
,为了好分辨一般叫他hls
,这种格式是苹果自身研究出来的,所以Safari
浏览器可直接支持,上面演示的时候hls
是直接放在Safari
浏览器的地址栏可以直接播放的。
flv
是早期flash
的一种视频格式,B
站早起就采用的这种格式,即使现在B
站也是支持H5
播放器和flash
播放器的。
直播目前最常用的三种协议是HLS
协议,RTMP
协议和HTTP-FLV
协议。HLS
对应的是hls
格式的视频也就是.ts
。RTMP
和HTTP-FLV
都是对应的flv
格式的视频。
HLS
协议是最简单的也是最常用的,他是苹果推出的一个直播协议,他的工作原理比较简单,H5
一般通过video
标签,从客户端获取一个M3U8
索引文件,这个M3U8
会直接放在video
的src
路径中。
因为M3U8
是一个索引文件,他会被解析成很多的.ts
片段,每一个片段就是一个直播流的分段。
浏览器的video
标签在某个时间会再次请求m3u8
,获取新的直播流片段,这样就实现了直播的实时播放,而发送这个m3u8
的请求是浏览器自主的行为。
<body>
<video id=example-video width=600 height=300 class="video-js vjs-default-skin" controls>
<source src="http://127.0.0.1:7002/live/movie.m3u8" type="application/x-mpegURL">
</video>
<script src="video.min.js"></script>
<script src="videojs-contrib-hls.js"></script>
<script> var player = videojs('example-video'); player.play(); </script>
</body>
这是一个比较标准的直播协议,但是m3u8
不一定包含了ts
文件,也有可能嵌套了一层m3u8
文件,也就是说第一个拿到的m3u8
文件里面还是m3u8
文件。
如果当前的m3u8
里面包含了m3u8
文件,那么当前这个文件就叫master playlist
。
如果当前的m3u8
文件里面包含的是ts
, 那他就叫media playlists
。
这种情况不常见,但是确实是存在的,需要额外注意一下。如果在实践直播的时候拿到的流文件不播放,可能是播放器不支持这种嵌套。
m3u8
分为动态列表,静态列表,全量列表。在直播行业基本是见不到静态列表的,他只是存在标准中。
动态列表主要用于直播的过程中,全量列表多用于点播,也就是录播。m3u8
的响应结果就是一个文本文件。
第一行标明了m3u8
的版本,这个比较重要,因为他直接涉及到播放器支持的hls的版本,如果版本不支持,后面的一些指令可能就无法解析。
第二行是版本的声明,默认是3
,第三行是默认视频的时长,第四行是视频流块的个数,每次请求都会加1
,再往下就是视频的ts
文件,前面的9.901
是这个ts
文件的时长。这里决定了浏览器的video
更新m3u8
文件的时机。
静态列表和动态列表返回文件差不多,只是在第五行多添加了一个playlist-type
值为event
。其他的就没什么区别了。
全量列表比动态列表多了两个东西,第一个是playlist-type
值为vod
,还有底部的ext-x-endlist
代表结束,浏览器识别到这个字段就不会再发送请求了。
对于第一个ts
文件,他会有一个PAT
的包,这个PAT
的包告诉要去找一个PMT
的包,PMT
会告诉所有的TS
里面哪些是视频TS
哪些是音频TS
。很多TS
组成一个叫做PES
的东西。
浏览器像去解析一个视频,首先要知道视频帧和音频帧,在第一个ts
文件中会告诉浏览器,通过先找PAT
, 再找PMT
,再找TS
文件,然后TS
文件再按照视频和音频分类把相连的ts
组成一个帧。
RTMP
是Real Time Messaging Protocol
(实时消息传输协议)的首字母缩写。该协议基于TCP
, 是一个协议族,包括RTMP
基本协议及RTMPT
/RTMPS
/RTMPE
等多种变种。RTMP
是一种设计用来进行实时数据通信的网络协议,主要用来在Flash
,AIR
平台和支持RTMP
协议的流媒体/交互服务器之间进行音视频和数据通信。
传统的软件和服务器之间的交互还是以RTMP
为主,比如说上文讲的视频音频的采集以PC
端为主,如果客户端通过软件的方式采集基本就是基于RTMP
,如果采集端用的是H5
他的协议一般是webrtc
。这是两种不同的技术方案。采集时RTMP
传输过程中视频也是flv
格式的。这里需要注意一下。
RTMP
要比HLS
协议用起来复杂一些因为他是基于TCP
协议的。HLS
使用非常简单但他的实时性会差一些,也就说他有延时,切片越多延时越大。HTTP-FLV
结合了HLS
的优点也就是http
请求然后又集合了RTMP
低延时的特性。
HTTP-FLV
和RTMP
都是长连接,传输的格式也都是flv
,不同点在于他们和CDN
的链接还有播放器的链接上,RTMP
是TCP
而HTTP-FLV
是HTTP
。
HTTP-FLV
相对于RTMP
优势有很多,比如可以在一定程度上避免防火墙的干扰,可以很好地兼容HTTP302
跳转,做到灵活调度,可以使用HTTPS
做加密通道,可以很好的支持移动端(安卓和IOS
)。
这里补充一点video
标签的知识,针对于大多数的前端开发来说,并没有真正意义上的了解video
标签,他的属性,他的事件。很多人都停留在知道他是视频标签,可以播放,暂停,调节音量,有个src属性中。
这是很危险的,Video
标签是H5
推出的一款功能十分强大的多媒体标签,可以说他是网页中媒体的未来。
标签属性部分:
<video src="test.map" width="400" height="225" controls controlslist="nodownload nofullscreen" poster="预览图" autoplay muted loop preload ></video>
controls: 底部控制条
controlslist: 底部控制条定制
poster: 预览图
autoplay: 自动播放
muted: 静音(移动端非静音的视频是不允许自动播放的,想要自动播放一定要静音)
loop: 循环播放
preload: 预加载,每个浏览器表现不一致,尤其是移动端,如果需要最好加上。
JS控制部分:
volume: 音量(0 - 1)
currentTime: 设置获取当前播放时间,单位是秒,超清和高清分别是不同的地址,档切换地址时需要定位时间。
src: 获取视频地址
video.volume = 0.5;
video.currentTime = 60;
video.src;
可以通过source
标签兼容视频地址出错, 这种情况js
需要使用currentSrc
获取当前地址。
<video>
<source src="./test.map" type="video/mp4"></source>
<source src="./test2.map" type="video/mp4"></source>
</video>
video事件:
loadstart: 视频开始加载。
durationchange: 时长变化,表示可以获取视频时长了。
loadedmetadata: 当指定的音频/视频的元数据已加载时,会发生 loadedmetadata 事件
loadeddata: 当前帧的数据已加载,但没有足够的数据来播放指定音频/视频的下一帧时,会发生 loadeddata 事件
progress: 当浏览器正在下载指定的音频/视频时,会发生 progress 事件
canplay: 当浏览器能够开始播放指定的音频/视频时,会发生 canplay 事件
canplaythrough: 当浏览器预计能够在不停下来进行缓冲的情况下持续播放指定的音频/视频时,会发生 canplaythrough 事件
play: 暂停状态改变到播放状态就会触发play事件
seeking: 切换进度条的时候会触发的事件。
seeked: seeking之后下载完数据就会执行。
waiting: 播放状态时,seeking之后会触发waiting。也就是播放状态如果没有足够数据支撑播放就会waiting。
playing: 播放中状态。
timeupdate: 播放时间更新的事件。
ended: 播放结束
error: 报错事件。
前面利用已经集成好的server
工具创建了一个直播的服务器,这里使用nginx
手动搭建一个类似的服务器,再来理解一下他的工作过程。
首先需要安装nginx
和ffmpeg
工具。
工具安装完成之后开始配置nginx
。在nginx.conf
文件中配置,需要配置服务RTMP
模块,在配置文件的最底部新开一个代码块叫rtmp
,里面写上监听1935
端口,视频切片大小设置4000
,也可以自行设置,然后配置一个rtmp
的直播应用rtmplive
,在配置一个hls
的直播应用。
rtmp {
server {
# 监听端口
listen 1935;
# 切片大小
chunk_size 4000;
# RTMP 直播流配置
application rtmplive {
# 开启直播
live on;
# 最大连接数
max_connections 1024;
}
# hls直播流配置
application hls {
live on;
hls on;
# 分割文件存储的位置
hls_path /usr/local/var/www/hls;
# hls分片大小
hls_fragment 5s;
}
}
}
配置好这个之后需要在http
模块中配置访问位置。可以在server
块中增加location
。
server {
listen 8080;
...
locaton /hls {
# 声明相应类型, 也就是响应头
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
# 目录指向rtmp块中切片的目录
root /usr/local/var/www;
# 禁止缓存
add_header Cache-Control no-cache;
}
}
至此nginx
就配置完毕了,可以重启nginx
进行测试。
nginx -s reload
同样的,可以找到前面的那个1.mp4
使用ffmpeg
来推流。这里视频采用libx264
编码,音频采用aac
编码,做成flv
推送到rtmp://localhost:1935/rtmplive/rtmp
域名,这个1935
就是设置rtmp
的端口,rtmplive
就是应用名称。
ffmpeg -re -i 1.mp4 -vcodec libx264 -acodec aac -f flv rtmp://localhost:1935/rtmplive/rtmp
-i: 输入
-vcodec: 视频编码
acodec: 音频编码
这个时候就开始切割视频了,这个过程也就像是摄像头实时获取视频的过程。
这是一个rtmp
协议的直播流,可以使用vlc
来播放,只要在file/open networks
中输入rtmp://localhost:1935/rtmplive/rtmp
就可以播放了。
下面再来演示一下HLS
的源文件制作,这里的ffmpeg
命令基本相同,只是路径需要变一下。上面nginx
配置了rtmplive
和hls
两个。hls
推流需要使用rtmp://localhost:1935/hls/stream
, 这里的stream
可以随意起,不过这个名字关系都后面访问的地址。
ffmpeg -re -i 1.mp4 -vcodec libx264 -acodec aac -f flv rtmp://localhost:1935/hls/stream
这里的hls
是http
协议,之前在nginx
的http
协议中也增加了一个hls
访问路径。http
的地址可以使用Safari
浏览器访问。也可以使用上面自己开发的播放器访问。
http://localhost:8080/hls/stream.m3u8
http-flv
的编译比较复杂,这里就不过多介绍了。至此H5
和小程序的直播就介绍完了。