前言
最近被安排做一个数据可视化的项目,其中包括视频直播(实时监控)功能,于是只懂用 <video>
播放视频文件的我开始学习关于直播、实时播放等知识,在此做下笔记,并转发一些参考性文章。
前置知识
直播协议
在选择工具之前首先要先了解直播的相关原理,这里推荐:
- 直播协议RTMP、HLS、HTTP FLV - Gopherzhang
- 介绍推流、拉流和常用协议
- 《理解RTMP、HttpFlv和HLS的正确姿势》 - 北塔资讯
- 介绍了常用的三个协议的来龙去脉
- 流媒体直播播放三大件PK:RTMP/HLS/HTTP-FLV - 大牛直播SDK
- 作为对协议概念的补充
直播源
对于视频直播,前端使用的也是一个作为直播源的 url 地址,这个地址用于获取直播源的文件,地址是不变的,而文件内容是随着直播而变化的。
客户端每隔一段时间就会重新获取直播源。
以 HLS 的 直播源文件(.m3u8) 为例,可以参考 什么是m3u8?直播源跟m3u8有什么关系? - 见微知著
技术选择
从我的角度去选择:
协议 | 结论 |
---|---|
RTMP | 项目需求是作为拉流端,不考虑 Flash 支持,不采用 |
HLS | 跨平台兼容性好,支持快进播放,延迟高,可用于播放录制完的视频 |
HTTP-FLV | 通过 flv.js 可实现 HTML5 兼容,延迟低,可用于播放实时监控视频 |
工具选择
- HTTP-FLV
- flv.js
- bilibili (前)员工开发的用于在 HTML5 上播放 FLV 格式视频
- 起初是用于将站内 flash 播放器平滑过渡到 HTML5 播放器的开源库
- 对于直播支持 HTTP-FLV
- B 站官方推荐使用 mpegts.js,并生成 flv.js 项目将减少维护。
- 一些吐槽:如何看待B站 (bilibili) 开源 HTML5 播放器内核 flv.js? - 知乎
- flv.js
- HLS:
hls.js 使用
npm install hls.js
<video id="video" src="" /
import Hls from 'hls.js'
const video = document.getElementById('video')
const url = 'http://xxxxxx/xxx.m3u8' // 直播视频源(.m3u8)文件地址
if (Hls.isSupported()) {
// 如果支持 hls.js(MediaSource Extensions)
var hls = new Hls()
hls.loadSource(url)
hls.attachMedia(video)
// 自动播放
hls.on(Hls.Events.MANIFEST_PARSED,function() {
video.play()
})
} else if (video.canPlayType('application/vnd.apple.mpegurl')) {
// 如果支持原生播放
video.src = url
// 自动播放
video.addEventListener('canplay',function() {
video.play()
})
}
也可以直接在 <video>
上添加 autoplay="autoplay"
实现自动播放。
video.js 使用
Vue 示例:
npm i video.js
首先引入 css,可以使用 CDN 地址,也可以使用 npm 包里的 video.js/dist/video-js.css
,可以在 html 模板中引入,也可以在 js 中 import
。
编写组件:
<video ref="MyPlayer" class="video-js">
your browser does not support the video tag
</video>
注意:要使用样式主题,必须为
<video>
元素设置 class 为对应的标记,默认video-js
。上面
<video>
最终会转化成:<div class="video-js"> <video></video> </div>
编写脚本:
import videojs from 'video.js'
import 'video.js/dist/lang/zh-CN.js'
export default {
data() {
return {
url: '',
player: null
}
},
mounted() {
this.player = videojs(this.$refs.MyPlayer, {
autoplay: 'muted', // 自动静音播放
controls: true, // 显示控制器
disablePictureInPicture: true, // 禁用画中画功能
language: 'zh-CN', // 语言设置
sources: [
{
src: this.url,
type: 'application/x-mpegURL', // m3u8 类型
},
],
}, () => {
// onPlayerReady
})
beforeDestroy() {
if (this.player) {
// 清除 video 元素
this.player.dispose()
}
}
}