uniapp视频播放器(h5+app)

embedded/2024/10/21 9:41:50/

关于uniapp视频播放器遇到的一些问题,mark下。

中途遇到了很多问题,如果有相同的伙伴遇到了类似的,欢迎交流

  • 官方的video播放器在app上不友好,有以下功能不支持。
  1. @loadedmetadata、@controlstoggle不支持导致只能手写控制层。

在这里插入图片描述

  1. 不支持外挂字幕,因为video在app上运行时,是采用的ijkplayer库来实现的,ijkplayer目前也不支持外挂字幕

在这里插入图片描述

  1. 使用subNVues或者cover-view来自定义绘制视频界面覆盖(因为cover-view不支持嵌套,所以最后采用使用subNVues)

在这里插入图片描述

  1. video在h5需要播放时采用的是html的video标签,但是不支持m3u8格式,最后采用的是dplayer播放器+hls来实现的m3u8播放(也可以通过m3u8格式转换后再进行播放)

我这边的想要的是自定义绘制视频界面,这样做的话就需要将video原有的control相关的功能重写(播放、暂停、快进、快退、全屏、音量等),全屏和非全屏两套样式,通过官方提供的uni.createVideoContext(videoId, this)可以获取到video的实例,然后通过实例调用video的api,比如play、pause等。

在这里插入图片描述

最终我这边实现后的播放器支持以下功能:

  1. app端自定义界面,播放、暂停、快进、快退、全屏、音量、选集、倍速、清晰度切换、手势(快进、后退、亮度调节、音量调节)。
  2. h5采用的是dplayer播放器+hls支持m3u8格式播放。
  3. 支持外挂字幕(SRT通过)
    下面说下具体的实现和遇到的问题:

1. 配置subNVues子窗体

  1. 这里注意的一点是path路径是从根目录开始的,不是对应的父窗体的相对路径。

  2. 文件格式一定是要nvue格式。

    配置完之后子窗体就会在对应的页面上显示。

在这里插入图片描述
在这里插入图片描述

video_42">2.配置video播放界面

  1. 因为我们需要自定义界面所以videocontrols需设置为false

在这里插入图片描述

  1. 全屏和非全屏后界面有些许差异,比如全屏后才可以选集等其他功能,那需要设计出两套样式。

    通过ref拿到video实例

videoCTX = this.$refs.video

全屏和取消全屏事件

  // 全屏/退出全屏fullOrExitScreen() {if (this.fullScreenStatus) {videoCTX.exitFullScreen()} else {videoCTX.requestFullScreen()}},

3. 设置手势操作

手势操作分为向上向下向左向右四个方位

  • 向左向右:快进、后退
  • 屏幕左侧上下滑动:亮度调节
  • 屏幕右侧上下滑动:音量调节

使用touchStart、touchMove、touchend来实现此功能

touchStart时存储首次的坐标点

this.oldTouchs = e.changedTouches[0]

我这边定义的touchType为三种类型,currentTime进度、luminance亮度、volume音量

  1. 首先先判断是否为上下滑动,如果上下的话就只能是亮度和音量调节,接着获取屏幕的宽度,判断手势移动的x坐标是否大于屏幕宽度的1/2,如果是就为音量调节,否则为亮度调节。

在这里插入图片描述

  1. 如果为进度条的话则先保存当前进度,视频暂停,通过x轴移动的距离计算出当前进度,然后通过video的seek方法跳转到当前进度。

在这里插入图片描述

然后再touchEnd设置video进度

在这里插入图片描述

  1. 音量调节也是一样的 算出滑动的距离后通过plus.device.setVolume设置

在这里插入图片描述

  1. 亮度调节也是一样的 算出滑动的距离后通过plus.screen.setBrightness设置

在这里插入图片描述

4. 配置字幕

  1. 如果是VVT格式可以采用video中track标签实现,.vtt 格式文件属于 Web Video Text Tracks Format(WebVTT),是一种基于文本 UTF-8 编码的格式,为 Web 媒体元素提供字幕数据文件。WebVTT 的 MIME 格式是 text/vtt。
  2. 我这边项目中是用的是SRT格式的,但是video无法解析出来,所以想到的办法是将SRT字幕格式转换成js可以解析的json格式。

下面是SRT原格式

在这里插入图片描述

  1. 通过以下函数将数据转换为数组

    createSrtArr(srt) {let arr = srt.split(/\n\n|\r\r|\r\n\r\n/)let result = []arr.forEach(item => {let srtObj = {}let containArr = item.split(/\n/)if (containArr[1]) {//此处正则用于取出00:00:00,213 --> 00:00:00,213这种结构,防止可能存在于此行的x,y坐标对后续处理造成影响var reg = /^(\d{2}):(\d{2}):(\d{2})[\.,](\d{1,3}) --\> (\d{2}):(\d{2}):(\d{2})[\.,](\d{1,3})/glet regResult = reg.exec(containArr[1])if (regResult) {let timeSplit = regResult[0].split(' --> ')srtObj.from = this.getSeconds(timeSplit[0])srtObj.to = this.getSeconds(timeSplit[1])//这里的两个replace主要是将srt中可能携带的font标签转化为易用的span,当时遇到了如果是font标签的话没办法继承父元素的字体大小的问题,题外话:本次字母字体大小采用了媒体查询进行设置srtObj.htmlText = containArr.slice(2).join(`\n`).replace(/\<font/g, '<span').replace(/\<\/font/g,'</span')result.push(srtObj)}}})return result}
    

转换后的数据格式如下

在这里插入图片描述

  1. 通过currentTime时长和获取到的subtitlesArray字幕数组获取到对应时间的字幕。
  getSubtitle(currentTime, arr) {let left = 0;let right = arr.length - 1;while (left <= right) {let mid = Math.floor((left + right) / 2);if (currentTime >= arr[mid].from && currentTime <= arr[mid].to) {return arr[mid].htmlText;} else if (currentTime < arr[mid].from) {right = mid - 1;} else {left = mid + 1;}}return null; // 如果未找到匹配的时间段,则返回null或者其他您认为合适的值}

PS: 这个里有注意事项,因为我这边是需要兼容h5和app端,通过时长获取到的字幕数据有可能携带标签,所以需要富文本展示,h5和app上均需要做处理。

<!-- #ifdef H5 --><view class="subtitles" v-html='subtitles'></view><!-- #endif --><!-- #ifdef APP-PLUS --><rich-text class="subtitles" :nodes="nodes" :style="videoBox"><!-- #endif --></rich-text>
  const res = this.getSubtitle(value,this.subtitlesArray) || ''if (this.subtitlesArray.length) {// #ifdef APP-PLUSthis.nodes[0].children[0].text =res// #endif// #ifdef H5this.subtitles = res// #endif}

这里先简单记录下,因为时间有限,代码已上传到线上,有需要的伙伴可以下载下来参考下。传送门


http://www.ppmy.cn/embedded/26950.html

相关文章

mysql主库delete一个没主键的表导致从库延迟很久问题处理

一 问题描述 发现线上环境一个从库出现延迟&#xff0c;延迟了2天了&#xff0c;还没追上主库。 查看当前运行的sql及事务&#xff0c;发现这个sql语句是在delete一个没主键的表。 二 问题模拟 这里在测试环境复现下这个问题。 2.1 在主库造数据 use baidd; CREATE TABL…

使用 Vitepress 构建博客并部署到 github 平台

前言 最近写了好多篇 Chrome 浏览器插件相关的文章&#xff0c;有十几二十篇&#xff0c;就想着构建个博客&#xff0c;用来放置相应的文章。 正好前段时间看到 VitePress 1.0.0 发布了&#xff0c;而且是用 markdown 写文章&#xff0c;正好写插件文章的时候文章都是 md 格式…

产品人生(2):从“Kanban方法”到“GTD时间管理法“

人生如产品&#xff0c;产品映人生&#xff0c;借鉴产品思维&#xff0c;快速提升软技能&#xff01; IT的小伙伴想必都听过或使用过Kanban&#xff08;看板&#xff09;&#xff0c;今天我们要聊一聊&#xff0c;如何从Kanban方法中找到高效管理时间的思路。 Kanban&#xff…

acwing算法提高之数据结构--线段树

目录 1 介绍2 训练3 参考 1 介绍 线段树是算法竞赛中常用的用来维护区间信息的数据结构。 线段树可以在O(logN)时间复杂度内完成以下操作&#xff1a; 单点修改。区间修改&#xff08;需要加入懒标记&#xff09;。区间查询&#xff08;区间求和、求区间最大值、求区间最小值…

Zapier 与生成式 AI 的自动化(一)

原文&#xff1a;zh.annas-archive.org/md5/057fe0c351c5365f1188d1f44806abda 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 前言 当组织处理手动和重复性任务时&#xff0c;生产力会遇到重大问题。Zapier 处于无代码运动的前沿&#xff0c;提供了一种先进的工具&a…

SQL中distinct的用法

在SQL&#xff08;结构化查询语言&#xff09;中&#xff0c;DISTINCT关键字用于返回唯一不同的值。当你使用SELECT语句从一个或多个列中选择数据时&#xff0c;如果这些列包含重复的值&#xff0c;DISTINCT关键字可以帮助你去除结果集中的重复行&#xff0c;只返回不同的值。 …

C++ 多态详解

文章目录 1. 多态的概念2. 多态的定义及实现2.1 多态的构成条件2.2 虚函数2.3 虚函数的重写2.3.1 虚函数重写的两个例外 2.4 C11 override 和 final2.5 重载、覆盖(重写)、隐藏(重定义)的对比 3. 多态的原理3.1 虚函数表3.2多态的原理 4. 单继承和多继承关系的虚函数表4.1 单继…

C++类的设计编程示例

一、银行账户类 【问题描述】 定义银行账户BankAccount类。 私有数据成员&#xff1a;余额balance&#xff08;整型&#xff09;。 公有成员方法&#xff1a; 无参构造方法BankAccount()&#xff1a;将账户余额初始化为0&#xff1b; 带参构造方法BankAccount(int m)&#xff1…