解决 video.js ios 播放一会行一会不行
最近用video 进行m3u8视频文件播放,但是途中遇到了 安卓和电脑端都能打开,ios有时可以播放有时播放不了
出现问题原因:
ios拿到视频流前需要预加载视频,如果当前视频流还没有打开过,ios拿不到视频流的缓存,这时候ios会一直转圈直到报错
解决思路:
(1)先打开一个播放窗口,提前加载视频流
(2)判断当前video的 readyState 属性
(3)当readyState的状态码不等于0时,创建当前预览的video
html代码:
<!-- 视频播放 start-->
<div class="monitor-preview__video">
<div id="videoBox" style="width: 94vw; height: 25vh;">
<video
id="VideoPreview"
class="video-js vjs-default-skin vjs-big-play-centered"
controls
style='width: 100%;height: 100%;'
x5-video-player-fullscreen="true"
webkit-playsinline
x5-playsinline
playsinline
x-webkit-airplay="allow"
>
<source :src="this.formData.path" type="application/x-mpegURL">
</video>
</div>
</div>
<!-- 视频播放 end-->
<!-- ios 直接打开视频预览有问题,所以这里搞一个播放预加载界面start-->
<div id="copyVideoBox" v-show="false">
<video
id="copyVideoPreview"
class="video-js vjs-default-skin vjs-big-play-centered"
controls
preload="metadata"
style='width: 0;height: 0;'
x5-video-player-fullscreen="true"
webkit-playsinline
x5-playsinline
playsinline
x-webkit-airplay="allow"
autoplay
>
<source :src="this.formData.path" type="application/x-mpegURL">
</video>
</div>
<!-- 取一个预加载界面end-->
js代码:
/**
* @param device 设备信息
* 切换视频
*/
async checkDevice (device) {
if (device && device.sysCameraCode) {
this.formData.deviceName = device.cameraName
const queryParams = {
sysCameraCode: device.sysCameraCode,
apiPath: window.location.origin
}
const videoRes = await this.$api.monitorPerm.preview(queryParams)
this.formData.path = videoRes.result.previewUrl
this.prepareVideo ()
}
},
/**
* 预加载视频信息
* ios 直接打开视频预览有问题,所以这里搞一个播放预加载界面start
*/
prepareVideo () {
const isIos = navigator.userAgent.toLowerCase().match(/cpu iphone os (.*?) like mac os/)
if (!isIos) {
this.reloadVideoDom()
return
}
// 清空旧的预览信息
this.clearVideoDom()
if (this.formData.copyVideo) {
this.formData.copyVideo.dispose()
}
this.formData.copyVideo = null
const videoBox = document.getElementById('copyVideoBox')
const VideoPreview = document.getElementById('copyVideoPreview')
if (VideoPreview) {
videoBox.removeChild(VideoPreview)
}
videoBox.innerHTML = '<video\n' +
' id="copyVideoPreview"\n' +
' class="video-js vjs-default-skin vjs-big-play-centered"\n' +
' controls\n' +
' preload="metadata"\n' +
' style=\'width: 100%;height: 100%;\'\n' +
' x5-video-player-fullscreen="true"\n' +
' webkit-playsinline\n' +
' x5-playsinline\n' +
' playsinline\n' +
' x-webkit-airplay="allow"\n' +
' autoplay\n' +
' >\n' +
` <source src="${this.formData.path}" type="application/x-mpegURL">\n` +
' </video>'
const path = this.formData.path
this.$nextTick(() => {
this.formData.copyVideo = this.$videojs('copyVideoPreview', {
bigPlayButton: true,
textTrackDisplay: false,
posterImage: false,
errorDisplay: true,
controlBar: true,
html5: {
hls: {
overrideNative: false
},
nativeVideoTracks: true,
nativeAudioTracks: true,
nativeTextTracks: true
}
}, function () {
this.src({
src: path,
type: 'application/x-mpegURL'
})
this.play()
})
// 监控预加载视频状态,状态不等于0创建预览dom
this.$nextTick(() => {
this.formData.time = setInterval(() => {
const myVid = this.formData.copyVideo.readyState()
console.log('myVid', myVid)
if (myVid !== 0) {
clearInterval(this.formData.time)
this.reloadVideoDom()
}
}, 1000)
})
})
},
/**
* 创建当前需要预览的视频dom
*/
reloadVideoDom () {
this.clearVideoDom()
const videoBox = document.getElementById('videoBox')
videoBox.innerHTML = '<video\n' +
' id="VideoPreview"\n' +
' class="video-js vjs-default-skin vjs-big-play-centered"\n' +
' controls\n' +
' preload="metadata"\n' +
' style=\'width: 100%;height: 100%;\'\n' +
' x5-video-player-fullscreen="true"\n' +
' webkit-playsinline\n' +
' x5-playsinline\n' +
' playsinline\n' +
' x-webkit-airplay="allow"\n' +
' autoplay\n' +
' >\n' +
` <source src="${this.formData.path}" type="application/x-mpegURL">\n` +
' </video>'
const path = this.formData.path
this.$nextTick(() => {
this.formData.video = this.$videojs('VideoPreview', {
bigPlayButton: true,
textTrackDisplay: false,
posterImage: false,
errorDisplay: true,
controlBar: true,
html5: {
hls: {
overrideNative: false
},
nativeVideoTracks: true,
nativeAudioTracks: true,
nativeTextTracks: true
}
}, function () {
this.src({
src: path,
type: 'application/x-mpegURL'
})
this.play()
})
})
},
/**
* 清空当前预览dom
*/
clearVideoDom () {
if (this.formData.video) {
this.formData.video.dispose()
}
this.formData.video = null
const videoBox = document.getElementById('videoBox')
const VideoPreview = document.getElementById('VideoPreview')
if (VideoPreview) {
videoBox.removeChild(VideoPreview)
}
}
问题到这里就解决了