vue项目video视频播放多种实现方式

一、vue-video-player

安装
npm i vue-video-player
引入

import { videoPlayer } from "vue-video-player";
import "video.js/dist/video-js.css";
import "vue-video-player/src/custom-theme.css";

index.vue

<template>
<div>
<video-player
                class="video-player vjs-custom-skin"
                ref="videoPlayer"
                name="videoPlayer"
                id="video"
                :playsinline="true"
                :globalOptions="globalSetting"
                :options="playerOptions"
                @play="onPlayerPlay($event)"
                @pause="onPlayerPause($event)"
                @ended="onPlayerEnded($event)"
                @waiting="onPlayerWaiting($event)"
                @timeupdate="onPlayerTimeupdate($event)"
                @statechanged="playerStateChanged($event)"
                @canplaythrough="onPlayerCanplaythrough($event)"
                @ready = "playerReadied"
        ></video-player>
</div>
</template>
<script>
import { videoPlayer } from "vue-video-player";
    import "video.js/dist/video-js.css";
    import "vue-video-player/src/custom-theme.css";
    import commentsList from "@/components/commentsList";
    export default {
        name: "showVideo",
        components: {
            videoPlayer
        },
        data() {
            return {
                playTime:'',
                current:'',
                playerOptions: {
                    playbackRates: [0.5, 1.0, 1.5, 2.0], // 可选的播放速度
                    autoplay: false, // 如果为true,浏览器准备好时开始回放。
                    muted: false, // 默认情况下将会消除任何音频。
                    loop: false, // 是否视频一结束就重新开始。
                    preload: "auto", // 建议浏览器在<video>加载元素后是否应该开始下载视频数据。auto浏览器选择最佳行为,立即开始加载视频(如果浏览器支持)
                    language: "zh-CN",
                    aspectRatio: "16:9", // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3")
                    fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。
                    sources: [
                        {
                            type: "video/mp4", // 类型
                            src:
                                "xxxxxx.mp4" // url地址
                        }
                    ],
                    poster: "", // 封面地址
                    notSupportedMessage: "此视频暂无法播放,请稍后再试", // 允许覆盖Video.js无法播放媒体源时显示的默认信息。
                    controlBar: {
                        timeDivider: true, // 当前时间和持续时间的分隔符
                        durationDisplay: true, // 显示持续时间
                        remainingTimeDisplay: false, // 是否显示剩余时间功能
                        fullscreenToggle: true // 是否显示全屏按钮
                    },
                },
            };
        },
        beforeRouteLeave(){
            this.$refs.videoPlayer.player.pause()
        },
        methods: {
            // 播放回调
            onPlayerPlay(player) {
                console.log("player play!", player);
            },

            // 暂停回调
            onPlayerPause(player) {
                console.log("player pause!", player);
            },

            // 视频播完回调
            onPlayerEnded($event) {
                console.log(player);
            },
            // DOM元素上的readyState更改导致播放停止
            onPlayerWaiting(player) {
                let time = localStorage.getItem("cacheTime")
                if(player.cache_.currentTime - Number(time) > 0.1){
                    this.current = Number(time)
                    this.playerReadied(player)
                }else{
                    this.current = player.cache_.currentTime
                }
            },

            // 已开始播放回调
            onPlayerPlaying($event) {
                // console.log(player)
            },

            // 当播放器在当前播放位置下载数据时触发
            onPlayerLoadeddata($event) {
                // console.log(player)
            },

            // // 当前播放位置发生变化时触发。
            onPlayerTimeupdate(player) {
                this.playTime = player.cache_.currentTime
                let playTime = player.cache_.currentTime
                setTimeout(function () {
                    localStorage.setItem("cacheTime",playTime)
                },500)


                let time = localStorage.getItem("cacheTime")
                if(player.cache_.currentTime - Number(time) > 2){
                    this.current = Number(time)
                    this.playerReadied(player)
                }else{
                    this.current = player.cache_.currentTime
                }
            },

            //媒体的readyState为HAVE_FUTURE_DATA或更高
            onPlayerCanplay(player) {
                // console.log('player Canplay!', player)
            },

            //媒体的readyState为HAVE_ENOUGH_DATA或更高。这意味着可以在不缓冲的情况下播放整个媒体文件。
            onPlayerCanplaythrough(player) {
                // console.log('player Canplaythrough!', player)
            },

            //播放状态改变回调
            playerStateChanged(playerCurrentState) {
                // console.log('player current update state', playerCurrentState)
            },

            //将侦听器绑定到组件的就绪状态。与事件监听器的不同之处在于,如果ready事件已经发生,它将立即触发该函数。。
            playerReadied(player) {
                // console.log('example player 1 readied', player);
                player.currentTime(this.current)
            }
        }
    };
</script>

<style lang="less">
    .vjs-custom-skin > .video-js .vjs-big-play-button {
        background-color: rgba(0,0,0,0.45);
        font-size: 3.0em;
        /* border-radius: 50%; */
        height: 1.5em !important;
        line-height:1.5em !important;
        margin-top: -1em !important;
    }
    /*这里用了第三方vue-video-player插件,但这个插件有bug,设置globalSetting:{controls:true}隐藏进度条不生效,故可设置插件样式进行隐藏vjs-progress-contro*/
    .vjs-progress-control {
        /*visibility:hidden;       // 隐藏进度条*/
    }

</style>

二、原生video标签播放文件,除了样式丑点没啥毛病

index.vue

<template>
<div>
<video
                  src="xxxxx.mp4"
                  :controls="videoOptions.controls"
                  class="video-js vjs-big-play-centered vjs-fluid"
                  webkit-playsinline="true"
                  playsinline="true"
                  x-webkit-airplay="allow"
                  x5-playsinline
                  style="width: 100%;"
                  @play="onPlayerPlay"
                  @pause="onPlayerPause"
                  @seeking="seeking"
                  autoplay="autoplay"
                  ref="video">
            </video>
</div>
</template>

<script>
export default {
        name: "showVideo",
        data() {
            return {
                videoOptions: {
                    controls:true,
                    src:
                        "xxxxxxx.mp4", // url地址
                },
                player: null,
                playTime:'',
                seekTime:'',
                current:'',
        },
        beforeRouteLeave(){
            //
        },
        mounted() {
            this.initVideo();
        },
        methods: {
                initVideo() {
                //原生初始化视频方法
                let myVideo = this.$refs.video;
                //ontimeupdate
                  myVideo.ontimeupdate = function() {myFunction()};
                  let _this = this;

                  function myFunction(){
                      let playTime = myVideo.currentTime
                      setTimeout(function () {
                          localStorage.setItem("cacheTime",playTime)
                      },500)
                      let time = localStorage.getItem("cacheTime")
                      // 当前播放位置发生变化时触发。
                      if(playTime - Number(time) > 2){
                          myVideo.currentTime = Number(time)
                      }else{
                      }
                  };
              
            // 播放回调
            onPlayerPlay(player) {
                // this.globalSetting = true
                console.log("player play!", player);
                // document.getElementsByClassName("vjs-control-bar").style.display = "block";
                // document.getElementsByClassName("vjs-control-bar").style.display = "block";
            },

            // 暂停回调
            onPlayerPause(player) {
                // this.globalSetting.controls = false;
                // console.log("player pause!", player);
                // var video = document.getElementById("video");
                // video.controls=false;
                // document.getElementsByClassName("vjs-control-bar").style.display = "none";
            },
            },

        beforeDestroy() {
            if (this.player) {
                this.player.dispose()
            }
        }
        }
</script>

三、video.js插件

1、先安装video.js...

index.vue

<template>
<div>
<video
                id="myVideo"
                ref="myvideo"
                class="video-js vjs-big-play-centered vjs-fluid"
                controls
                preload="auto"
                width="100%"
                height="100%"
                @on="onPlayerPlay"
                @pause="onPlayerPause"
                :poster="videoOptions.src"
        >
            <source
                    type="video/mp4"
                    :src="videoOptions.src"
            >
        </video>
</div>
</template>
<script>
//直接引入videojs会报错 
import _videojs from 'video.js'
const videojs = window.videojs || _videojs
import 'video.js/dist/video-js.css'
export default {
name: "showVideo",
data(){
  return {
                videoOptions: {
                    controls:true,
                    src: "xxxxxxxxx.mp4", // url地址
                },
                player: null
  }
},
mounted() {
            this.initVideo();
          
        },
methods: {
            initVideo() {
                //页面dom元素渲染完毕,执行回调里面的方法
                let options = {
                    controls: true,
                    //自动播放属性,muted:静音播放
                    autoplay: false,
                    //建议浏览器是否应在<video>加载元素后立即开始下载视频数据。
                    preload: "auto",
                    //设置视频播放器的显示宽度(以像素为单位)
                    // width: "800px",
                    //设置视频播放器的显示高度(以像素为单位)
                    // height: "400px",
                    controlBar:{
                        playToggle:true
                    }
                };
                this.player = videojs(this.$refs.myvideo,options,function() {
                    let _this = this;
                    this.on('timeupdate', function() {
                        this.playTime = this.currentTime()
                        let playTime = this.currentTime()
                        setTimeout(function () {
                            localStorage.setItem("cacheTime",playTime)
                        },500)


                        let time = localStorage.getItem("cacheTime")
                        if(this.currentTime() - Number(time) > 2){
                            this.current = Number(time)
                            this.currentTime(this.current)
                        }else{
                            this.current = this.currentTime()
                        }
                    })

                    this.on('ended', function() {
                        console.log('ended',"播放结束")
                    })

                    this.on('progress', function() {
                        console.log('progress',"开始播放")
                    })

                    this.on('error', function() {
                        _this.$message.warning("异常,无法播放")
                    })
                })
            }
}
}

</script>
<style lang="less">
    /*修改播放器样式*/
    .video-js{
        width: 120%!important;
        height: 100%!important;
    }
    .video-js .vjs-big-play-button {
        background-color: rgba(0,0,0,0.45);
        font-size: 3.0em;
        border-radius: 50%;
        height: 1.5em !important;
        line-height:1.5em !important;
        margin-top: -1em !important;
    }
    .vjs-paused .vjs-big-play-button,
    .vjs-paused .vjs-big-play-button {
        display: block!important;
    }
    .myVideo-dimensions {
        width: 100%!important;
        height: 100%!important;
        display: block!important;
    }
    .vjs-poster{
        background-size: 100% 100%!important;
    }
</style>

推荐阅读更多精彩内容