更新记录

2.0.1(2026-06-16)

增加使用说明

2.0.0(2026-06-16)

0.0.1


平台兼容性

uni-app(5.13)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
×
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟

uni-app x(5.13)

Chrome Safari Android iOS 鸿蒙 微信小程序
- - - - - -

custom-video-player —— 跨平台原生视频播放插件

一款开箱即用的视频播放器组件,各平台底层走原生播放器,自带完整 UI 控件、手势交互,完整支持 0.5x ~ 2.0x 倍速播放

适用于:教培视频、短视频 Feed、课程播放、直播回放等场景。


〇、运行要求(重要!)

由于本插件使用了 UTS 原生 SDK 调用各平台底层播放器(Android MediaPlayer、iOS AVPlayer 等),不同平台的运行方式不同:

运行平台 是否需要自定义基座 说明
Web (H5) 不需要 直接 运行 → 运行到浏览器 即可,底层用 HTML5 video
微信小程序 不需要 直接 运行 → 运行到小程序模拟器,底层用微信 video 组件
Android 真机/模拟器 需要 需先 运行 → 制作自定义基座,再用自定义基座运行
iOS 真机/模拟器 需要 需先 运行 → 制作自定义基座,再用自定义基座运行
鸿蒙真机/模拟器 需要 需先制作自定义基座运行

如何制作自定义基座?

  1. HBuilderX 菜单 → 运行 → 运行到手机或模拟器 → 制作自定义基座
  2. 选择目标平台(Android / iOS),等待打包完成
  3. 打包完成后,再次 运行 → 运行到手机或模拟器,选择刚刚制作的自定义基座即可

小白提示:如果你是第一次开发,建议先在 Web(浏览器) 上调试,无需任何配置,效果和真机一致。等逻辑调通后再打自定义基座跑真机。


一、快速上手(1 分钟)

1. 导入组件

<template>
  <custom-video-player
    ref="playerRef"
    src="https://www.w3schools.com/html/mov_bbb.mp4"
    :autoplay="true"
    :show-mute-btn="true"
    @timeupdate=""
  />
</template>

<script lang="uts" setup>
import CustomVideoPlayer from '@/uni_modules/custom-video-player/components/custom-video-player/custom-video-player.uvue'

const playerRef = ref<any>(null)

function (e: { currentTime: number; duration: number }) {
  console.log('进度:', e.currentTime.toFixed(1), '/', e.duration.toFixed(1))
}
</script>

这就行了——组件自动处理:原生播放器创建、控件渲染、手势交互、全屏切换、倍速菜单。你只需传入 src 即可播放。

2. 通过 ref 控制播放

// 播放 / 暂停
playerRef.value.play()
playerRef.value.pause()

// 跳转到第 30 秒
playerRef.value.seek(30)

// 切换到 1.5 倍速
playerRef.value.setRate(1.5)

// 进入全屏
playerRef.value.requestFullScreen()

// 读取当前状态
const state = playerRef.value.getState()
console.log(state.currentTime, state.duration, state.isPlaying)

二、运行 Demo

项目内置了完整的调试 Demo 页面,推荐先跑起来看看效果:

页面路径:pages/VideoSub/videoPlayerDemo

或在 pages.json 中跳转:

{ "path": "pages/VideoSub/videoPlayerDemo" }

Demo 提供:

  • 多视频源切换
  • 所有 Props 实时开关
  • 手势操作演示
  • 全事件日志输出

三、Props(组件属性)

基础属性

Prop 类型 默认值 说明
src String '' 视频地址(支持 http/https/本地路径)
poster String '' 封面图地址,播放前显示
autoplay Boolean false 是否自动播放
loop Boolean false 是否循环播放
muted Boolean false 是否静音
object-fit String 'contain' 视频填充模式:contain / cover / fill
initial-time Number 0 初始播放位置(秒),即 start-seconds
defaultRate Number 1.0 默认倍速(0.5 / 1.0 / 1.25 / 1.5 / 2.0)
duration Number 0 预设时长(秒),视频加载后自动覆盖
video-id String 自动生成 播放器唯一 ID,用于多实例区分

控件显隐

Prop 类型 默认值 说明
show-controls Boolean true 是否显示底部控制栏
show-play-btn Boolean true 是否显示底部播放/暂停按钮
show-center-play-btn Boolean true 是否显示中间大播放按钮
show-mute-btn Boolean false 是否显示静音按钮
show-fullscreen-btn Boolean true 是否显示全屏按钮(同 show-fullscreen
show-rate-btn Boolean true 是否显示倍速按钮
show-back-btn Boolean true 是否显示顶部返回按钮
show-more-btn Boolean false 是否显示顶部更多按钮

手势控制

Prop 类型 默认值 说明
enable-play-gesture Boolean true 双击播放/暂停
enable-progress-gesture Boolean true 水平滑动快进/快退

其他

Prop 类型 默认值 说明
title String '' 顶部标题文字
tablet Boolean false 是否启用平板/宽屏适配(UI 等比放大)
controls Boolean true 保留字段,对齐 uni-app video 组件

使用示例

<custom-video-player
  src="https://example.com/video.mp4"
  poster="https://example.com/cover.jpg"
  :autoplay="true"
  :loop="false"
  :muted="false"
  :default-rate="1.0"
  object-fit="contain"
  title="我的视频"
  :show-mute-btn="true"
  :show-back-btn="true"
  :enable-progress-gesture="true"
  :enable-play-gesture="true"
/>

四、Events(事件)

所有事件名对齐 uni-app / 微信小程序 VideoContext,可直接迁移。

事件 触发时机 回调参数
@ready 播放器准备完成
@play 开始/继续播放
@pause 暂停播放
@ended 播放结束
@state 状态变化 { state: string }
@timeupdate 播放进度变化 { currentTime: number, duration: number }
@load 元数据加载完成 { width: number, height: number, duration: number }
@fullscreen 全屏切换 { fullScreen: boolean, direction: 'vertical'\|'horizontal' }
@error 播放失败 { errMsg: string }
@back 点击顶部返回按钮
@ratechange 倍速变更 { rate: number }
@buffering 缓冲状态变化 { isBuffering: boolean }

state 取值说明

含义
idle 初始状态,尚未准备
prepared 准备完成,可以播放
playing 正在播放
paused 已暂停
stopped 已停止(需重新 prepare 才能再播)
finished 播放完成(自然结束)
error 播放错误

使用示例

<custom-video-player
  src="..."
  @ready="onReady"
  @play="onPlay"
  @pause="onPause"
  @timeupdate=""
  @state="onState"
  @load="onLoad"
  @error="onError"
  @back="onBack"
  @ratechange=""
  @buffering="onBuffering"
  @fullscreen="onFullscreen"
/>
function onReady() { console.log('可以播放了') }
function onPlay() { console.log('开始播放') }
function onPause() { console.log('暂停了') }

function (e: { currentTime: number; duration: number }) {
  // 更新进度条
  progress.value = (e.currentTime / e.duration) * 100
}

function onLoad(e: { width: number; height: number; duration: number }) {
  console.log(`视频尺寸 ${e.width}x${e.height},时长 ${e.duration}s`)
}

function onError(e: { errMsg: string }) {
  uni.showToast({ title: '播放失败: ' + e.errMsg, icon: 'none' })
}

function onBack() {
  // 自定义返回逻辑;返回按钮也可通过 show-back-btn="false" 隐藏
  uni.navigateBack()
}

五、Ref API(通过 ref 调用组件方法)

组件暴露了完整的方法供外部控制:

方法 参数 返回值 说明
play() void 播放
pause() void 暂停
stop() void 停止(回到开头)
seek(seconds) number void 跳转到指定秒数
setRate(rate) number void 设置倍速(0.5~2.0)
playbackRate(rate) number void 同 setRate(对齐 VideoContext)
requestFullScreen(direction?) number? void 进入全屏(0=竖屏 90=横屏)
exitFullScreen() void 退出全屏
enterFullscreen() void 同 requestFullScreen(0)
exitFullscreen() void 同 exitFullScreen()
togglePiP() void 画中画开关(APP-Android)
toggleBackgroundAudio() void 后台音频/锁屏控制开关
getState() object 获取播放器状态快照

getState() 返回值

{
  currentTime: number    // 当前播放秒数
  duration: number       // 总时长
  rate: number           // 当前倍速
  isPlaying: boolean     // 是否正在播放
  isFullscreen: boolean  // 是否全屏
  isPiP: boolean         // 是否画中画
  videoWidth: number     // 视频宽度(暂未实现)
  videoHeight: number    // 视频高度(暂未实现)
}

使用示例

const playerRef = ref<any>(null)

// 播放控制
playerRef.value.play()
playerRef.value.pause()
playerRef.value.seek(60)           // 跳到 1 分钟

// 倍速切换
playerRef.value.setRate(2.0)       // 2 倍速

// 全屏
playerRef.value.requestFullScreen(90)  // 横屏全屏

// 画中画(Android)
playerRef.value.togglePiP()

// 读取进度
const state = playerRef.value.getState()
console.log(`${state.currentTime}/${state.duration}`)

六、手势交互

组件内置以下手势,无需额外代码:

手势 操作 效果
双击 在视频画面上快速双击 播放 / 暂停
水平滑动 在视频画面上左右滑动 快进 / 快退(每 50px ≈ 10 秒)
单击 在视频画面上单击 显示 / 隐藏控件(3 秒自动隐藏)
点击进度条 点击/拖拽底部进度条 seek 到指定位置

手势可通过 Props 关闭:

<custom-video-player
  :enable-play-gesture="false"       <!-- 关闭双击 -->
  :enable-progress-gesture="false"   <!-- 关闭水平滑动 -->
/>

七、控件自动隐藏

播放时,底部控制栏和顶部标题栏会在 3 秒无操作后自动隐藏,触摸视频画面即可重新显示。

  • 暂停状态下控件始终显示
  • 视频未开始播放时控件始终显示
  • 触摸视频画面可以随时唤醒控件

八、完整使用示例

一个包含常用功能的完整示例:

<template>
  <view style="flex:1">
    <custom-video-player
      ref="playerRef"
      :src="videoUrl"
      :poster="posterUrl"
      :title="videoTitle"
      :autoplay="false"
      :default-rate="1.0"
      object-fit="contain"
      :show-mute-btn="true"
      :show-back-btn="true"
      :enable-play-gesture="true"
      :enable-progress-gesture="true"
      @ready="onReady"
      @play="onPlay"
      @pause="onPause"
      @timeupdate=""
      @error="onError"
      @back="onBack"
    />
  </view>
</template>

<script lang="uts" setup>
import CustomVideoPlayer from '@/uni_modules/custom-video-player/components/custom-video-player/custom-video-player.uvue'

const playerRef = ref<any>(null)
const videoUrl = ref('https://www.w3schools.com/html/mov_bbb.mp4')
const posterUrl = ref('')
const videoTitle = ref('示例视频')

function onReady() {
  console.log('播放器就绪')
}

function onPlay() {
  console.log('正在播放')
}

function onPause() {
  console.log('已暂停')
}

function (e: { currentTime: number; duration: number }) {
  // 业务逻辑,比如记录学习进度
  const progress = e.duration > 0 ? (e.currentTime / e.duration) * 100 : 0
  console.log('进度:', progress.toFixed(1) + '%')
}

function onError(e: { errMsg: string }) {
  uni.showToast({ title: '播放失败', icon: 'none' })
}

function onBack() {
  uni.navigateBack()
}
</script>

九、目录结构

uni_modules/custom-video-player/
├── package.json
├── readme.md                          ← 你正在看的文档
├── utssdk/
│   ├── interface.uts                  # 统一接口定义(类型 + API 契约)
│   ├── app-android/index.uts          # Android: MediaPlayer + SurfaceView
│   ├── app-ios/index.uts              # iOS: AVPlayer + AVPlayerLayer
│   ├── app-harmony/index.uts          # 鸿蒙: AVPlayer + XComponent
│   ├── web/index.uts                  # Web: HTML5 video
│   └── mp-weixin/index.uts            # 微信小程序: video 组件
└── components/
    └── custom-video-player/
        └── custom-video-player.uvue   # 统一组件层(跨平台 UI)

十、各平台原生实现

平台 原生播放器 倍速 API 支持档位
Android MediaPlayer + SurfaceView setPlaybackParams(speed) 0.5x ~ 2.0x
iOS AVPlayer + AVPlayerLayer AVPlayer.rate 0.5x ~ 2.0x
鸿蒙 AVPlayer + XComponent AVPlayer.speed 0.5x ~ 2.0x
Web (H5) HTML5 video video.playbackRate 0.25x ~ 4.0x
微信小程序 video 组件 + VideoContext VideoContext.playbackRate() 0.5x ~ 2.0x

十一、注意事项

1. 视频源要求

  • 推荐使用 HTTPS 地址
  • 支持格式:MP4、M3U8(各平台兼容性有差异)
  • 本地路径请使用 @/static/xxx.mp4/static/xxx.mp4

2. 倍速生效时机

平台 生效时机
Android 播放状态 (state == 'playing')
iOS 播放状态 (state == 'playing')
鸿蒙 播放状态 (state == 'playing')
Web 任何时候
微信小程序 任何时候

建议: 先调用 play(),再调用 setRate(),确保倍速在各平台生效。

3. Android API 版本

  • MediaPlayer.setPlaybackParams() 需要 API 23+(Android 6.0)
  • 低版本设备不支持倍速,会降级为正常速度

4. 直播场景

  • 直播流(如 M3U8)不设置 duration,进度条会自动适配
  • 微信小程序端 M3U8 需基础库版本 ≥ 2.0.0

5. 多实例

同一页面可放多个 <custom-video-player>,通过 video-id 区分:

<custom-video-player video-id="player1" src="..." />
<custom-video-player video-id="player2" src="..." />

不传 video-id 时组件自动生成唯一 ID。

6. 画中画 / 后台音频

  • togglePiP() 目前仅在 Android 平台有原生实现
  • toggleBackgroundAudio() 用于启用锁屏信息 + 后台音频播放(Android/iOS)
  • 其他平台调用这些方法不会崩溃,只是无效果

十二、常见问题

Q: 如何隐藏所有控件,只显示视频画面?

<custom-video-player
  :show-controls="false"
  :show-center-play-btn="false"
  :enable-play-gesture="false"
  :enable-progress-gesture="false"
/>

Q: 如何获取当前播放进度?

两种方式:

  1. 监听 @timeupdate 事件
  2. 主动调用 playerRef.value.getState().currentTime

Q: 视频加载失败怎么处理?

监听 @error 事件,组件会自动显示"播放失败,点击重试"的 UI。

Q: 如何在微信小程序中使用?

直接引入组件即可——底层自动切换为微信 <video> 组件 + VideoContext,无需额外配置。

Q: 如何自定义倍速列表?

目前固定为 0.5x / 1.0x / 1.25x / 1.5x / 2.0x。如需自定义,可修改组件中 availableRates 常量:custom-video-player.uvue 第 148 行。

隐私、权限声明

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

网络权限(用于加载视频资源)、前台媒体播放

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

插件不采集任何数据

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

暂无用户评论。