vue+flvjs实现自定义控制条的流媒体播放器
flvjs与FLV有什么区别和联系?
flv.js
是 HTML5 Flash 视频(FLV)播放器,纯原生 JavaScript 开发,没有用到 Flash。由 bilibili 网站开源(Github)。
概览:
一个实现了在 HTML5 视频中播放 FLV 格式视频的 JavaScript 库。它的工作原理是将 FLV 文件流转码复用成 ISO BMFF(MP4 碎片)片段,然后通过 Media Source Extensions 将 MP4 片段喂进浏览器。
flv.js 是使用 ECMAScript 6 编写的,然后通过 Babel Compiler 编译成 ECMAScript 5,使用 Browserify 打包。
功能:
- FLV 容器,具有 H.264 + AAC 编解码器播放功能
- 多部分分段视频播放
- HTTP FLV 低延迟实时流播放
- FLV 通过 WebSocket 实时流播放
- 兼容 Chrome, FireFox, Safari 10, IE11 和 Edge
- 十分低开销,并且通过你的浏览器进行硬件加速
FLV
HTTP FLV则是将RTMP封装在HTTP协议之上的,可以更好的穿透防火墙等。rtmp和http-flv的视频格式都是flv格式的,只是传输协议而不同。rtmp是tcp的传输协议,而http-flv是http长链接的传输协议。
总结
flvjs是一个H5播放器。FLV是一种协议。flvjs可以用于播放FLV格式的视频。
几种视频流比较。
协议 | http-flv | rtmp | hls |
---|---|---|---|
传输方式 | http流 | tcp流 | http流 |
视频封装格式 | flv | flv | Ts文件 |
延迟 | 低 | 低 | 高 |
数据分段 | 连续流 | 连续流 | 切片文件 |
h5播放 | flv.js | video.js | hls.js |
vue中使用flvjs。
1.使用npm安装flv.js
npm install --save flv.js
2.新建FlvLive.vue文件,在文件中引入
import flvjs from \'flv.js\'
3.在template标签中添加代码
<figure
ref="videoContainer"
data-fullscreen="false"
>
<video
ref="video"
autoplay
>
Your browser is too old which doesn\'t support HTML5 video.
</video>
</figure>
4.在created中加入以下代码
this.$nextTick(() => {
if (flvjs.isSupported()) {
const flvPlayer = flvjs.createPlayer({
type: \'flv\',
isLive: true,
url: this.src,
});
flvPlayer.attachMediaElement(this.$refs.video);
flvPlayer.load();
flvPlayer.play();
this.flvPlayer = flvPlayer;
}
});
flvjs.isSupported()
判断当前浏览器是否支持flv。
flvPlayer.attachMediaElement(this.$refs.video)
挂载video标签。
也可以使用如下方式:
<video
id="videoEdlement"
autoplay
>
Your browser is too old which doesn\'t support HTML5 video.
</video>
js
const id = document.getElementById(\'videoEdlement\')
flvPlayer.attachMediaElement(id)
使用这种方式会导致组件无法复用。除非给video传入不同的id的值。
5.传入src,一个简单的播放器就完成了。也可以在video标签中加入controls
属性以利用H5播放器自带的控制条。
自定义控制条。
效果图,画面是ffmpeg推的一个mp4的流。红框部分为控制条。
使用全屏API
这里使用webkitRequestFullScreen()
API实现全屏功能。
webkitRequestFullScreen()
方法用于发出异步请求使元素进入全屏模式。来自MDN教程的解释。
使用全屏API时需要注意,如果全屏的元素是video,自定义的控制条会被全屏后的video元素覆盖住,更改z-index也不能解决。所以要放大video的父级元素。
this.$refs.videoContainer.webkitRequestFullScreen();
CSS部分
设置全屏时的背景,隐藏全屏时video标签中的控制条。
/* fullscreen */
html:-ms-fullscreen {
width: 100%;
}
:-webkit-full-screen {
background: #666;
}
figure[data-fullscreen=\'true\'] {
max-width: 100%;
width: 100%;
margin: 0;
padding: 0;
/* hide controls on fullscreen with WebKit */
video::-webkit-media-controls {
display: none !important;
}
}
figure[data-fullscreen=\'true\'] {...}
在点击全屏按钮时会改变这个属性。体现在如下代码中。
setFullscreenData(state) {
this.$refs.videoContainer.setAttribute(
\'data-fullscreen\',
Boolean(state),
);
},
判断当前页面是否处于全屏状态
对应不同的浏览器内核做兼容处理。
isFullScreen() {
return Boolean(
document.fullScreen ||
document.webkitIsFullScreen ||
document.mozFullScreen ||
document.msFullscreenElement ||
document.fullscreenElement,
);
},
开发中遇到的报错
Uncaught (in promise) DOMException:The play() request was interrupted by a new load request
报错信息表示:视频还没有准备好,就已经开始播放了。这种情况会出现在,视频地址错误的情况下。常常是地址为空,或者格式错误。
Uncaught (in promise) DOMException: The play() request was interrupted by a call to pause().
调用play()的时候,音频文件还没有加载完成导致的问题。建议给video标签加上autoplay。不然老是出现这个问题。到底是什么原因导致的还不知道。
同一页面中引入4个画面时,其他三个画面会报错。video标签的id一致导致的。
总结
本文通过实现一个自定义控制条的H5播放器,来学习相关的内容,包括:flvjs在vue中的使用。js的全屏API。以及一个document的一些内置对象的使用。
完整代码:gitee