在移动端视频播放器的实践笔记

4,081 阅读3分钟

本文记录一下最近在直播组关于在移动端视频播放器的笔记。
分别使用了原生video标签,video.js,flv.js, TC player几个来实现在移动端各设备间视频播放的兼容适配。

原生video标签

原生的video标签中,事件等各个方面属性在不同设备、不同浏览器下会出现不兼容情况。

使用原生video标签,在安卓和I0S11以下机型中,autoplay不支持;解决办法:

  1. 使用静音【muted】播放
  2. 引导用户点击后播放<-->推荐

在微信内核和一些移动端浏览器中,播放视频会默认全屏;需添加以下属性阻止全屏:

x5-video-orientation="portraint"
webkit-playsinline='true'
playsinline='true'
x-webkit-airplay='true'
x5-video-player-type='h5'
x5-video-player-fullscreen='true'
x5-video-ignore-metadata='true'

以上属性,经测试后在微信内是如期的;但在小米浏览器上视频还是全屏播放。

关于更多各个设备下video标签属性的差异,非常推荐这位前辈的文章: 移动端HTML video视频播放优化实践

以下为原生video标签示例,支持暂停播放,是否缓冲到可播放状态

step1: 在组件中声明video

<template>
    <div>
        <div class="video">
            <video :src="infoData.imagesUrls[0].url" :poster="infoData.imagesUrls[0].thumbUrl" ref="video"
             x5-video-orientation="portraint" @timeupdate="handleTimeupdate"
             webkit-playsinline='true' playsinline='true' x-webkit-airplay='true'
             x5-video-player-type='h5' x5-video-player-fullscreen='true' x5-video-ignore-metadata='true'
             id="video" loop preload="auto" :playOrPause="playOrPause">
        您的设备不支持!
              </video>
        </div>
        <div class="playOrPause">
          <img class="video_play" @click="pauseVideo()" v-show="!playOrPause" src="http://lztimg.oss-cn-qingdao.aliyuncs.com/images/20210203/share03.png"/>
        </div>
    </div>
</template>

step2:设置播放器和一些事件处理

<script>
mounted() {
  this.$video = this.$refs.video;
    /**
     * 定时获取当前视频长度,获取到后获取当前视频已经下载多少了
     * 当当前视频下载量大于等于当前视频长度时去除加载动画;待用户点击播放
     * 以下定时器中,在非IOS中使用
     * */
    this.$video.setAttribute('autoplay', true)
    let getVideoLengthTimer = setInterval(()=>{
      let duration = this.$video.duration;
      if(!isNaN(duration)){
        let end = this.getVideoEnd();
        if(end <= duration) {
          return
        }
        // 去除加载动画和遮罩
        clearInterval(getVideoLengthTimer)
      }else{
        // 去除加载动画和遮罩
        clearInterval(getVideoLengthTimer)
      }
    },1000)
  }
  methods: {
  // 暂停/开始视频
    pauseVideo(){
      try {
        let video = document.getElementById('video');
        if (this.playOrPause) {
          video.pause();
        } else {
          video.play();
          video.pause();
          setTimeout(() => {
            video.play();
          }, 100);
        }
        this.playOrPause = !this.playOrPause;
        // this.getVideoDuration();
      } catch (e) {
        alert(e);
      }
    },
    // 获取当前视频已经加载多少了
    getVideoEnd(){   // video:video标签对象
      let end = 0
      try {
        if(this.$video.buffered.length>0){
          end = this.$video.buffered.end(0) || 0
          end = parseInt(end * 1000 + 1) / 1000
        }
      } catch(e) {
        console.log(e)
      }
      return end
    },
    // IOS下会自动播放,在自动播放后清除遮罩
    handleTimeupdate(){
      if(!this.$video.paused){
        this.playOrPause = true
      }
      let mask = document.getElementById('mask');
      mask.style.opacity = 0;
      mask.style.zIndex = -99;
    },
  }
</script>

TCplayer Lite 在vue中使用笔记

腾讯出品:TCPlayerLite 文档

首先先说明 此播放器不支持在移动端播放.FLV格式视频。

listener可以监听到video各个时间段的事件;并针对特别事件做处理

step1:引入

// 在index.html头文件引入
<script src="https://imgcache.qq.com/open/qcloud/video/vcplayer/TcPlayer-2.3.3.js" charset="utf-8"></script>

step2: 在组件中创建容器

<template>
    <div class="video" >
    	<div id="id_test_video" style="width:100%; height:100vh;"></div>
    </div>
</template>

step3: 设置播放器

<script>
	export default {
	 mounted() {
        var self = this;
        var player = new TcPlayer('id_test_video', {
          "mp4": "//vjs.zencdn.net/v/oceans.mp4", //请替换成实际可用的播放地址
          "autoplay" : true,      //iOS 下 safari 浏览器,以及大部分移动端浏览器是不开放视频自动播放这个能力的
          "poster" : "http://www.test.com/myimage.jpg",
          "width" :  '100vw',//视频的显示宽度,请尽量使用视频分辨率宽度
          "height" : '100vh', //视频的显示高度,请尽量使用视频分辨率高度
          "live": false,	// 是否直播
          // "controls": "none"	// 是否显示控制条
          listener: (msg) => {	// 监听播放器事件
            console.log(msg.type)
            // progress timeupdate
            if(msg.type === 'progress'){
              self.loading = true
            }
            if(msg.type === 'timeupdate'){
              self.loading = false;
            }
          }
    });

    // 给video标签添加,在各个设备下不自动全屏显示
    let video = document.getElementsByTagName('video')[0];
    video.setAttribute("x5-video-orientation", "portraint")
    video.setAttribute("webkit-playsinline", "true")
    video.setAttribute("playsinline", "true")
    video.setAttribute("x-webkit-airplay", "true")
    video.setAttribute("x5-video-ignore-metadata", "true")
    video.setAttribute("x5-video-player-fullscreen", "true")
    video.setAttribute("x5-video-player-type", "h5")
  }
}
</script>

此时,播放器可以使用了

step4: 修改默认样式

// 视频播放区域
.vcp-player video{
  width: 100vw;
  height: auto;
  min-height: 100vh;
}

#id_test_video{
  display: flex;
  align-items: center;
}

// 视频封面
.vcp-poster img{
  width: 100%;
  //height: 100%;
}

.vcp-bigplay{
  height: 100%;
}

// 加载动画
.vcp-loading{
  border: none;
  background: url("https://lztimg.oss-cn-qingdao.aliyuncs.com/ips/images/20210201/loading.gif") center no-repeat;
  width: 1.6rem;
  height: 1rem;
  background-size: 60%;
  margin-left: -0.8rem;
}
.vcp-loading:before{
  content: "";
  display: inline;
}

// 全屏
.vcp-fullscreen-toggle{
  display: none;
}

// 播放/暂停 按钮
.vcp-playtoggle{
  position: absolute;
  top: -50vh;
  left: 50%;
  background: url("http://lztimg.oss-cn-qingdao.aliyuncs.com/images/20210203/share03.png") center no-repeat;
  width: 1.6rem;
  height: 1.6rem;
  margin-left: -0.8rem;
}

// 进度条
.vcp-slider{
  background-color: rgba(89,83,84,1);
}
.vcp-slider .vcp-slider-track{
  background-color: #fff;
}

// 控制条背景
.vcp-panel-bg{
  background: none;
}

// 时间显示
.vcp-timelabel{
  // display: none;
  text-align: center;
  width: 100%;
  font-size: 0.28rem;
  line-height: 1.8;
  padding: 0;
}

video.js + flv.js 播放.flv直播数据

因为IOS不支持MSE,所以,FLV视频不能在IOS下播放

参考:

如何在iOS WebView中播放FLV视频?

Can I use... Support tables for HTML5, CSS3, etc

给video绑定ended事件,当直播流结束时会触发(不要循环播放:loop:false);

step1:引入

// 在index.html头文件引入
    <link href="https://unpkg.com/video.js/dist/video-js.css" rel="stylesheet">
    <script src="https://unpkg.com/video.js/dist/video.min.js"></script>
    <script src="https://unpkg.com/flv.js/dist/flv.min.js"></script>
    <script src="https://unpkg.com/videojs-flvjs/dist/videojs-flvjs.min.js"></script>

step2: 在组件中创建容器

<template>
    <div class="video">
      <video id="videojs-flvjs-player" class="video-js liveVideo vjs-default-skin vjs-big-play-centered" width="100vw" height="100vh"
             x5-video-orientation="portraint" ref="videojs"
             webkit-playsinline='true' playsinline='true' x-webkit-airplay='true'
             x5-video-player-type='h5' x5-video-player-fullscreen='true' x5-video-ignore-metadata='true'>

      </video>
    </div>
</template>

step3: 设置播放器

<script>
  export default {
    mounted() {
    var flvUrl = this.infoData.room.mixedPlayURL;

    var player = videojs('videojs-flvjs-player', {
      techOrder: ['html5', 'flvjs'],
      flvjs: {
        mediaDataSource: {
          isLive: true,
          cors: true,
          withCredentials: false,
        },
      },
      sources: [{
        src: flvUrl,
        type: 'video/mp4'
      }],
      autoplay: true,
      loop: false,	// 需要捕获直播结束事件,一定要禁止循环播放
      controls: true,
      preload: "auto",
      poster: this.infoData.room.liveCover
    }, function onPlayerReady() {
      console.log('player ready')

      player.on('error', (err) => {
        console.log('first source load fail')

        player.src({
          src: flvUrl,
          type: 'video/x-flv'
        });

        player.ready(function () {
          console.log('player ready')
          player.load();
          player.play();
        });
      })

	  // 绑定直播结束事件
      player.on('ended', () => {
        console.log("直播结束")
      })

	  // 绑定加载到可以播放的事件
      player.on("canplaythrough", function () {
        console.log("视频源数据加载完成")
      })

    });
  },
  }
</script>

此时,播放器可以使用了

step4: 修改默认样式

<style>
/*播放按钮*/
.liveVideo .vjs-big-play-button {
  background: url("http://lztimg.oss-cn-qingdao.aliyuncs.com/images/20210203/share03.png") center no-repeat;
  height: 2.2em;
  border: none;
}

/*去掉自带的播放按钮样式*/
.liveVideo .vjs-big-play-button .vjs-icon-placeholder:before {
  content: "";
}

/*隐藏控制条*/
.liveVideo .vjs-control-bar {
  display: none !important;
}

/*更改加载动画*/
.liveVideo .vjs-loading-spinner {
  border: none;
  background: url("https://lztimg.oss-cn-qingdao.aliyuncs.com/ips/images/20210201/loading.gif") center no-repeat;
  width: 1.6rem;
  height: 1rem;
  background-size: 60%;
  margin-left: -0.8rem;
}

/*去除原生加载动画*/
.liveVideo .vjs-loading-spinner:before,
.liveVideo .vjs-loading-spinner:after {
  border: none;
  animation: none !important;
}
</style>

前端苦设备适配久矣!


参考文章:

video.js的一些监听事件汇总

video.js 结合 flv.js播放flv视频

移动端HTML5 video 视频播放优化实践

播放器 SDK TCPlayerLite 腾讯云

Video.js Documentation


很多未尽之处,在日后想起便会更新~
撒花,散会~