更新记录

1.0.3(2026-09-04)

demo

1.0.2(2026-09-04)

  • 【UI重构】底部控制栏重构为 B 站两层布局(上层细红进度条,下层合并时间与控制按钮)
  • 【图标与样式】更新播放/暂停/全屏图标,加大音量与全屏图标尺寸,全屏模式下控制栏支持 1.4 倍放大
  • 【状态修复】修复视频播放完毕后状态仍停留在 playing 的问题
  • 【类型与编译】修复 UTS 中 Float 与 Number 类型转换导致的 ClassCastException 编译与运行时问题
  • 【包体积优化】iOS 平台改为通过 CocoaPods 远程依赖 Libmpv 框架,极大减小插件上传体积
  • 【文档完善】新增完整 API 使用文档,包含播放控制、音量、速度、弹幕、清晰度、全屏等所有方法的详细说明和示例

平台兼容性

uni-app x(5.0)

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

DPlayer 视频播放器

基于 libmpv 的跨平台视频播放器 uni_modules 插件,支持 H.265 解码和直播拉流。

功能特性

  • H.265/HEVC 支持:Android/iOS 硬件解码 + FFmpeg 软件解码
  • 直播拉流:HLS、HTTP-FLV、RTMP、RTSP 协议
  • 多平台:uni-app X (UTS)、uni-app NVue、Web、微信小程序
  • 弹幕系统:滚动弹幕、顶部弹幕、底部弹幕
  • 清晰度切换:多码率无缝切换
  • 自动重连:直播断流自动重连
  • B站风格 UI:底部控制栏采用 B 站两层布局设计

安装

  1. 下载本插件到项目的 uni_modules/ 目录
  2. pages.json 中配置页面
  3. 在页面中使用 <d-player-video> 组件

iOS 依赖配置

iOS 平台通过 CocoaPods 自动依赖 Libmpv 框架,无需手动下载。首次编译时会自动从 Gitee 下载 libmpv-1.0.0.xcframework.zip

基础用法

<template>
  <d-player-video
    ref="player"
    src="https://example.com/video.mp4"
    :autoplay="true"
    :live="false"
    @statechange="onStateChange"
    @progress=""
    @prepared="onPrepared"
    @error="onError"
  />
</template>

<script lang="uts">
export default {
  methods: {
    onStateChange(e: any) {
      console.log('状态变化:', e.state)
    },
    (e: any) {
      console.log('进度:', e.position, '/', e.duration)
    },
    onPrepared(e: any) {
      console.log('时长:', e.duration)
    },
    onError(e: any) {
      console.error('错误:', e.code, e.message)
    }
  }
}
</script>

Props

属性 类型 默认值 说明
src String "" 视频/直播流地址
autoplay Boolean false 自动播放
loop Boolean false 循环播放
live Boolean false 是否为直播流
muted Boolean false 静音
volume Number 1.0 音量 (0-1)
playbackRate Number 1.0 播放速度
decodeMode String "auto" 解码模式: auto/hw/sw
showControls Boolean true 显示控制栏
showDanmaku Boolean false 显示弹幕
objectFit String "contain" 视频填充模式

API 使用方法

通过 ref 调用组件方法:

播放控制

// 开始播放(如果未加载媒体则自动加载)
this.$refs.player.play()

// 暂停播放
this.$refs.player.pause()

// 停止播放(重置到开头)
this.$refs.player.stop()

// 跳转到指定位置(单位:毫秒)
this.$refs.player.seek(10000)  // 跳转到 10 秒
this.$refs.player.seek(60000)  // 跳转到 1 分钟

音量控制

// 设置音量(0-1 之间)
this.$refs.player.setVolume(0.5)  // 50% 音量
this.$refs.player.setVolume(0.0)  // 静音
this.$refs.player.setVolume(1.0)  // 最大音量

// 切换静音状态
this.$refs.player.toggleMute()

// 获取静音状态
const muted = this.$refs.player.getMuted()

播放速度

// 设置播放速度
this.$refs.player.setSpeed(0.5)   // 0.5 倍速
this.$refs.player.setSpeed(1.0)   // 正常速度
this.$refs.player.setSpeed(1.5)   // 1.5 倍速
this.$refs.player.setSpeed(2.0)   // 2 倍速

// 获取当前播放速度
const speed = this.$refs.player.getPlaybackRate()

获取播放信息

// 获取播放状态
// 返回值: "idle" | "opening" | "ready" | "playing" | "paused" | "completed" | "error"
const state = this.$refs.player.getState()

// 获取当前播放位置(单位:毫秒)
const position = this.$refs.player.getPosition()

// 获取媒体总时长(单位:毫秒)
const duration = this.$refs.player.getDuration()

// 获取视频尺寸
// 返回值: { width: number, height: number }
const size = this.$refs.player.getVideoSize()
console.log('视频宽度:', size.width, '视频高度:', size.height)

// 获取是否为直播流
const isLive = this.$refs.player.isLive()

// 获取全屏状态
const isFullscreen = this.$refs.player.isFullscreen()

// 获取循环播放状态
const loop = this.$refs.player.getLoop()

// 获取自动播放状态
const autoplay = this.$refs.player.isAutoplay()

// 获取控制栏显示状态
const showControls = this.$refs.player.isShowControls()

// 获取弹幕显示状态
const showDanmaku = this.$refs.player.isShowDanmaku()

// 获取解码模式
// 返回值: "auto" | "hw" | "sw"
const decodeMode = this.$refs.player.getDecodeType()

// 获取视频填充模式
// 返回值: "contain" | "cover" | "fill" | "none"
const objectFit = this.$refs.player.getObjectFit()

弹幕控制

// 添加弹幕
this.$refs.player.addDanmaku("这是一条弹幕")

// 添加带样式的弹幕
this.$refs.player.addDanmaku("彩色弹幕", {
  color: "#ff0000",      // 弹幕颜色
  fontSize: 20,          // 字体大小
  type: "scroll"         // 类型: "scroll" | "top" | "bottom"
})

// 设置弹幕显示/隐藏
this.$refs.player.setDanmakuVisible(true)   // 显示弹幕
this.$refs.player.setDanmakuVisible(false)  // 隐藏弹幕

// 清空所有弹幕
this.$refs.player.clearDanmaku()

清晰度切换

// 设置清晰度列表
this.$refs.player.setQualityLevels([
  { id: "1080p", label: "1080P 超清", url: "https://example.com/1080p.mp4" },
  { id: "720p", label: "720P 高清", url: "https://example.com/720p.mp4" },
  { id: "480p", label: "480P 标清", url: "https://example.com/480p.mp4" }
])

// 切换清晰度面板显示/隐藏
this.$refs.player.toggleQualityPanel()

// 获取当前清晰度 ID
const qualityId = this.$refs.player.getCurrentQuality()

// 获取当前清晰度标签
const qualityLabel = this.$refs.player.getCurrentQualityLabel()

全屏控制

// 进入全屏
this.$refs.player.setFullscreen(true)

// 退出全屏
this.$refs.player.setFullscreen(false)

// 切换全屏状态
const isFullscreen = this.$refs.player.isFullscreen()
this.$refs.player.setFullscreen(!isFullscreen)

释放资源

// 停止播放并释放所有资源(组件销毁前调用)
this.$refs.player.release()

完整示例

<template>
  <view>
    <d-player-video
      ref="player"
      src="https://example.com/video.mp4"
      :autoplay="true"
      :loop="false"
      :live="false"
      @statechange="onStateChange"
      @progress=""
      @prepared="onPrepared"
      @completion="onCompletion"
      @error="onError"
    />
    <view class="controls">
      <button @click="togglePlay">播放/暂停</button>
      <button @click="seekForward">快进 10 秒</button>
      <button @click="seekBackward">快退 10 秒</button>
      <button @click="changeSpeed">切换倍速</button>
    </view>
  </view>
</template>

<script lang="uts">
export default {
  data() {
    return {
      isPlaying: false,
      currentTime: 0,
      duration: 0,
      currentSpeed: 1.0
    }
  },
  methods: {
    togglePlay() {
      const state = this.$refs.player.getState()
      if (state === "playing") {
        this.$refs.player.pause()
      } else {
        this.$refs.player.play()
      }
    },

    seekForward() {
      const pos = this.$refs.player.getPosition()
      this.$refs.player.seek(pos + 10000)
    },

    seekBackward() {
      const pos = this.$refs.player.getPosition()
      this.$refs.player.seek(Math.max(0, pos - 10000))
    },

    changeSpeed() {
      const speeds = [0.5, 1.0, 1.5, 2.0]
      const idx = speeds.indexOf(this.currentSpeed)
      this.currentSpeed = speeds[(idx + 1) % speeds.length]
      this.$refs.player.setSpeed(this.currentSpeed)
    },

    onStateChange(e) {
      this.isPlaying = (e.state === "playing")
      console.log('状态变化:', e.state)
    },

    (e) {
      this.currentTime = e.position
      this.duration = e.duration
    },

    onPrepared(e) {
      this.duration = e.duration
      console.log('媒体加载完成,时长:', e.duration)
    },

    onCompletion() {
      console.log('播放完成')
    },

    onError(e) {
      console.error('播放错误:', e.code, e.message)
    }
  },

  onUnmounted() {
    this.$refs.player.release()
  }
}
</script>

事件

事件名 参数 说明
statechange { state } 播放状态变化
progress { position, duration } 播放进度更新
prepared { duration } 媒体加载完成
buffering { percent } 缓冲状态
error { code, message } 播放错误
videosizechanged { width, height } 视频尺寸变化
seekcomplete {} 跳转完成
completion {} 播放完成
livereconnect { attempt } 直播重连

直播拉流

<template>
  <d-player-video
    src="rtmp://live.example.com/stream"
    :live="true"
    :autoplay="true"
    @livereconnect="onReconnect"
  />
</template>

支持的直播协议:

  • HLS (m3u8)
  • HTTP-FLV
  • RTMP
  • RTSP

H.265 支持

组件自动检测 H.265 硬件解码能力:

  • Android:MediaCodec 硬解 + FFmpeg 软解
  • iOS:VideoToolbox 硬解 + FFmpeg 软解
  • Web:ffmpeg.wasm 软解(实验性)
  • 小程序:不支持 H.265

平台支持

平台 状态 说明
uni-app X (Android) 完整支持 libmpv + MediaCodec
uni-app X (iOS) 完整支持 libmpv + VideoToolbox
uni-app NVue 完整支持 同 uni-app X
Web 完整支持 mpegts.js + hls.js
微信小程序 基础支持 原生 video 组件

UI 特性

B站风格控制栏

底部控制栏采用 B 站两层布局设计:

  • 上层:细红色进度条,支持拖动 seek
  • 下层:播放/暂停按钮、时间显示、倍速、音量、全屏

图标样式

  • 播放按钮:饱满三角形(B站风格)
  • 暂停按钮:圆角双竖杠(B站风格)
  • 全屏按钮:四角向外/向内图标
  • 音量按钮:喇叭+声波图标

全屏适配

  • 全屏模式下控制栏自动放大 1.4 倍
  • 保持 B 站风格布局一致

注意事项

  1. H.265 专利风险:H.265 编解码器存在专利许可问题,商业使用需注意授权
  2. Web 端 H.265:依赖 ffmpeg.wasm,性能可能受影响
  3. 小程序限制:微信小程序原生 video 组件不支持 H.265
  4. 直播重连:默认最多重试 3 次,间隔 3 秒
  5. iOS 依赖:首次编译需联网下载 Libmpv 框架(约 10MB)

开发

目录结构

d-player-video/
├── index.uts                    # 全局入口
├── index.vue                    # 根组件
├── package.json                 # uni_modules 配置
├── common/
│   ├── types.uts                # 类型定义
│   ├── events.uts               # 事件常量
│   ├── state-machine.uts        # 状态机
│   ├── player-config.uts        # 配置管理
│   ├── danmaku-types.uts        # 弹幕类型
│   └── quality-types.uts        # 清晰度类型
├── components/
│   ├── DPlayerControl.vue       # 控制栏组件
│   ├── DPlayerProgress.vue      # 进度条组件
│   ├── DPlayerDanmaku.vue       # 弹幕组件
│   └── DPlayerQuality.vue       # 清晰度组件
└── utssdk/
    ├── app-android/
    │   ├── index.vue            # Android UTS 组件
    │   ├── index.uts            # Android 平台函数
    │   ├── config.json          # Android 配置
    │   └── DPlayerNative.kt     # Native 桥接
    ├── app-ios/
    │   ├── index.vue            # iOS UTS 组件
    │   ├── index.uts            # iOS 平台函数
    │   ├── config.json          # iOS 配置
    │   ├── Libmpv.podspec       # CocoaPods 配置
    │   └── DPlayerEngine.swift  # 引擎实现
    ├── web/
    │   └── index.uts            # Web 平台实现
    └── mp-weixin/
        └── index.vue            # 微信小程序实现

更新日志

1.0.2(2026-09-03)

  • 【UI重构】底部控制栏重构为 B 站两层布局(上层细红进度条,下层合并时间与控制按钮)
  • 【图标与样式】更新播放/暂停/全屏图标,加大音量与全屏图标尺寸,全屏模式下控制栏支持 1.4 倍放大
  • 【状态修复】修复视频播放完毕后状态仍停留在 playing 的问题
  • 【类型与编译】修复 UTS 中 Float 与 Number 类型转换导致的 ClassCastException 编译与运行时问题
  • 【包体积优化】iOS 平台改为通过 CocoaPods 远程依赖 Libmpv 框架,极大减小插件上传体积
  • 【文档完善】新增完整 API 使用文档,包含播放控制、音量、速度、弹幕、清晰度、全屏等所有方法的详细说明和示例

1.0.0(2026-08-30)

初始化

许可

MIT License

隐私、权限声明

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

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

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

暂无用户评论。