app内嵌h5 视频播放器踩坑

2,877 阅读3分钟

第一篇文章 记app webview内嵌h5开发视频播放器踩坑

  1. 视频自动播放
  2. ios默认全屏播放
  3. 在微信,飞书等内置浏览器打开h5,调用requestFullscreen方法,自动旋转导致视频进度条拖动错误

查阅MDN发现

网页加载完成后立即播放音频(或带有音频轨道的视频)可能会意外地打扰到用户。尽管自动播放媒体文件是一个很实用的功能,但是我们也应该谨慎地使用它,保证只有在它被需要的时候才使用。为了让用户拥有控制权,通常浏览器会提供各种方式禁用自动播放音频功能。

由于浏览器带有自动播放策略,需要在视频不能自动播放时,进行处理,总结找到的几种方法。
1.将视频进行静音处理,视频在静音的情况下是可以进行自动播放的,但是就导致视频没有声音。

<video muted></video>

2.调用video标签的play方法返回一个Promise,可以根据该Promise状态检测能否自动播放进行相应的处理。

// 检测h5能否自动播放
export function isAutoPlay() {
  return new Promise((resolve, reject) => {
    const video = document.createElement('video')
    document.body.appendChild(video)
    const startPlayPromise = video.play()
    if (startPlayPromise !== undefined) {
      startPlayPromise
        .then(() => {
          resolve()
        })
        .catch((error) => {
          if (error.name === 'NotAllowedError') {
            reject(new Error("can't autoPlay"))
          } else {
            reject(error.message)
          }
        })
        .finally(() => {
          document.body.removeChild(video)
        })
    }
  })
}

3.引导用户在播放视频之前和网页产生交互行为。

在ios webview中,播放视频时会默认全屏播放,此时需要在video标签上进行设置

//视频播放时局域播放
playsinline="true" 
webkit-playsinline="true"

注:但是这个属性比较特别, 需要嵌入网页的APP比如WeChat中UIwebview 的allowsInlineMediaPlayback = YES

如果还需要ios能够自动播放,还需要ios进行设置。

为了在app上播放器和设计图一致,手写了一个简易播放器,在该播放器上,需要实现全屏功能。

直接使用浏览器自带的requestFullscreen方法,查阅兼容性发现,ios设备对该属性支持不咋滴

截屏2022-02-12 上午11.17.21.png

最后决定在app内部打开的h5使用css来模拟全屏的效果,暂时没有更好方案。 直接将父元素直接铺满,video标签在其中居中,高度根据width:100%自适应。

在app外部,使用原生方法来对元素进行全屏操作

    full() {
    //通过jsBridge来判断是否app环境
      if (this.jsBridge.check()) {
        this.isFull = !this.isFull
      } else if (!document.fullscreenEnabled) {
        this.isFull = !this.isFull
      } else if (this.isFull) {
      //推出全屏判断各浏览器兼容性
        if (document.exitFullscreen) {
          document.exitFullscreen()
        } else if (document.msExitFullscreen) {
          document.msExitFullscreen()
        } else if (document.mozCancelFullScreen) {
          document.mozCancelFullScreen()
        } else {
          document.webkitExitFullscreen()
        }
        this.isFull = false
      } else {
      //进入全屏判断各浏览器兼容性
        const video = document.querySelector('.video')
        if (video.requestFullscreen) {
          video.requestFullscreen()
        } else if (video.mozRequestFullScreen) {
          video.mozRequestFullScreen()
        } else if (video.webkitRequestFullscreen) {
          video.webkitRequestFullscreen()
        } else if (video.msRequestFullScreen) {
          video.msRequestFullScreen()
        }
        this.isFull = true
      }
      // const video = this.$refs.video
    },

当我们使用微信内置浏览器打开h5进行播放视频时,调用微信浏览器的requestFullscreen方法,浏览器自动将我们的视频进行了横屏操作,导致进度条拖拽功能出现了错误。

进度条拖拽功能实现步骤:

  1. 获取进度条元素相对于page的left和right以及本身的宽
    getOffsetInfo() {
      this.left = document.getElementsByClassName('progress-box')[0].getBoundingClientRect().left
      this.right = document.getElementsByClassName('progress-box')[0].getBoundingClientRect().right
      this.domWidth = document.getElementsByClassName('progress-box')[0].clientWidth
    },
  1. 当进度条的touch事件触发之后获取触摸点的坐标 当前进度 = ((触摸点的x坐标 - 进度条的left) / 进度条的width)* 100
    computedNowPosition() {
      const pageX = this.startTouchPoint.pageX
      const ratio = (pageX - this.left) / this.domWidth
      //duration为当前视频总时长
      this.currentTime = ratio * this.duration
      this.$refs.video.currentTime = ratio * this.duration
      this.width = ratio * 100
    },

在微信内打开h5使用全屏方法,浏览器自动旋转了播放器,导致计算当前播放进度方法出错,经过反复查找问题,我们的left是一开始播放器没有旋转时的left,当播放器被旋转之后left被改变了,并且触发了window的resize事件,所以当resize事件被触发的时候,我们需要重新获取进度条的各种距离

    // 在微信或者飞书打开使用自带全屏方法,全屏时重新获取进度条相对屏幕的距离
    window.addEventListener('resize',()=>{
      this.getOffsetInfo()
    })

以此记录掘金第一篇文章!!!