更新记录

0.3.1(2026-09-29)

Added

  • README 新增「注意事项」章节:蒸汽模式不支持 rpx、退出全屏字体变大、watch 不触发、@keyframes 不可用、Math.random() 返回 0、Element.animate() 不支持、iOS 事件对象兼容说明

Fixed

  • iOS 自定义 UI 时间/状态不更新:getEventValue 先尝试 (e as any)[key] 属性访问,失败再 fallback 到 (e as Map<string, any>).get(key)
  • 所有 Demo 页面 rpx → px 转换(d-video/vapor/live),2rpx=1px

0.2.0(2026-09-29)

新增

  • HLS 直播 Demo — 新增 pages/live/index 直播页面,支持 HLS/FLV 切换、断流重连提示
  • switchSource API — 组件暴露 switchSource(url) 方法,Vapor 模式下直接调用切换视频源(不依赖 prop watch)
  • 鸿蒙全屏横屏 — 鸿蒙端全屏通过 $setPageStyle('pageOrientation', 'landscape') 实现横屏切换
  • H5 全屏 — 使用原生 DOM Fullscreen API(el.requestFullscreen() / document.exitFullscreen())
  • Iconfont 图标 — 控制栏全部替换为 iconfont 图标(播放/暂停/音量/静音/全屏/返回)
  • README 文档 — 组件 API、Props、Events、Iconfont 用法、平台支持全覆盖

修复

  • 视频源切换失效 — Vapor 模式下 watch(() => props.src) 不触发,改用暴露 switchSource(url) 方法直接调用
  • 图标不显示 — 字体码点错误(U+EA24-31 → U+E612/E60F/E610/E611/E615/E617),改用字体实际包含的码点
  • Iconfont 写法 — 模板中用 HTML 实体 &#xe612; 而非 JS 转义 '\uE612'
  • 字体加载方式 — 从 uni.loadFontFace JS API 改为 CSS @font-face 全局加载,跨平台通用
  • 声音图标反了 — 静音时显示静音图标,有声时显示音量图标
  • EOF 位置不同步 — 播放结束时进度停在 01:29 而非 01:30,在 onNativeEvent EOF 分支补发 emitTimeupdate
  • EOF loading 不消失 — 新增 nativeIsEof() 轮询 eof-reached 属性
  • 总时长显示 00:00 — 模板改用 formatTime(durationMs / 1000)
  • 播放按钮不切换 — nativePlay/nativePause 设置 player.state
  • H5 video 自带 UI — 添加 controls="false" 等属性隐藏原生控制栏
  • 弹幕渲染 — Vapor 模式下重构为 v-for + setInterval 推进位置,替代不可用的 createElement

变更

  • 控制栏布局 — 左侧播放/时间,右侧倍速/弹幕/音量/全屏,用 ctrl-left/ctrl-right 分组
  • 移除清晰度按钮 — 控制栏不再显示清晰度按钮(API 保留)
  • Demo 页面精简 — Vapor demo 去掉清晰度切换,新增直播跳转入口

平台兼容性

uni-app x(5.0)

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

d-video · 蒸汽模式视频播放器

对齐官方 uni-video 架构,UI 直接写 view、native-view 桥接 libmpv 引擎,支持蒸汽(Vapor)模式与直播/倍速/弹幕/全屏。

特性

  • 蒸汽模式 — 视图层直出 bytecode/nativecode,无 VDOM diff
  • native-view 桥接 — Android 端通过 native-view 桥接 libmpv,Web 端回退内置 <video>
  • 跨平台 — Android / iOS / 鸿蒙 / H5 四端覆盖
  • 直播支持 — HLS/FLV/RTMP/RTSP/WebRTC 直播流,断流自动重连,直播模式自动隐藏进度条与倍速
  • 弹幕引擎 — Vapor 视图层 v-for + setInterval 推进,不经过 VDOM diff
  • 图标字体 — CSS @font-face 全局加载,模板用 HTML 实体 &#xe612; 引用
  • 全屏 — Android 沉浸式 + requestedOrientation,iOS/鸿蒙 $setPageStyle 横屏,H5 原生 DOM Fullscreen API
  • 自定义 UI — controls="false" 隐藏默认 UI,通过 <slot> 插槽注入自定义控制栏
  • 多实例 — 支持同页多个 d-video 实例,各自独立引擎

快速开始

# 安卓
cli launch app-android --project <path> --playground custom --customType local --cleanCache true

# H5
cli launch web --project <path>

使用

<d-video
  ref="playerRef"
  :src="videoUrl"
  :autoplay="false"
  :live="false"
  :muted="false"
  :danmuBtn="true"
  :enableDanmu="true"
  :danmuList="danmuList"
  :showMuteBtn="true"
  @statechange="onStateChange"
  @progress=""
  @prepared="onPrepared"
  @fullscreenchange=""
/>

自定义 UI(Slot 插槽)

传 controls="false" 隐藏默认 UI,通过 <slot> 注入自定义控制栏:

<d-video ref="playerRef" :src="videoUrl" :controls="false" :showCenterPlayBtn="false" :showLoading="false">
  <!-- 自定义播放按钮 -->
  <view class="my-overlay" v-if="!playing">
    <text class="my-play-btn" @click="playerRef?.play()">▶</text>
  </view>
  <!-- 自定义控制栏 -->
  <view class="my-controls">
    <text>{{ formatTime(position) }} / {{ formatTime(duration) }}</text>
    <text @click="playerRef?.toggle()">{{ playing ? '⏸' : '▶' }}</text>
    <text @click="playerRef?.toggleFullscreen()">⛶</text>
  </view>
</d-video>

多实例视频列表

<scroll-view>
  <view v-for="(item, idx) in videoList" :key="idx">
    <d-video
      :ref="(el: any) => onPlayerRef(el, idx)"
      :src="item.src"
      :controls="false"
      :danmuBtn="false"
      @statechange="(e: any) => onStateChange(e, idx)"
      @progress="(e: any) => (e, idx)"
    ></d-video>
    <text>{{ item.title }}</text>
  </view>
</scroll-view>

直播模式

<d-video
  :src="hlsUrl"
  :live="true"
  :autoplay="true"
  @livereconnect="onReconnect"
/>

直播模式下自动隐藏进度条、倍速控制;断流触发 livereconnect 事件。

支持协议

协议 示例
RTMP rtmp://192.168.0.182:1936/test
RTSP rtsp://192.168.0.182:8554/test
HLS https://192.168.0.182:8888/test/index.m3u8
WebRTC http://192.168.0.182:8889/test
FLV https://example.com/live.flv

组件 API

Props

属性 类型 默认值 说明
src string — 视频 URL
controls boolean true 显示默认控制栏
autoplay boolean false 自动播放
live boolean false 直播模式
muted boolean false 静音
loop boolean false 循环
playbackRate number 1.0 倍速
objectFit string 'contain' 填充模式
title string '' 全屏标题
danmuBtn boolean false 显示弹幕开关
enableDanmu boolean false 开启弹幕
danmuList Danmu[] [] 弹幕列表
showMuteBtn boolean false 显示静音按钮
showFullscreenBtn boolean true 显示全屏按钮
showPlayBtn boolean true 显示播放按钮
showCenterPlayBtn boolean true 显示中央播放按钮
showLoading boolean true 显示加载指示

Methods

方法 说明
play() 播放
pause() 暂停
stop() 停止
seek(ms) 跳转(毫秒)
toggle() 播放/暂停切换
mute(muted) 静音/取消
playbackRate(rate) 设置倍速
requestFullscreen() 进入全屏
exitFullscreen() 退出全屏
toggleFullscreen() 全屏切换
getCurrentState() 当前状态
getPosition() 当前位置(ms)
getDuration() 总时长(ms)
switchQuality(index) 切换清晰度
switchSource(url) 切换视频源(Vapor 模式需直接调用)

Events

事件 说明
statechange 播放状态变化
progress 播放进度
prepared 就绪
end 播放结束
error 错误
fullscreenchange 全屏变化
livereconnect 直播重连

Iconfont 用法

/* App.uvue 全局加载 */
@font-face {
  font-family: 'dplayer-iconfont';
  src: url('/static/dplayer-iconfont.ttf');
}
<!-- 模板中用 HTML 实体,不要用 JS 转义 -->
<text style="font-family: 'dplayer-iconfont';">&#xe612;</text>

<!-- 动态切换可用 JS 字符串 -->
<text>{{ playing ? '\ue60f' : '\ue612' }}</text>
图标 码点 HTML 实体
播放 U+E612 &#xe612;
暂停 U+E60F &#xe60f;
全屏进入 U+E610 &#xe610;
全屏退出 U+E611 &#xe611;
音量 U+E615 &#xe615;
静音 U+E617 &#xe617;

注意:字体文件不含 U+E601,返回按钮使用 Unicode 箭头 ← 代替。

Demo 页面

页面 路径 说明
蒸汽模式 Demo pages/vapor/index 多实例视频列表 + 弹幕 + 全屏
官方式 Demo pages/d-video/index 对齐 uni-video
HLS 直播 Demo pages/live/index 直播流 + 断流重连
自定义 UI Demo pages/custom-ui/index slot 插槽自定义控制栏

平台支持

平台 引擎 全屏方式
Android libmpv (native-view) 沉浸式 + requestedOrientation
iOS libmpv (native-view) $setPageStyle 横屏
鸿蒙 libmpv (native-view) $setPageStyle 横屏
H5 内置 <video> DOM Fullscreen API

注意事项

  1. 蒸汽模式不支持 rpx — Vapor 模式下 rpx 会被当作固定像素值,不随屏幕适配缩放,请统一使用 px(2rpx = 1px)
  2. 退出全屏字体变大 — 全屏状态下 100vw/100vh 计算会因方向切换导致 UI 异常,建议全屏/非全屏使用不同的控制栏样式,或通过 fullscreenchange 事件监听后主动切换
  3. Vapor 模式 watch 不触发 — watch(() => props.src) 在 Vapor 模式下不会触发,需通过 switchSource(url) 方法直接切换视频源
  4. CSS @keyframes 不可用 — Vapor 模式下 CSS 动画不生效,弹幕等动效请使用 v-for + setInterval 推进
  5. Math.random() 不生效 — Vapor 模式下返回 0,需使用自定义伪随机(如 LCG)
  6. Element.animate() 不支持 — Vapor 模式下不可用,需手动操作样式
  7. iOS 事件对象 — 自定义 UI 中读取事件数据时,需兼容属性访问和 Map.get() 两种方式

许可

MIT

隐私、权限声明

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

无

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

无

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

无

暂无用户评论。