使用Video.js 播放视频测试

3,404 阅读4分钟

一、安装依赖

yarn add video.js //安装video.js
yarn add videojs-contrib-hls // 播放流的话需要安装 hls插件

二、引入video.js

在plugins文件夹下创建 hls.js

import Vue from 'vue';
import 'videojs-contrib-hls';
const hls = require('videojs-contrib-hls');
Vue.use(hls);

在 nuxt.config.js 中引用video.js样式


css: ['video.js/dist/video-js.css']

三、在使用video.js的页面中引用 video.js

import Videojs from 'video.js'; // 引入Videojs

1、测试使用video.js

初始化videoJs

 initVideo(nowPlayVideoUrl) {
      let that = this; // 重定向this
      // 这些options属性也可直接设置在video标签上,见 muted
      let options = {
        controls: true, //确定播放器是否具有用户可以与之交互的控件。没有控件,启动视频播放的唯一方法是使用autoplay属性或通过Player API。
        // autoplay: "muted",//自动播放属性,muted:静音播放
        preload: 'auto', //预加载 auto 自动
        fluid: true, // 自适应宽高
        language: 'zh-CN', // 设置语言
        // poster: require('@/assets/images/train/1.png'), //播放前显示的视频画面,播放开始之后自动移除。通常传入一个URL
        // inactivityTimeout: false,//显示时间
        // width:'100%',
        // height:'210px'
        sources: [
          // 注意,如果是以option方式设置的src,是不能实现 换台的 (即使监听了nowPlayVideoUrl也没实现)
          {
            src: nowPlayVideoUrl,
            type: 'application/x-mpegURL', // 告诉videojs,这是一个hls流
          },
        ],
        controlBar: false,
      };
      // videojs的第一个参数表示的是,文档中video的id
      let myPlayer = Videojs('videoPlayer', options, function onPlayerReady() {
        console.log('onPlayerReady 中的this指的是:', this); // 这里的this是指Player,是由Videojs创建出来的实例
        that.volumeProgress();
        this.on('loadedmetadata', function () {});
        // 视频播放时更新当前播放进度
        this.on('timeupdate', function () {
          that.durationimeVue(); // 更新播放进度
          if (!that.ischange) {
            // 当拖拽进度条是不更新进度条
            that.cacheProgress();
          }
        });
        // 视频 缓冲进度
        this.on('progress', function () {});
        this.on('play', function () {
          //播放
          that.playstart = true; //控制显示播放暂停按钮
        });
        this.on('pause', function () {
          //暂停
          that.playstart = false; //控制显示播放暂停按钮
        });
        this.on('volumechange', function (e) {
          //音量改变
          if (!that.volumeChange) {
            that.volumeProgress();
          }
        });
      });
      that.myPlayer = myPlayer
温馨提示;

onPlayerReady() 方法中是video 初始化完成后触发的事件,this.on('××××××××', function () {}); 是初始化完成后或视频播放过程中 触发的事件;

监听事件\ this 指的是video实例
    this.on('suspend', function() {//延迟下载
        console.log("延迟下载")
    });
    this.on('loadstart', function() { //客户端开始请求数据
        console.log("客户端开始请求数据")
    });
    this.on('progress', function() {//客户端正在请求数据
        console.log("客户端正在请求数据")
    });
    this.on('abort', function() {//客户端主动终止下载(不是因为错误引起)
        console.log("客户端主动终止下载")
    });
    this.on('error', function() {//请求数据时遇到错误
        console.log("请求数据时遇到错误")
    });
    this.on('stalled', function() {//网速失速
        console.log("网速失速")
    });
    this.on('play', function() {//开始播放
        console.log("开始播放")
    });
    this.on('pause', function() {//暂停
        console.log("暂停")
    });
    this.on('loadedmetadata', function() {//成功获取资源长度
        console.log("成功获取资源长度")
    });
    this.on('loadeddata', function() {//渲染播放画面
        console.log("渲染播放画面")
    });
    this.on('waiting', function() {//等待数据,并非错误
        console.log("等待数据")
    });
    this.on('playing', function() {//开始回放
        console.log("开始回放")
    });
    this.on('canplay', function() {//可以播放,但中途可能因为加载而暂停
        console.log("可以播放,但中途可能因为加载而暂停")
    });
    this.on('canplaythrough', function() { //可以播放,歌曲全部加载完毕
        console.log("可以播放,歌曲全部加载完毕")
    });
    this.on('seeking', function() { //寻找中
        console.log("寻找中")
    });
    this.on('seeked', function() {//寻找完毕
        console.log("寻找完毕")
    });
    this.on('timeupdate', function() {//播放时间改变
        console.log("播放时间改变")
    });
    this.on('ended', function() {//播放结束
        console.log("播放结束")
    });
    this.on('ratechange', function() {//播放速率改变
        console.log("播放速率改变")
    });
    this.on('durationchange', function() {//资源长度改变
        console.log("资源长度改变")
    });
    this.on('volumechange', function() {//音量改变
        console.log("音量改变")
    });
常用方法
player.play(); // 播放
player.pause(); // 暂停
player.currentTime(); // 播放时长、可以根据此方法更改播放时间 player.currentTime(time);
player.duration(); // 视频总播放时长,
player.volume(); // 声音,可以根据 player.volume(volume) 改变声音 声音大小(0-1之间)
player.muted(Boolean) // 是否静音
player.requestPictureInPicture() //开启画中画
player.buffered(); 缓冲,就是返回下载了多少
player.bufferedPercent();百分比的缓冲
player.width(); //获取宽度 player.width(640) 设置宽度
player.height(); //获取高度 设置高度player.height(480);
视频状态与播放状态
player.controls();//是否有默认控制条
player.currentTime(); = value; //当前播放的位置,赋值可改变位置
player.startTime(); //一般为0,如果为流媒体或者不从0开始的资源,则不为0
player.duration(); //当前资源长度 流返回无限
player.paused(); //是否暂停
player.defaultPlaybackRate(); = value;//默认的回放速度,可以设置
player.playbackRate(); = value;//当前播放速度,设置后马上改变
player.played(); //返回已经播放的区域,TimeRanges,关于此对象见下文
player.seekable();//返回可以seek的区域 TimeRanges
player.ended();//是否结束
player.autoPlay(); //是否自动播放
player.loop(); //是否循环播放
自定义全屏退出全屏按钮
//开启全屏
let playerHtml = this.$refs.videobox; // 包裹video标签 bom
if (playerHtml.requestFullscreen) {
    playerHtml = playerHtml.requestFullscreen();
} else if (playerHtml.mozRequestFullScreen) {
    playerHtml = playerHtml.mozRequestFullScreen();
} else if (playerHtml.msRequestFullscreen) {
    playerHtml = playerHtml.msRequestFullscreen();
} else if (playerHtml.webkitRequestFullscreen) {
    playerHtml = playerHtml.webkitRequestFullScreen();
}
//退出全屏
if (document.exitFullscreen) {
  document.exitFullscreen();
} else if (document.msExitFullscreen) {
  document.msExitFullscreen();
} else if (document.mozCancelFullScreen) {
  document.mozCancelFullScreen();
} else if (document.webkitExitFullscreen) {
  document.webkitExitFullscreen();
}

四、附上代码

<template>
  <div ref="videobox" :class="iFullScreen ? 'fullscreenbox ' : 'videobox'">
    <video id="videoPlayer" class="video-js"></video>
    <!-- 自定义组件 全屏 画中画 start -->
    <div class="individualcontrol">
      <div class="fullscreen">
        <img
          v-if="!iFullScreen"
          class="w-20 h-20 transform rotate-180"
          :src="require('@/assets/match/img/full.png')"
          @click="fullscreen"
        />
        <img
          v-else
          class="w-20 h-20 transform rotate-180"
          :src="require('@/assets/match/img/quit.png')"
          @click="quitscreen"
        />
      </div>
      <div class="PIP" @click="pipclick">
        <img
          class="w-20 h-20 transform rotate-180"
          :src="require('@/assets/match/img/pip.png')"
        />
      </div>
    </div>
    <!-- 自定义组件 全屏 画中画 end -->
    <!-- 自定义组件 后退 暂停 播放 快进 播放进度条 下一个 start -->
    <div class="controlBar">
      <!-- 后退 start -->
      <div class="retreat w-20" @click="currentTimeRetreat">
        <img
          class="w-20 h-20 transform rotate-180"
          :src="require('@/assets/match/img/return.png')"
        />
      </div>
      <!-- 后退 end -->
      <!-- 播放暂停 start-->
      <div class="play w-20" @click="comtrol_play">
        <img
          v-if="playstart"
          class="w-20 h-20 rotate-180"
          :src="require('@/assets/match/img/pause.png')"
        />
        <img
          v-else
          class="w-20 h-20 rotate-180"
          :src="require('@/assets/match/img/play.png')"
        />
      </div>
      <!-- 播放暂停 end-->
      <!-- 快进 start-->
      <div class="fastforward w-20" @click="currentTimeFF">
        <img
          class="w-20 h-20 rotate-180"
          :src="require('@/assets/match/img/return.png')"
        />
      </div>
      <!-- 快进 end-->
      <!-- 进度条 start-->
      <div class="broadcastpace">
        <span>{{ video.currentTime }}</span>
        <div class="progressbar">
          <el-slider
            v-model="Barvalue"
            :show-tooltip="false"
            @change="Barchange"
            @mousedown.native="ischange = true"
            @mouseup.native="ischange = false"
          ></el-slider>
        </div>
        <span>{{ video.duration }}</span>
      </div>
      <!-- 进度条 end-->
      <!-- 声音 start-->
      <div class="volume">
        <div class="iconVolume" @click="volumeClick">
          <img
            v-if="video.volumeval != 0"
            class="w-20 h-20"
            :src="require('@/assets/match/img/loud.png')"
          />
          <img
            v-else
            class="w-20 h-20"
            :src="require('@/assets/match/img/turndown.png')"
          />
        </div>
        <div class="sliderVolume">
          <el-slider
            v-model="video.volumeval"
            vertical
            height="100px"
            @change="volumeBarchange"
            @mousedown.native="volumeChange = true"
            @mouseup.native="volumeChange = false"
          >
          </el-slider>
        </div>
      </div>
      <!-- 声音 end-->
      <div></div>
      <!-- 下一个 start-->
      <div class="next">
        <img
          class="w-20 h-20 transform -rotate-90"
          :src="require('@/assets/match/img/next.png')"
        />
      </div>
      <!-- 下一个 end-->
    </div>
    <!-- 自定义组件 后退 暂停 播放 快进 播放进度条 下一个 end -->
  </div>
</template>
<script>
import { rateProgress } from '@/utils/index'; // 正则
import Videojs from 'video.js'; // 引入Videojs
export default {
  data() {
    return {
      video: {
        Src: 'https://vjs.zencdn.net/v/oceans.mp4', // 视频链接
        // Src: 'http://××××××××××××:1935/vod//tstv1/20220310/1750003900_mp4/175000_3900_1000k_(1013_00_1275_36)_bvs_mp4/tzwj_video.m3u8',
        currentTime: '0:00:00',
        duration: '0:00:00',
        volumeval: 0,
      },
      playstart: false, // 是否正在播放
      controlBarhide: false, // 是否要隐藏控制条
      iFullScreen: false, // 是否全屏
      Barvalue: 0, // 视频 播放进度
      ischange: false, // 是否拖拽进度条
      volumeChange: false, // 拖动声音进度条
      Barsetvalue: '',
      CanDragDrop: true, // 是否可快进
      myPlayer: null, // 播放器
    };
  },
  mounted() {
    this.initVideo(this.video.Src);
    // 全屏监听
    if (document.addEventListener) {
      document.addEventListener(
        'webkitfullscreenchange',
        this.exitHandler,
        false
      );
      document.addEventListener('mozfullscreenchange', this.exitHandler, false);
      document.addEventListener('fullscreenchange', this.exitHandler, false);
      document.addEventListener('MSFullscreenChange', this.exitHandler, false);
    }
  },
  methods: {
    initVideo(nowPlayVideoUrl) {
      let that = this; // 重定向this
      // 这些options属性也可直接设置在video标签上,见 muted
      let options = {
        controls: true, //确定播放器是否具有用户可以与之交互的控件。没有控件,启动视频播放的唯一方法是使用autoplay属性或通过Player API。
        // autoplay: "muted",//自动播放属性,muted:静音播放
        preload: 'auto', //预加载 auto 自动
        fluid: true, // 自适应宽高
        language: 'zh-CN', // 设置语言
        sources: [
          // 注意,如果是以option方式设置的src,是不能实现 换台的 (即使监听了nowPlayVideoUrl也没实现)
          {
            src: nowPlayVideoUrl,
            // type: 'application/x-mpegURL', // 告诉videojs,这是一个hls流
          },
        ],
        controlBar: false,
      };
      // videojs的第一个参数表示的是,文档中video的id
      let myPlayer = Videojs('videoPlayer', options, function onPlayerReady() {
        console.log('onPlayerReady 中的this指的是:', this); // 这里的this是指Player,是由Videojs创建出来的实例
        that.volumeProgress(); // 更新播放进度
        this.on('loadedmetadata', function () {});
        // 视频播放时更新当前播放进度
        this.on('timeupdate', function () {
          that.durationimeVue(); // 更新播放进度
          if (!that.ischange) {
            // 当拖拽进度条是不更新进度条
            that.cacheProgress();
          }
        });
        this.on('play', function () {
          //播放
          that.playstart = true; //控制显示播放暂停按钮
        });
        this.on('pause', function () {
          //暂停
          that.playstart = false; //控制显示播放暂停按钮
        });
        this.on('volumechange', function (e) {
          //音量改变
          if (!that.volumeChange) {
            that.volumeProgress();
          }
        });
      });
      that.myPlayer = myPlayer;
    },
    // 视频播放暂停
    comtrol_play() {
      if (this.myPlayer.paused()) {
        this.myPlayer.play();
      } else {
        this.myPlayer.pause();
      }
    },
    // 视频后退
    currentTimeRetreat() {
      if (this.myPlayer.currentTime() > 10) {
        let time = this.myPlayer.currentTime() - 10;
        // 当前播放时间小于10  可以快退减10
        this.myPlayer.currentTime(time);
      } else {
        //   否则就回到起点
        this.myPlayer.currentTime(0);
      }
    },
    // 视频快进
    currentTimeFF() {
      if (
        this.myPlayer.currentTime() < this.myPlayer.duration() &&
        this.CanDragDrop
      ) {
        // 当前播放时间小于总时间 并且可以快进 可以快进加10
        let time = this.myPlayer.currentTime() + 10;
        this.myPlayer.currentTime(time);
      }
    },
    //更新播放时长
    durationimeVue() {
      let result = this.myPlayer.duration(); // 视频总时长
      let result2 = this.myPlayer.currentTime(); // 当前播放时长
      this.video.duration = rateProgress(result);
      this.video.currentTime = rateProgress(result2);
      console.log(result);
    },
    // 视频播放进度条
    cacheProgress() {
      let duration = this.myPlayer.duration();
      this.Barvalue = (this.myPlayer.currentTime() / duration) * 100;
    },
    // 进度条拖拽
    Barchange(e) {
      let currentProgress = (e / 100) * this.myPlayer.duration();
      this.myPlayer.currentTime(currentProgress);
    },
    // 声音进度条拖拽
    volumeBarchange(e) {
      this.myPlayer.volume(e / 100);
    },
    // 声音进度条
    volumeProgress() {
      let volume = this.myPlayer.volume();
      this.video.volumeval = volume * 100;
    },
    // 静音
    volumeClick() {
      if (this.video.volumeval != 0) {
        this.myPlayer.volume(0);
      } else {
        this.myPlayer.volume(50 / 100);
      }
    },
    // 全屏播放
    fullscreen() {
      let playerHtml = this.$refs.videobox;
      if (playerHtml.requestFullscreen) {
        playerHtml = playerHtml.requestFullscreen();
      } else if (playerHtml.mozRequestFullScreen) {
        playerHtml = playerHtml.mozRequestFullScreen();
      } else if (playerHtml.msRequestFullscreen) {
        playerHtml = playerHtml.msRequestFullscreen();
      } else if (playerHtml.webkitRequestFullscreen) {
        playerHtml = playerHtml.webkitRequestFullScreen();
      }
      //   this.iFullScreen = true; // 改变是否全屏状态
    },
    // 退出全屏
    quitscreen() {
      if (document.exitFullscreen) {
        document.exitFullscreen();
      } else if (document.msExitFullscreen) {
        document.msExitFullscreen();
      } else if (document.mozCancelFullScreen) {
        document.mozCancelFullScreen();
      } else if (document.webkitExitFullscreen) {
        document.webkitExitFullscreen();
      }
      //   this.iFullScreen = false; // 改变是否全屏状态
    },
    //监听esc退出全屏
    exitHandler() {
      if (this.iFullScreen) {
        this.iFullScreen = false;
      } else {
        this.iFullScreen = true;
      }
    },
    // 画中画
    pipclick() {
      let whetherNot = document.pictureInPictureElement;
      console.log(whetherNot);
      if (whetherNot) {
        this.myPlayer.requestPictureInPicture();
      } else {
        this.myPlayer.requestPictureInPicture();
      }
    },
  },
};
</script>
<style lang="scss" scoped>
...
</style>

效果展示

企业微信截图_16469819516661.png