更新记录

1.0.0(2026-09-21)

  • 新版发布支持iOS、Android、HarmonyOS
  • 支持预加载视频、大量视频不耗内存
  • 支持本地视频、网络视频、rtsp/rtmp
  • 支持自定义互动组件
  • 支持全屏

平台兼容性

uni-app(5.01)

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

uni-app x(5.06)

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

其他

多语言 暗黑模式 宽屏模式
× ×

yt-slide-player 使用文档

yt-slide-player 是面向 uni-app x App 的上下滑视频播放标准式组件。组件支持整页纵向切换、自动播放、播放控制、倍速、音量、播放进度、内置进度条、首尾分页事件,以及 MP4、HLS、RTSP、RTMP 和本地视频等常用播放源。

特别提醒

  • 购买本插件前,请先试用,请先试用,请先试用,确认满足需求之后再行购买。虚拟物品一旦购买之后无法退款。
  • 如有使用上的疑问、bug,可以进交流群联系作者;
  • 请在合法范围内使用,若使用本插件做非法开发,本方概不负责;
  • 插件需先引入再打自定义基座后运行测试
  • 本插件为标准组件只能用于uniapp-x项目
  • 可下载插件提供的示例项目测试、试用。

一、支持范围

  • uni-app x App:iOS、Android、HarmonyOS;
  • Android 7.0 及以上,支持 armeabi-v7aarm64-v8a
  • iOS 12.0 及以上,支持 arm64 真机;
  • 支持网络 MP4、HLS(m3u8)、RTSP、RTMP、本地绝对路径和 file:// 地址;
  • 不支持 Web、普通 uni-app、微信小程序等非 uni-app x App 平台。

插件包含平台能力,调试前需要制作并使用自定义基座。修改或升级插件后,也应重新制作自定义基座。iOS 请使用 arm64 真机或云打包验证,不要使用 iOS 模拟器。

二、快速开始

1. 放置组件

插件安装到项目的 uni_modules/yt-slide-player 后,可直接通过 easycom 使用,无需手动 import 组件。

组件必须设置明确的宽度和高度,否则播放器可能不可见:

<template>
  <view class="page">
    <yt-slide-player
      ref="slidePlayer"
      class="player"
      @ready="onReady"
      @indexchange="onIndexChange"
      @statechange="onStateChange"
      @timeupdate=""
      @requestrefresh="onRequestRefresh"
      @requestloadmore="onRequestLoadMore">
    </yt-slide-player>
  </view>
</template>

<style>
.page {
  position: fixed;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  background-color: #000000;
}

.player {
  width: 100%;
  height: 100%;
}
</style>

2. 获取组件实例

页面通过组件公开实例调用播放方法:

player() : YtSlidePlayerComponentPublicInstance | null {
  return this.$refs['slidePlayer'] as YtSlidePlayerComponentPublicInstance | null
}

不要在 onLoad 中立即调用实例方法。应等待组件触发 ready,再设置播放器参数和视频列表。

3. 设置视频列表

onReady() {
  const player = this.player()
  if (player == null) return

  // 建议先设置配置,再传入列表。
  player.setAutoplay(true)
  player.setVolume(100)
  player.setNativeProgressVisible(true)
  player.setNativeProgressColors('#FFFFFFFF', '#52FFFFFF', '#FFFFFFFF')

  player.setItems(this.items)
}

三、视频数据格式

setItems()appendItems() 接收 UTSJSONObject[]

items: [
  {
    id: 'video-001',
    url: 'https://example.com/video/001.mp4',
    author: '@演示账号',
    title: '视频标题或描述',
    resizeMode: 'cover',

    // 可以继续保存业务字段,供页面自己的点赞、评论等 UI 使用。
    liked: false,
    likeCount: 128,
  },
  {
    id: 'camera-001',
    url: 'rtsp://user:password@192.168.1.10:554/stream',
    author: '@实时画面',
    title: 'RTSP 监控流',
    resizeMode: 'contain',
  },
] as UTSJSONObject[]

字段说明:

字段 类型 是否必填 默认值 说明
id string 建议必填 自动生成 视频的稳定业务标识。列表中的值应唯一,分页追加时也不能重复。
url string 视频地址。也可以使用字段名 source,但推荐统一使用 url
author string 空字符串 显示在视频页面上的作者名称。
title string 空字符串 显示在视频页面上的标题或说明。
resizeMode string cover 当前视频的画面适配方式,只支持 covercontain

业务可在每个 item 中增加点赞、收藏、评论数等自定义字段。插件只读取上表中的播放字段,不会修改其它业务字段。

resizeMode 说明

  • cover:保持视频比例并铺满播放区域,超出区域会居中裁剪。适合竖屏短视频;
  • contain:保持视频比例并完整显示,空余区域显示黑色。适合横屏视频、4:3 视频和监控流;
  • 字段缺失或值不正确时按 cover 处理。

四、全部公开方法

组件当前没有必须传入的 props,所有配置和控制都通过公开方法完成。

1. 列表与自动播放

setItems(items)

替换整个视频列表,并回到第 0 条。

参数 类型 说明
items UTSJSONObject[] 新的视频列表。空数组表示清空列表。

返回值:void

刷新数据、切换频道或替换完整列表时使用:

this.player()?.setItems(newItems)

appendItems(items)

在现有列表尾部追加视频,不切换当前视频,适合分页加载更多。

参数 类型 说明
items UTSJSONObject[] 要追加的视频列表。每条数据应使用新的唯一 id

返回值:void

for (let i = 0; i < moreItems.length; i++) {
  this.items.push(moreItems[i])
}
this.player()?.appendItems(moreItems)

setAutoplay(enabled)

设置传入列表后是否自动播放,默认开启。建议在第一次调用 setItems() 前设置。

参数 类型 说明
enabled boolean true 自动播放,false 等待业务调用 playCurrent()

返回值:void

2. 播放控制

playCurrent()

播放或继续当前视频。返回值:void

this.player()?.playCurrent()

pauseCurrent()

暂停当前视频。返回值:void

this.player()?.pauseCurrent()

toggleCurrentPlayback()

在播放和暂停之间切换,适合绑定到页面按钮或点击事件。返回值:void

this.player()?.toggleCurrentPlayback()

stop()

停止播放并释放播放器相关资源。页面正常卸载时组件会自行清理;业务需要提前停止播放时可主动调用。

返回值:void

this.player()?.stop()

调用 stop() 后,如果还要继续使用组件,建议重新调用 setItems() 建立播放列表。

3. 跳转视频与播放进度

scrollToVideo(index, animated)

跳转到列表中的指定视频。

参数 类型 默认值 说明
index number 目标下标,从 0 开始。应在 0~items.length - 1 范围内。
animated boolean true 是否显示切页动画。

返回值:void

this.player()?.scrollToVideo(3, true)

seekTo(percent)

把当前点播视频跳转到指定百分比。

参数 类型 说明
percent number 目标进度,范围 0~100。例如 50 表示视频中间。

返回值:boolean

  • true:本次进度请求已被接受;
  • false:当前是直播流、视频未准备完成、没有有效总时长,或当前没有可播放数据。
const accepted = this.player()?.seekTo(50) ?? false
if (!accepted) {
  uni.showToast({ title: '当前视频暂不支持进度跳转', icon: 'none' })
}

RTSP、RTMP 等实时流没有稳定的可寻址时间轴,通常不支持 seekTo()

4. 倍速和音量

setPlaybackRate(rate)

设置当前视频的播放倍速。每条视频分别保存自己的倍速,切换视频不会把当前倍速套用到其它视频。

参数 类型 可选值
rate number 0.50.75124

返回值:boolean。设置成功返回 true;倍速不支持或当前没有视频时返回 false

const accepted = this.player()?.setPlaybackRate(2) ?? false

setVolume(value)

设置播放器音量。

参数 类型 说明
value number 0~1000 静音,100 最大音量。越界值会按有效范围处理。

返回值:void

this.player()?.setVolume(80)

5. 内置进度条

setNativeProgressVisible(enabled)

显示或隐藏组件内置的可拖动进度条,默认显示。隐藏后不会停止 timeupdate 回调,也不会禁用 seekTo(),因此可以自行绘制进度 UI。

参数 类型 说明
enabled boolean true 显示,false 隐藏。

返回值:void

this.player()?.setNativeProgressVisible(false)

实时流没有有效总时长时,内置进度条会自动隐藏。

setNativeProgressColors(playedColor, trackColor, thumbColor)

设置内置进度条的三种颜色。

参数 类型 说明
playedColor string 已播放部分颜色。
trackColor string 未播放轨道颜色。
thumbColor string 圆形滑块颜色。

返回值:void

颜色支持 #RRGGBB#AARRGGBB。8 位颜色的前两位是透明度,例如 #52FFFFFF 表示带透明度的白色。

// 默认白色样式
this.player()?.setNativeProgressColors(
  '#FFFFFFFF',
  '#52FFFFFF',
  '#FFFFFFFF'
)

// 绿色样式
this.player()?.setNativeProgressColors(
  '#FF00C853',
  '#5200C853',
  '#FFFFFFFF'
)

颜色格式不正确时,对应部分会使用默认颜色。

6. 状态查询

isPlaying()

返回当前视频是否处于播放状态。

返回值:boolean

const playing = this.player()?.isPlaying() ?? false

getCurrentIndex()

返回当前视频下标,从 0 开始。

返回值:number

const index = this.player()?.getCurrentIndex() ?? 0

getCurrentPlaybackRate()

返回当前视频的播放倍速。

返回值:number

const rate = this.player()?.getCurrentPlaybackRate() ?? 1

五、全部事件回调

<yt-slide-player
  ref="slidePlayer"
  @ready="onReady"
  @indexchange="onIndexChange"
  @statechange="onStateChange"
  @timeupdate=""
  @requestrefresh="onRequestRefresh"
  @requestloadmore="onRequestLoadMore">
</yt-slide-player>
事件 回调数据 触发时机
ready 组件已就绪,可以设置参数并调用 setItems()
indexchange index, itemId 当前显示的视频发生变化。
statechange index, state, message, playing 当前视频的播放状态发生变化。
timeupdate index, currentMs, totalMs, position 播放时间和进度更新。
requestrefresh index 已位于第一条,用户继续向下拉并松手。通常用于刷新列表。
requestloadmore index 已位于最后一条,用户继续向上推并松手。通常用于加载下一页。

回调字段

字段 类型 说明
index number 产生事件的视频下标。
itemId string 当前视频 item 的 id
state string 播放状态,详见下一节。
message string 状态说明或错误提示;可能为空字符串。
playing number 1 表示正在播放,0 表示没有播放。
currentMs number 当前播放时间,单位毫秒。
totalMs number 视频总时长,单位毫秒;直播流通常为 0
position number 归一化进度,范围 0~1。页面显示百分比时乘以 100

不同平台收到的事件可能是 Map,也可能由 detail 包装。可以在页面统一转换:

eventMap(e : any | null) : Map<string, any> {
  if (e == null) return new Map<string, any>()

  if (e instanceof Map) {
    const map = e as Map<string, any>
    if (map.has('detail')) return this.eventMap(map.get('detail'))
    return map
  }

  const objectValue = e as UTSJSONObject
  if (objectValue['detail'] != null) {
    return this.eventMap(objectValue['detail'])
  }

  const result = new Map<string, any>()
  const keys = [
    'index', 'itemId', 'state', 'message', 'playing',
    'currentMs', 'totalMs', 'position'
  ]
  for (let i = 0; i < keys.length; i++) {
    const key = keys[i]
    const value = objectValue[key]
    if (value != null) result.set(key, value)
  }
  return result
}

readNumber(data : Map<string, any>, key : string, fallback : number = 0) : number {
  if (!data.has(key)) return fallback
  return parseFloat(`${data.get(key)}`)
}

readInteger(data : Map<string, any>, key : string, fallback : number = 0) : number {
  return Math.round(this.readNumber(data, key, fallback))
}

readString(data : Map<string, any>, key : string) : string {
  if (!data.has(key)) return ''
  return `${data.get(key)}`
}

页面中的回调下标是 UTS number,需要整数时统一使用 Math.round() 转换,以保证跨平台写法一致。

播放状态 state

statechange.state 可能为:

state 说明 常见 UI
idle 尚未设置或已经停止 隐藏加载提示
preparing 正在连接和准备视频 显示加载中
ready 已准备完成 等待播放或即将播放
playing 正在播放 隐藏加载提示和暂停提示
paused 已暂停 显示暂停状态或播放按钮
buffering 正在缓冲 显示加载中
ended 播放结束 根据业务更新 UI
failed 播放失败 使用 message 显示错误信息或重试入口

切换视频期间,上一条视频可能产生最后一次状态回调。因此应先比较回调中的 index,只用当前下标更新页面 UI:

onStateChange(e : any) {
  const data = this.eventMap(e)
  const index = this.readInteger(data, 'index', -1)
  if (index != this.currentIndex) return

  this.state = this.readString(data, 'state')
  this.message = this.readString(data, 'message')
  this.showLoading = this.state == 'preparing' || this.state == 'buffering'
  this.isPlaying = this.state == 'playing'
}

进度回调

onTimeUpdate(e : any) {
  const data = this.eventMap(e)
  const index = this.readInteger(data, 'index', -1)
  if (index != this.currentIndex) return

  this.currentMs = this.readNumber(data, 'currentMs', 0)
  this.totalMs = this.readNumber(data, 'totalMs', 0)
  this.progressPercent = this.readNumber(data, 'position', 0) * 100
}

如果自行使用 <slider> 控制进度,松手时再调用一次 seekTo()

<slider
  :value="progressPercent"
  :min="0"
  :max="100"
  :step="0.1"
  :disabled="totalMs <= 0"
  @change="Change" />
onSeekChange(e : UniSliderChangeEvent) {
  if (this.totalMs <= 0) return
  const accepted = this.player()?.seekTo(e.detail.value) ?? false
  if (!accepted) {
    uni.showToast({ title: '当前视频暂不支持拖动', icon: 'none' })
  }
}

六、刷新和加载更多

在第一条继续向下拉会触发 requestrefresh。刷新完成后使用 setItems() 替换列表:

onRequestRefresh(_e : any) {
  // 此处替换成项目自己的网络请求。
  const refreshedItems = this.items
  this.player()?.setItems(refreshedItems)
}

在最后一条继续向上推会触发 requestloadmore。请求成功后使用 appendItems() 追加数据:

onRequestLoadMore(_e : any) {
  // 此处替换成项目自己的分页请求。
  const moreItems = [
    {
      id: `page-${this.page}-video-1`,
      url: 'https://example.com/more.mp4',
      author: '@新视频',
      title: '加载更多返回的视频',
      resizeMode: 'cover',
    },
  ] as UTSJSONObject[]

  for (let i = 0; i < moreItems.length; i++) {
    this.items.push(moreItems[i])
  }
  this.player()?.appendItems(moreItems)
}

需要自行增加“正在请求”和“没有更多数据”标记,避免用户连续越界时重复请求接口。

七、完整页面示例

完整示例请点击使用HBuilderX导入示例项目包含初始化、所有事件、播放/暂停、跳转、倍速、音量、内置进度条、状态查询、刷新和加载更多。业务项目可以在播放器上方继续叠加关注、点赞、评论、收藏、分享等页面 UI。

八、全屏页面

如果页面就是全屏短视频流,可在 pages.json 中关闭系统导航栏:

{
  "path": "pages/index/index",
  "style": {
    "navigationStyle": "custom",
    "pageOrientation": "portrait"
  }
}

播放器使用 width: 100%height: 100% 或固定定位铺满页面。进入横屏时只需要修改页面方向和布局,不需要销毁、隐藏或重新创建播放器组件;横屏后仍可继续上下滑动。

不要使用 v-if 反复创建和销毁 <yt-slide-player>。需要遮挡播放器时,优先在组件上方叠加普通 uni-app x 页面元素。

九、使用注意事项

  1. 所有初始化调用应放在 ready 回调中;
  2. 每条数据建议提供唯一且稳定的 id
  3. 刷新列表使用 setItems(),加载更多使用 appendItems()
  4. timeupdate.position 范围是 0~1seekTo(percent) 参数范围是 0~100,不要混用;
  5. RTSP、RTMP 通常不支持拖动进度,暂停后再次播放会回到当前实时画面;
  6. 页面只处理与 currentIndex 相同的状态和时间回调,避免旧视频回调覆盖当前 UI;
  7. 互动按钮、业务 loading、错误提示等 UI 可放在 uni-app x 页面中自行设计;
  8. 网络地址是否可播放还取决于地址有效性、网络权限、服务器协议和设备能否访问该地址;
  9. 插件更新后如出现“找不到方法”或原生能力没有更新,请清理项目编译缓存并重新制作自定义基座。

十、常见问题

组件显示黑屏或完全不可见

先确认组件具有明确宽高,再确认已收到 ready 并调用 setItems()。同时检查视频地址能否在当前设备网络中访问。

为什么横屏视频显示不完整

该条视频使用了 cover。把当前 item 的 resizeMode 改为 contain 即可完整显示。

为什么 seekTo() 返回 false

常见原因包括:当前是 RTSP/RTMP 实时流、视频尚未准备完成、totalMs0,或者当前列表为空。建议在 timeupdate.totalMs > 0 后再启用自定义拖动控件。

如何根据播放状态显示页面 UI

监听 statechangepreparingbuffering 显示加载状态,playing 隐藏加载状态,paused 显示暂停状态,failed 使用 message 展示错误或重试入口。

如何加载 100 条或更多数据

可以直接设置列表,但实际业务更建议分页加载。首屏先调用 setItems(),收到 requestloadmore 后请求下一页并调用 appendItems()

为什么更新插件后仍提示找不到新方法

停止当前运行任务,清理 HBuilderX 项目编译缓存后重新编译;如果新增或修改了平台能力,还需要重新制作对应平台的自定义基座。

十一、更多好用插件推荐

隐私、权限声明

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

Android 需要网络、网络状态和唤醒锁权限;iOS 播放局域网 RTSP 时需要本地网络权限。

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

插件不采集任何数据

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

暂无用户评论。