videojs官网: https://videojs.com/getting-started
video.js安装
使用videoJs前势必需要先安装videoJs,目前有两种方式可以使用;
- npm包安装工具
npm install video.js --save-dev
npm install videojs-contrib-hls --save
- 直接在
<head></head>
标签里引入需要的videoJs文件
<link href="https://cdn.bootcss.com/video.js/7.6.5/alt/video-js-cdn.min.css" rel="stylesheet">
<script src="https://cdn.bootcss.com/video.js/6.6.2/video.js"></script>
<script src="https://cdn.bootcss.com/videojs-contrib-hls/5.15.0/videojs-contrib-hls.min.js"></script>
video.js引入
- 在vue的主入口文件
main.js
里进行引入
// 引入video.js样式
import "video.js/dist/video-js.css"
import videojs from 'video.js'
import 'videojs-contrib-hls' // 用来播放hls流
import '@videojs/http-streaming'
// 在原型上注册以便在任何地方都可以使用
Vue.prototype.$video = video;
- 如果使用改插件的页面不多,可以直接在需要使用的页面进行引入
import videojs from 'video.js'
import 'videojs-contrib-hls'
import '@videojs/http-streaming'
video.js使用
-
video
标签使用
根据业务逻辑设计,我这边的直播链接是用户选择后通过后端动态获取的,因此在HTML部分没有使用<source></source>
配置播放地址
<video id="videoBox" playsinline class="video-js vjs-default-skin vjs-big-play-centered vjs-fluid vjs-16-9" controls preload="none"></video>
- videoJs初始化,创建播放器
initVideo() {
let videoPlayer = videojs("videoBox",{
fluid: true, // 扩展以适应其容器的大小
bigPlayButton: false, // 是否在暂停时显示大的播放按钮,按钮一般默认在左上角
textTrackDisplay: true,
posterImage: false, // 是否使用视频的缩略图
errorDisplay: false,
}, function (){
// 回调函数,在播放器创建完成后执行
// 这里我用来处理获取到动态视频地址时手动触发播放器播放
this.src({
src: 'url',
type: 'application/x-mpegURL'
})
this.play()
})
}
- 一定记得离开页面时销毁组件
videoPlayer.dispose()
注意点:
在开始视频直播时,可能会出现后端下发指令去拉流,但是设备还没上报流的情况,这时候后端给的直播地址并不是有效的,videoJs拉取不到流会报错并停止播放拉流;
对于这种情况,我们可以监听播放器,手动触发其继续获取数据直到成功播放
videoPlayer.on('error', function () {
setTimeout(() => {
this.src({
src: url,
type: 'application/x-mpegURL'
})
this.play()
}, 5000)
})
videoJs常用配置
-
autoplay : true/false
播放器准备好之后,是否自动播放 -
controls : true/false
是否拥有控制条 【默认true】,如果设为false ,那么只能通过api进行控制了。也就是说界面上不会出现任何控制按钮 -
height
: 视频容器的高度,字符串或数字、单位像素 -
width
: 视频容器的宽度, 字符串或数字 单位像素 -
loop : true/false
视频播放结束后,是否循环播放 -
muted : true/false
是否静音 -
poster
: 播放前显示的视频画面,播放开始之后自动移除。通常传入一个URL -
preload
:预加载
‘auto‘ 自动
’metadata‘ 元数据信息 ,比如视频长度,尺寸等
‘none‘ 不预加载任何数据,直到用户开始播放才开始下载 -
children: Array | Object
可选子组件 从基础的Component组件继承而来的子组件,数组中的顺序将影响组件的创建顺序哦。 -
posterImage : true/false
在未播放前是否显示缩略图 -
poster
配置缩略图地址 -
bigPlayButton : true/false
是否显示播放的大图标
videoJs常用监听
videoPlayer.controlBar.playToggle.on('click', () => {
// 监听播放暂停按钮的点击
})
videoPlayer.tech_.on('click', () => {
// 监听视频内容里的点击
})
videoPlayer.bigPlayButton.on('click', ()=> {
// 监听播放按钮大图标
})
videoPlayer.on('play', () => {
// 监听视频开始播放
})
videoPlayer.on('pause', () => {
// 监听视频暂停
})
videoPlayer.on('canplaythrough', function (){
// 监听视频加载完成
})
videoPlayer.on('error', function () {
// 监听视频获取失败
})
通过样式修改video.js播放按钮、控件
- 播放按钮大图标居中显示
在<video></video>
标签增加vjs-big-play-centered
类
<video id="videoBox" class="video-js vjs-default-skin vjs-big-play-centered vjs-fluid vjs-16-9"></video>
- 播放按钮样式修改
.video-js .vjs-big-play-button{}
- 暂停时显示播放按钮
.vjs-paused .vjs-big-play-button,
.vjs-paused.vjs-has-started .vjs-big-play-button {
display: block;
}
- 禁止视频在苹果电脑自动全屏,需在标签上配置
playsinline
<video id="videoBox" playsinline class="video-js vjs-default-skin vjs-big-play-centered vjs-fluid vjs-16-9"></video>
- videoJs插件播放视频时,进度条默认显示的剩余时间,若想要显示总时间和已播放的时间,可以修改下css,如图:
::v-deep.video-js .vjs-time-control {
display: block;
}
::v-deep.video-js .vjs-remaining-time {
display: none;
}
- 使用自定义的视频缩略图时,可能会出现视频大小和缩略图不匹配,导致出现黑边的情况,可以设置样式去掉黑边
::v-deep .video-js .vjs-tech {
object-fit: fill;
}
::v-deep .vjs-poster {
background-size: cover;
}
语言切换
实现video.js语言与系统语言保持一致;
首先把需要的几种语言引入并添加到插件中(这里我只用了中英文)
// main.js
import "video.js/dist/video-js.css"
import lang_zhcn from "video.js/dist/lang/zh-CN.json"
import en_US from "video.js/dist/lang/en.json"
videojs.addLanguage('zh_CN', lang_zhcn)
videojs.addLanguage('en_US', en_US)
Vue.prototype.$videojs = videojs;
然后在初始化video.js时配置语言
this.videoPlayer = this.$videojs("videoBox",{
// 获取系统当前语言并配置
language: this.$store.state.language,
}, () => {})
遇到的问题
由于业务要求,需要在播放视频结束后将视频播放器恢复到初始状态,即停止播放并显示封面图;查看了文档,有一个reset
方法是重置用的,使用后发现是能达到恢复播放器相关参数为默认值,但是不能显示封面图;经过对播放器生成的dom元素的观察,发现封面图是否显示是由两个类控制的,分别是.vjs-has-started
和.vjs-hidden
,因此我们可以通过清除这两个类实现显示封面图;具体实现方式如下:
this.videoPlayer.pause() // 根据情况,我这边会有在播放中触发初始化的情况,所以加了个暂停
this.videoPlayer.src('')
this.videoPlayer.reset() // 重置
this.videoPlayer.posterImage.setSrc(require('@/assets/img/video_template_bg.png')) // 发现重置后一开始设置的封面图会被清空,这里需要重新设置下
this.videoPlayer.posterImage.show() // 移除`.vjs-hidden`
document.getElementsByClassName('video-js')[0].classList.remove('vjs-has-started') // 移除`.vjs-has-started`