uni-app小程序视频播放字幕滚动

羅 小子 前端评论2171字数 4081阅读13分36秒阅读模式

起因:淘宝小店接一个需求,客户需要在视频播放的同时,实现字幕每帧的高亮以及滚动,同时满足拖动字幕实现快进以及底部进度条拖动快进,后退,暂停,播放。

根据上面的需求描述,可以分为以下几个功能点:文章源自羅小子-https://luozz.cn/uni-app-wechat-video/

  1. 视频播放
  2. 根据播放时间高亮对应字幕以及字幕滚动到顶部
  3. 字幕拖动到某一处,就播放到这个时间点上
  4. 底部进度条的快进,后退,暂停,播放。

功能点1:视频播放

上面是拆分出来的功能点,现做第一个,实现视频的播放。视频播放在uni-app中可以使用video标签。这个很简单,官方有案例。文章源自羅小子-https://luozz.cn/uni-app-wechat-video/

<video id="myVideo" src="视频地址" ></video>

功能点2:根据播放时间高亮对应字幕以及字幕滚动到顶部

接下来做第二个需求,字幕;字幕客户那边给的是一个.srt的字幕文件,文件不能在小程序中直接打开,可以通过请求的方式获取里面的文本信息。获取到文本信息后,里面的内容要做处理,因为内容是有时间帧以及一些符合。文章源自羅小子-https://luozz.cn/uni-app-wechat-video/

uni-app小程序视频播放字幕滚动文章源自羅小子-https://luozz.cn/uni-app-wechat-video/

上面图片中就是.srt文件内容,接下来对文件内容进行处理;文章源自羅小子-https://luozz.cn/uni-app-wechat-video/

// view 代码片段
<scroll-view id="scrollView" scrollY @scroll="scrollEvent" class="eac" :scrollIntoView="scrollIndex" 
:style="{height:`${windowHeight}px`}">
   <view :id="`text${index}`" :data-id="index" :class="item.color ? 'textcss activeTxt' : 'textcss'"
            v-for="(item,index) in voaTextList" :key="index" @touchmove="touchmove"     @touchend="touchends">
        <text class="enSent">{{item.textEn}}</text>
        <text class="cnSent">{{item.textCn}}</text>
    </view>
</scroll-view>
<view class="line" ref="line" v-show="isLine">
       <u-divider text="播放此处" textPosition="right"></u-divider>
</view>


// 通过request请求,把返回的数据传入
parseSrt(srt) { // 处理符号
	srt = srt.trim();
	let list = srt.split('\n\n');
        let subs = [];
	for (let i = 0; i < list.length; i++) {
		let sub = {};
		let tmp = list[i].split('\n');
		sub.id = tmp[0];
		sub.time = tmp[1].replace(/,/g, '.');
		sub.startTime = this.timeToSec(sub.time.split(' --> ')[0]);
		sub.endTime = this.timeToSec(sub.time.split(' --> ')[1]);
		sub.textEn = tmp[2];
		sub.textCn = tmp[3];
		subs.push(sub);
	}
	return subs;
},
timeToSec(time) {
        let arr = time.split(':');
        return parseFloat(arr[0]) * 3600 + parseFloat(arr[1]) * 60 + parseFloat(arr[2]);
},
// 对字幕进行处理
loadSubtitles(subs) {
       let arr = [];
       for (let i = 0; i < subs.length; i++) {
             arr.push({
                   startTime: subs[i].startTime, 
                   endTime: subs[i].endTime,
                   textEn: subs[i].textEn,
                  textCn: subs[i].textCn,
                  index:i,
                 color: false
          });
      }
      return arr;
},
// 滚动到顶部
scrollEvent(e, i) {
      this.scrollContainerTop = e.detail.scrollTop
},

功能点3:字幕拖动到某一处,就播放到这个时间点上

在做这一步的时候卡了很久😒,试了很多中方法一度怀疑人生 😂,结果就是我把他想复杂了🤣。文章源自羅小子-https://luozz.cn/uni-app-wechat-video/

先分析一波,首先解决拖动的问题,拖动首先想到的是touch事件,用到touchmovetouchend,关于touch事件 有不了解的请点击MDN查看。拖动解决后,就要考虑当字幕拖动的时候怎么知道当前拖动到哪个位置上?首先用touchmove获取到top值然后展示“拖动到此处”的节点。当手指离开屏幕时touchend事件被触发,隐藏“拖动到此处”,获取scroll-view组件的位置和尺寸信息,通过横线坐标位置来判断。(横线坐标>=上一个坐标位置 && 横线坐标 < 下一个坐标位置 );具体代码如下:文章源自羅小子-https://luozz.cn/uni-app-wechat-video/

touchmove(e) {
    this.isLine = true;
    const line = uni.createSelectorQuery().in(this);
    line.select('.line').boundingClientRect((item, o) => {
	  this.lineTop = item.top
   }).exec()
  this.videoContext.pause()
}
touchends(e) {
    this.isLine = false;
     uni.createSelectorQuery().in(this).select('#scrollView').boundingClientRect().exec((res) => {
           const scrollViewRect = res[0] // scroll-view组件的位置和尺寸信息
           this.scrollContainerTop = scrollViewRect.top // 记录滚动容器的顶部位置
           uni.createSelectorQuery().in(this).selectAll('.textcss').boundingClientRect().exec((res) => {
                 const subtitleRects = res[0] // 每一行字幕的位置和尺寸信息
                // 在这里可以获取到每一行字幕的坐标位置和其他信息
                 subtitleRects.forEach((rect, i) => {
                      // 修正坐标,减去滚动容器的顶部位置
                      const subtitleTop = rect.top - this.scrollContainerTop
                       this.demo(i)
                })
        })
   })
},
demo(t) { 
     let a = this,
          e = this.heightArr,
          i = uni.createSelectorQuery();
    i.select("#text" + t).boundingClientRect(), i.selectViewport().scrollOffset(), i.exec((function(i) {
              e["text" + t] = i[0];
              let s = a.voaTextList,
                   o = a.voaTextList.length;
             if (o - 1 == t) {
                for (let r = 0, d = a.lineTop, c = 0; c < o; c++) {
                        if(d >= e["text" + c].top && d < e["text" + (c + 1)].top && (r = c)){
                                  a.videoContext.seek(s[r].startTime)
                                  a.videoContext.play()
                       } 
              }
        }}))
},

功能点4:底部进度条的快进,后退,暂停,播放。

这一步就很简单了,没有上一步这么复杂;只需要获取到视频的总时长,然后通过timeupdate事件监听播放帧,动态修改进度条长度就行。文章源自羅小子-https://luozz.cn/uni-app-wechat-video/

funtimeupdate(t) {
    var i = this.flag,
	 o = t.detail.currentTime,
	 e = t.detail.duration;
    this.currentTime = this.handleTime(o)
    this.time = o;
    let list = this.voaTextList;
    list.forEach((item, index) => {
	if (o >= item.startTime && o < item.endTime) {
		item.color = true;
		this.scrollIndex = `text${index}`
	} else {
		item.color = false;
	}
 })
   this.$set(this.voaTextList, this.voaTextList, list);
},
handleTime(t) {
    let s = Math.floor(t / 60) + ':' + (t % 60 / 100).toFixed(2).slice(-2)
    return s
},
timeToSec(time) {
     var arr = time.split(':');
     return parseFloat(arr[0]) * 3600 + parseFloat(arr[1]) * 60 + parseFloat(arr[2]);
}

到此整个功能点已经完成开发。源码我会放在下面,有兴趣的可以看看....文章源自羅小子-https://luozz.cn/uni-app-wechat-video/

输入验证码查看隐藏内容

扫描二维码关注本站微信公众号 羅小子
或者在微信里搜索 羅小子
回复 视频播放字幕 获取验证码
wechat 羅小子
文章源自羅小子-https://luozz.cn/uni-app-wechat-video/文章源自羅小子-https://luozz.cn/uni-app-wechat-video/
继续阅读
微信小程序
微信扫一扫
weinxin
我的微信
微信公众号
微信扫一扫
weinxin
我的公众号
羅 小子
  • 本文由 发表于 2023年6月6日 13:30:45
  • 转载请务必保留本文链接:https://luozz.cn/uni-app-wechat-video/
  • uni-app
  • 小程序
  • 视频播放
评论  0  访客  0
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: