更新记录

2.0.0(2024-08-03) 下载此版本

将原有的ls-dom-video迁移至此。


平台兼容性

Vue2 Vue3
App 快应用 微信小程序 支付宝小程序 百度小程序 字节小程序 QQ小程序
× × × × × × ×
钉钉小程序 快手小程序 飞书小程序 京东小程序
× × × ×
H5-Safari Android Browser 微信浏览器(Android) QQ浏览器(Android) Chrome IE Edge Firefox PC-Safari
× × × × × × × × ×

dom-video-player - 使用 html5 的原生 video 标签,实现的APP中的视频播放器组件

介绍

缘由(uniapp 提供的 video 原生组件不香吗???)

  • 香!uniapp 中的 video 是原生组件,提供了丰富的参数配置和事件回调,能不香吗?但局限性也是有的,无法满足我司的产品需求 和 设计同学的 UI 需求(打也打不过):
    • uniapp 的视频播放器是原生组件,层级比较高于普通前端组件,难以被业务组件和定制化需求所遮挡覆盖
    • 使用 cover-view 遮挡的话又有一些 css 样式限制 & 显隐的兼容性问题,plus.nativeObj.view的开发难度高。
    • uniapp 的视频播放器就难以自定义样式了,播放按钮、进度条、遮挡层级等无法实现 UI 的设计需求。
    • video 在 scroll-viewswiper 中的使用问题,原生组件使用限制
    • uniapp 的视频播放器在 iOS 端与uni.getBackgroundAudioManager背景音频的事件冲突,事件调用存在互相干扰。

实现

  • 代码实现其实很简单的,思路:通过 renderjs 将 HTML5 中的 video 标签渲染到 APP 上来
  • 但是从一开始想到这个思路真的好难,起初在插件市场没找到一个解决视频层级的相关插件,于是只能自己写了~

迭代更新

上线 DCloud 插件市场 一年以来,大家反馈都很不错,基本都是五星好评,还有许多大佬们的打赏,也收到了许多的技术咨询和私信,根据大家的需求和建议更新迭代了下:

  • 对编码本身做了优化,清晰的定义了原生事件自定义事件,方便大家根据自身业务去进行二次开发、修改。
  • 优化了属性更新逻辑,支持播放过程中controlsmutedloop等属性变更,不会造成视频的重新渲染。
  • 优化了 Android 在加载视频时出现黑色播放按钮的情况,增加了 loading 效果,优化了视频封面的第一帧展示。
  • 新增了播放进度(timeupdate)播放总长(durationchange)的自定义事件,用户可通过事件监听来实现自定义进度条。
  • 新增了ratechangefullscreenchangecanplay等 video 的原生事件监听。
  • 新增了全屏播放fullScreen()函数调用,支持多机型、多端的兼容适配,支持安卓、ios、h5端。
  • 新增了进度跳转toSeek(time, isDelay)函数调用,支持延迟生效,保证视频加载完成后生效。
  • 新增了 swiper 的 banner 的左右滑案例、全屏上下滑动类似抖音视频播放案例。
  • 提供了更加完善的 vue2 项目示例,顺便支持了下 vue3 的使用和项目示例。

使用说明

video 组件的 props 传值:

src: '' // 视频地址
autoplay: false // 是否自动播放
loop: false // 是否循环播放
controls: false // 是否显示控制栏
muted: false // 是否静音
isLoading: false // Android系统加载时显示loading(为了遮挡安卓的黑色按钮)
objectFit: 'contain' // 视频尺寸与video区域的适应模式
poster: '' // 视频封面

video 向父组件传递的事件:

play: () => {} // 播放事件
pause: () => {} // 暂停事件
ended: () => {} // 播放结束事件
timeupdate: (e) => {} // 视频播放进度事件
durationchange: (e) => {} // 视频总时长改变事件

video 组件methods方法:

play() // 播放
pause() // 暂停
remove() // 移除视频
fullScreen() // 进入全屏
toSeek(time) // 跳转到指定时间点(s)
// example: 父组件对 video 的 methods 调用案例
methods: {
  // 播放视频
  play() {
    const videoPlayer = this.$refs.domVideoPlayer
    videoPlayer.play()
  },
  // 删除视频
  remove() {
    const videoPlayer = this.$refs.domVideoPlayer
    videoPlayer.remove()
  }
}

子组件的data数据:

currentTime: 0 // 当前播放时间
duration: 0 // 视频总时长
playing: false // 是否播放中
// example: 父组件对 video 的 data 数据获取案例
methods: {
  // 播放/暂停视频
  playOrPause() {
    const videoPlayer = this.$refs.domVideoPlayer
    // 获取 video 当前是否处于播放中
    if (videoPlayer.playing) {
      videoPlayer.pause()
    } else {
      videoPlayer.play()
    }
  }
}

组件书写案例:

<DomVideoPlayer
  ref="domVideoPlayer"
  src="https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/uni-app-video-courses.mp4"
  autoplay
  loop
  controls
  muted
/>

父组件调用子组件方法:

/* vue2 */
let videoPlayer = this.$refs.domVideoPlayer
videoPlayer.play()
/* vue3 */
const videoPlayer = ref(null)
videoPlayer.play()

使用异常 Q&A

  • 视频黑屏,播放不出来?

    • 视频地址必须是网络地址,不可以是本地地址。
    • 播放器仅支持常用视频格式,视频格式支持情况
    • 视频带有签名已过期、视频过大导致加载时间长等。
  • 我的视频是 hlsflv 格式(视频流),该如何播放?

    • flv 格式的视频就没办法了,flv.js 重点是调用 MediaSource 的创建,在 iOS 的浏览器内核中暂时不支持该 API。
    • hls 格式的视频还算有办法,使用 hls.js 去播放就好了,具体使用可以看我另一个插件项目:hls-video-player
  • Android 端的视频,为什么播放前有个黑色播放图标

    • 因为使用的是 html5 中的 video 标签进行播放,而在 Android 系统的浏览器内核中,视频器自带了这个播放图标样式,无法自定义。
    • 解决方案:使用 loading 去遮挡播放图标这个期间的视频加载过程,该组件已实现该能力,提供了 isLoading 属性,默认是 false,设置为 true 即可。
  • 为什么拖拽 video 原生进度条的时候,视频会出现文字 “在左侧或右侧点按两次即可跳过 10 秒”?

    • 因为是使用 html5 中的 video 标签进行播放,而在 Android 系统的浏览器内核中,视频器自带了这个文字提示,无法自定义。
  • iOS 端为什么不能两个视频同时播放

    • 因为在 iOS 系统中不允许两个音频媒体同时播放,所以两个有声视频是不能同时播放的。
    • 想同时播放两个视频最简单的方案是,将视频的 muted 静音属性设置为 true,这样两个视频就不会播放声音,即可以同时播放视频了。
  • 我要在视频上做一个 click 点击事件,该怎么做?

    • 可以在 DomVideoPlayer 组件外包一层 div,然后给 div 标签绑定上点击事件,就可以了。
  • 我的项目是 vue3 的,组件是 vue2 的,可以使用吗?

    • 可以使用的,demo 案例中有 vue3 的基本案例、swiper案例等。
  • 控制台显示 xxxx https://goo.gl/LdLk22 xxxx 这样之类的报错是什么?

    • 点开链接有相关说明,一种是警告我们不要在非静音状态下直接播放视频,这是谷歌的用户体验规范,可以忽略。
    • 另一种是告诉我们 play() 被 pause() 行为打断了,因为 play() 是异步,不影响视频播放,可以忽略。
  • vue3 可以使用吗?

    • 当然可以,本身编译后是兼容的,在示例项目中有 vue3 的案例。
    • 如果希望组件也是 vue3 版本的,因为是 renderjs 写的,其实没必要。
  • 有更多的函数和组件调用的业务需求,该如何扩展

    • 更多拓展函数和事件,可以通过组件中的提供的renderFunc进行实现,video 原生的事件调用可借助组件中的eventCommand进行实现,详细可阅读源码。
    • 有难题需要技术咨询、需要更多的定制化组件、定制化能力、其它技术问题等可以联系作者,提供免费/付费帮助。

作者联系方式?

// 因官方不允许作者透露个人信息,需要大佬们理解一下了...

const numbers = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
const secrets = [9, -1, -5, 1, 3, 2]

let weChat = ''
numbers.forEach((v, i) => {
  weChat += (secrets[i] || 0) + v
})
console.log(weChat)

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

许可协议

MIT协议

使用中有什么不明白的地方,就向插件作者提问吧~ 我要提问