解决 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)
      }
    }

问题到这里就解决了

相关推荐

  1. 解决 video.js ios 播放

    2023-12-07 05:32:03       42 阅读
  2. 文学 Apache Zeppelin

    2023-12-07 05:32:03       36 阅读

最近更新

  1. TCP协议是安全的吗?

    2023-12-07 05:32:03       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2023-12-07 05:32:03       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2023-12-07 05:32:03       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2023-12-07 05:32:03       20 阅读

热门阅读

  1. 微信小程序中全局变量的应用

    2023-12-07 05:32:03       38 阅读
  2. 【Android】Glide的简单使用(下)

    2023-12-07 05:32:03       36 阅读
  3. JPA构建多条件查询

    2023-12-07 05:32:03       38 阅读
  4. 浅谈深度学习中的过拟合

    2023-12-07 05:32:03       34 阅读
  5. EasyExcel下拉列表长度过长不显示【已修复】

    2023-12-07 05:32:03       45 阅读
  6. 第3节:Vue3 v-bind指令

    2023-12-07 05:32:03       37 阅读
  7. 【flink】基于flink全量同步postgres表到doris

    2023-12-07 05:32:03       38 阅读
  8. Stream流

    Stream流

    2023-12-07 05:32:03      31 阅读
  9. 算法工程师-机器学习面试题总结(4)

    2023-12-07 05:32:03       33 阅读
  10. golang学习笔记——go互斥锁

    2023-12-07 05:32:03       41 阅读
  11. (二)回测框架之策略Mocker

    2023-12-07 05:32:03       35 阅读
  12. 如何给自己的网站加密

    2023-12-07 05:32:03       35 阅读