调试问题
实际上我们在浏览器端调试时,移动端网页的有些问题很难发现,样式问题只是次要的。比较容易出现的问题就是浏览器提供的媒体组件,浏览器通常使用操作系统提供的API来实现一些功能,如音频和视频播放。不同的操作系统可能提供了不同的API,或者即使是相同的API,它们的实现也可能有所不同,这也可能导致不同的表现。这里我们主要在以下环境做了测试,也是我们常用的几个环境:安卓浏览器、ios浏览器、微信浏览器。然后本篇文章主要展示几个出现的问题及其解决方案。
1.全屏播放问题
本问题主要分为两种,一是移动端的video播放基本都是默认全屏播放,当视频开始播放的时候,视频默认进入全屏模式;二是当我们修改了视频默认不全屏播放时,在微信浏览器端想要进入全屏播放模式得需要特殊的处理。 第一个问题在本系列的第二篇文章的模板说明种已说明了解决方法:
正常的video在手机端播放的时候都是默认全屏播放,因此我们需要控制视频初始内联播放,因此需要设置一下属性: webkit-playsinline="true" playsinline="true" x5-playsinline 这里同时设置了3个playsinline主要是兼容不同的设备 使视频默认为内联播放即可解决这个问题。
第二个问题,目前仅在微信端的浏览器复现,实际上我们在实现SetFullScreen方法的时候已经对大部分浏览器做了兼容:
javascript
const video = this.video.target
if (video.requestFullscreen) {
video.requestFullscreen()
} else if (video.mozRequestFullScreen) {
/* Firefox */
video.mozRequestFullScreen()
} else if (video.webkitRequestFullscreen) {
/* Chrome, Safari 和 Opera */
video.webkitRequestFullscreen()
} else if (video.msRequestFullscreen) {
/* IE/Edge */
video.msRequestFullscreen()
}
但是在微信浏览器中,video元素上都没有这些方法,也没有提供进入全屏模式的方法,而仅仅提供了两个关于全屏模式进入和退出的监听方法,实际上也不是很好使,这里不展示了,感兴趣的大家自行搜索。这里说一下我们的解决思路,是根据第一个问题产生的方案,因为微信端其实也是默认播放视频的,所以当我们检测到微信环境,我们在设置全屏的时候,把内联播放取消,然后播放即可进入全屏播放;然后当我们退出全屏时,再点播放按钮进入播放时,再把我们的video标签设置为内联播放即取消了全屏播放。完美解决全屏播放的问题:
javascript
SetFullScreen() {
// other codes...
if (
navigator.userAgent.toLocaleLowerCase().indexOf('micromessenger') !== -1
) {
video.pause()
video.removeAttribute('webkit-playsinline')
video.removeAttribute('playsinline')
video.removeAttribute('x5-playsinline')
video.removeAttribute('x-webkit-airplay')
video.play()
}
}
PlayVideo() {
if (this.video.target.paused) {
if (
navigator.userAgent.toLocaleLowerCase().indexOf('micromessenger') !==
-1
) {
this.video.target.setAttribute('webkit-playsinline', 'true')
this.video.target.setAttribute('playsinline', 'true')
this.video.target.setAttribute('x5-playsinline', 'x5-playsinline')
this.video.target.setAttribute('x-webkit-airplay', 'true')
}
this.video.target.play()
} else {
this.video.target.pause()
}
}
2.开始播放白屏问题
当我们的视频资源是从网络上或者cdn上动态加载的时候,总是在开始播放的时候白屏或者黑屏 1s左右,当网络差的时候这种白屏或者黑屏时间可能更长,当然这是由于视频资源加载缓慢的原因。首先想到的解决方案就是poster+preload,将preload设置为auto或者metadata,然后把poster设置好,确实在视频未播放的时候不会出现黑屏或者白屏。但是当我们点击播放的时候,还是会有黑屏或者白屏闪烁一下,所以这个并不能解决我们的体验问题。 因此思考我们需要把poster单独抽离出来,同时去监听canplay事件,当视频可以播放的时候再将poster隐藏,同时播放视频。 所以我们在start-play-btn和video之间放一层poster,同时控制它的展示状态即可:
模板
html
<video
:src="videoSrc"
id="video"
class="player"
style="object-fit:fill"
webkit-playsinline="true"
playsinline="true"
x5-playsinline
preload="auto"
:poster="poster"
x-webkit-airplay="true"
ref="video"
></video>
<div
class="poster"
id="poster"
v-if="!video.canplay"
>
<img
src="https://peiyinimg.qupeiyin.cn/2024-03-19/171083686254726059014.jpg-thumb"
class="poster-icon"
>
</div>
<div
class="fz-player-controls-panel-wrapper"
id="playerPanel"
@click="ShowControl"
>...</div>
逻辑代码
javascript
data() {
return {
// ... other params,
video: {
// ... other params,
canplay: false
}
}
},
video.oncanplay = () => {
// ... other code
this.video.canplay = true
}
虽然不知道媒体文件播放在各个浏览器的实现细节,但是我们可以通过宏观的方式解决一些看似不可能解决的问题。这就是编码的魅力。
3.关键帧问题
video播放在浏览器有一个细节问题,有些视频当我们seek的时候,我们的indicator总是在播放时或前或后的跳动一下,或者当我们拖动indicator之后松开的时候,也会或前或后的跳动一下然后再正常播放进度,很让人抓狂。其实还以为是我们计算的seek时间有那么零点几秒的差异。但是不管怎么去调接时间的精度,有些视频总是会出现这种问题。仔细调研一番才知道,这就是视频压缩中的"关键帧"问题。当我们进行seek的时候video会把帧定位到离我们seek时间最近的那个关键帧上,当我们视频的编码格式或分辨率不高的时候,也就会概率出现seek不准确的问题。解决这个办法,目前之后去修改我们播放的视频源了,暂时没有找到前端的解决方案。
总结
实际上在调试过程中我们可能会遇到了许多的问题,但是如果我们的编码足够细致且够优雅,实际上逻辑问题基本都遇不到,遇到的都是一些兼容和体验问题,而往往这些体验问题,其实占我们调试的大部分时间。毕竟产品都是给用户用的,如果体验不好,那么做出来又有什么意义呢。在调试过程中,其实我们也在不断的优化我们的代码,让自己的代码变的优雅,是一个优秀的程序员必备的技能之一,下一章我们就来结合本项目谈谈代码优化的话题。