需要自行准备一个视频文件,并且提取视频中的文字内容,文字内容包含时间跟文字的切分,即按照时间断句的形式,比如[00:05]第一句话,[00:10]第二句话;数据准备好以后,安装videoPlayer,用于播放视频文件。下面就是完整的视频播放与文字内容双向联动的代码:
<template><divclass="app-container"><divstyle="display: flex"><divstyle="width: 65%"><el-cardstyle="margin-top: 10px;"> 视频画面 <divclass="demo"><video-playerclass="video-player vjs-custom-skin"ref="videoPlayer":playsinline="true"@timeupdate="onPlayerTimeupdate($event)":options="playerOptions"></video-player></div></el-card></div><divstyle="width: 34%"><el-cardid="cardContent"style="width: 100%;margin-top: 10px;margin-left: 10px;display: block;overflow: auto;"><span>视频文字内容</span><divv-if="contentBlank"style="text-align: center;">暂无数据</div><divv-if="!contentBlank"class="demo1"><divid="container"><divstyle="overflow-y: auto"id="containerContent"><!-- <p style="white-space: pre-line" v-html="dateConList"></p> --><ulstyle="list-style-type:none;margin:0;padding:0"><liv-for="(item,index) in startTimeSentenceList":key="index"><el-link@click="posStartTime(item.startTime)"><pstyle="white-space: pre-line"v-html="item.sentence"></p></el-link></li></ul></div></div></div></el-card></div></div></div></template><script>import { videoPlayer } from"vue-video-player"; import"video.js/dist/video-js.css"; import"videojs-contrib-hls"; exportdefault { name: "VedioContent", data() { return { currentArray:[], currentTimeRangeMap:null, dateConList: "", startTimeSentenceList:[], contentBlank: false, playerOptions: { playbackRates: [0.5, 1.0, 1.5, 2.0], // 可选的播放速度autoplay: true, // 如果为true,浏览器准备好时开始回放。muted: false, // 默认情况下将会消除任何音频。loop: false, // 是否视频一结束就重新开始。preload: "auto", // 建议浏览器在<video>加载元素后是否应该开始下载视频数据。auto浏览器选择最佳行为,立即开始加载视频(如果浏览器支持)language: "zh-CN", aspectRatio: "16:10", // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3")fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。sources: [ { type: "video/mp4", // 类型src: require("vedio.mp4"), // url地址 }, ], poster: "", // 封面地址notSupportedMessage: "此视频暂无法播放,请稍后再试", // 允许覆盖Video.js无法播放媒体源时显示的默认信息。controlBar: { timeDivider: true, // 当前时间和持续时间的分隔符durationDisplay: true, // 显示持续时间remainingTimeDisplay: false, // 是否显示剩余时间功能fullscreenToggle: true, // 是否显示全屏按钮 } }, }; }, components: {videoPlayer}, activated() { this.queryVedioContent(); }, deactivated() { }, methods: { posStartTime(posStartTime){ letmin=posStartTime.split(":")[0] letsec=posStartTime.split(":")[1] letsecNum=Number(min*60)+Number(sec) this.$refs.videoPlayer.player.currentTime(secNum) this.$refs.videoPlayer.player.play() }, // 当前播放位置发生变化时触发。onPlayerTimeupdate($event) { letdisplayElm=document.getElementsByClassName("vjs-current-time-display")[0] if(displayElm!=null&&this.currentTimeRangeMap!=null&&this.currentArray.indexOf(displayElm.textContent)===-1){ letcurrenttime=displayElm.textContentletmin=currenttime.split(":") if(min[0].length==1){ currenttime="0"+currenttime } for(constkeyinthis.currentTimeRangeMap){ if(currenttime>=key&¤ttime<=this.currentTimeRangeMap[key]){ letfocusElement=document.getElementById(key+","+this.currentTimeRangeMap[key]) focusElement.parentElement.style.color="red" }else{ letdisfocusElement=document.getElementById(key+","+this.currentTimeRangeMap[key]) disfocusElement.parentElement.style.color="" } } } }, //视频内容分析查看queryVedioContent(id) { this.contentBlank=false; this.playerOptions['sources'][0]['src'] =""; //getContents(query).then((response) => {// if (response.ret === 200) {this.dateConList=response.data.contentval; this.currentTimeRangeMap=response.data.timeRangeMap; this.startTimeSentenceList=response.data.startTimeSentenceListthis.playerOptions['sources'][0]['src'] =response.data.vediosrc; //} else {// this.playerOptions['sources'][0]['src'] = "";// this.dateConList = "";// this.contentBlank = true;// }// }); }, }, }; </script><stylelang="scss"scoped>.demo{ width: 100%; height: calc(100vh - 150px); /deep/video{ object-fit: fill; // 消除播放器两边的黑色留白 (object-fit 知识详见下文拓展部分) } /* 视频开始的按钮样式 *//deep/.video-js.vjs-big-play-button{ // border-width: 3px;// border-color: rgb(255, 255, 255);// border-style: solid;// border-radius: 50%;// width: 56px;// height: 56px;// line-height: 50px;background-color: rgba(0,0,0,0); position: absolute; // top: 0;// bottom: 0;// left: 0;// right: 0;margin: auto; } /* 滚动条的样式 *//deep/.video-js.vjs-control-bar{ background-color: rgba(43, 51, 63, 0); } /deep/.video-js.vjs-play-progress{ background-color: rgb(238,191,0); } /deep/.video-js.vjs-load-progressdiv{ background-color: rgb(255, 255, 255); } } .demo1{ width: 100%; height: calc(100vh - 200px); } </style>
主要思想是通过@timeupdate="onPlayerTimeupdate($event)"监控视频播放时间然后找到对应时间的文字内容,通过posStartTime(item.startTime)"再点击时间文字的时候,定位到视频的时间进行播放。