更新记录
5.1.0(2026-09-01)
新增功能
- 新增 Seek 模式选择:支持精确模式(Accurate)与快速模式(Inaccurate)两种 Seek 策略,接入方可按需选择,兼顾精度与响应速度
- 新增播放器日志级别控制(
setPlayerLogLevel),生产环境可一键降噪,仅输出关键日志 - 新增 iOS 端下载通知管理:下载进度与完成/失败通知实时推送,与 Android 体验对齐
- 新增 Android 端延迟创建机制:播放器实例按需创建,减少页面启动耗时,提升起播速度
体验优化
- Android 小窗/画中画稳定性全面增强:引入确定性准入机制,系统拒绝后自动降级应用内浮窗,能力恢复后自动回升,消除"时拒时成" 的随机体验
- Android 浮窗关闭逻辑优化:关窗即结束播放,避免资源残留
- iOS 手势快进快退体验与 Android 完全对齐:灵敏度随时长自适应、基准位置锁定、进度条拖动防抖
- 封面加载中断处理优化:快速切集时及时取消前一次封面请求,避免旧封面覆盖新封面
- Android 事件载荷传输机制优化:事件数据传递更稳定、更完整
问题修复
- 修复画中画模式下播放/暂停、快进快退按钮不显示或点击无响应的问题
- 修复画中画模式下快进快退导致 UI 闪烁的问题
- 修复 Android 浮窗态播放被意外暂停的问题:离屏暂停守卫补全小窗接管感知,浮窗全程持续播放
- 修复 Android 纯音频模式下封面截取不显示的问题
- 修复 Android 端播放器线程安全问题
- 修复锁屏/息屏时播放器自动进入小窗的问题
- 修复 iOS 全屏态进入画中画后停留横屏的问题
- 修复 iOS 定时关闭选择"播完当前"不生效的问题
- 修复 iOS 更多菜单及弹层按钮无法点击的问题
- 修复播放器实例切换时 viewready 事件发射异常的问题
- 修复竖屏模式下进度条拖动失效的问题
- 修复悬浮窗关闭逻辑异常:现关窗即结束播放,行为符合预期
- 修复 Android 端播放器 ID 重复注册导致事件异常的问题
环境要求
| 项目 | 要求 |
|---|---|
| HBuilderX | 3.99+ |
| Android | 8.0+(API 26,画中画要求) |
| iOS | 13.0+(系统画中画需 iOS 15+) |
| 打包方式 | 自定义调试基座 / 云打包正式包(不支持标准基座) |
| License | 阿里云播放器 SDK 7.0.0+ 需配置 LicenseKey 与证书,详见 readme「License 配置」章节 |
平台兼容性
uni-app(3.99)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | Android插件版本 | iOS | iOS插件版本 | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|---|---|
| - | - | - | - | - | - | 8.0 | 5.1.0 | 13 | 5.1.0 | - |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| - | - | - | - | - | - | - | - | - | - | - | - |
阿里云播放器SDK(ApsaraVideo Player)
uni-app 版阿里云播放器组件:基于 ApsaraVideo Player SDK 封装的 UTS 插件(组件 + 模块混合形态),Android / iOS 双端能力对齐。 内置企业级控制栏与手势交互,提供小窗播放、投屏、后台播放、纯音频、倍速、定时关闭、下载等开箱即用的播放能力。 仅支持 App 端(Android + iOS),H5 / 小程序请使用阿里云官方 Web 播放器。
核心接入方式:
- 在模板中放置
<ali-player-view>组件(承载视频渲染 + 内置控制栏)- 通过 Props 设置播放源(
src/vid+playAuth/vid+ STS)和参数- 通过
ref调用组件方法(prepare()、play()、seekTo()等)- 事件通过组件的
@ready/@play/@ended等回调接收(双端事件负载统一使用detail键包裹,业务层通过e.detail || e提取)- 竖屏返回按钮通过
@back事件通知 Vue 层(通常执行uni.navigateBack())
目录
功能概览
| 功能类别 | 支持能力 |
|---|---|
| 播放方式 | URL 直播/点播、VidAuth(推荐)、VidSts |
| 视频格式 | MP4、HLS (M3U8)、FLV、RTMP、RTS 超低延时直播 |
| 播放控制 | 播放/暂停/停止/Seek/重加载/续播 |
| 画面控制 | 缩放模式、旋转、镜像 |
| 音频控制 | 音量、静音 |
| 内置控制栏 | 播放/暂停、进度条、全屏切换、倍速、纯音频、画中画、返回 |
| “更多”抽屉 | 分享/收藏/倍速/定时关闭/下载,条目与顺序可配置(moreActions) |
| 倍速播放 | 弹层宫格 + 自定义滑杆(0.5~4.0),预设档位可配置(speedPresets) |
| 定时关闭 | 不开启/播完当前/倒计时,倒计时档位可配置(sleepTimerPresets) |
| 视频下载 | vid 源走阿里云 SDK 下载器;URL 源插件自实现 HTTP 下载(m3u8 逐分片合并 .ts) |
| UI 定制 | 主题色 themeColor 一键换色、全部内置文案 texts 可覆盖(多语言) |
| 画中画(PiP) | Android 8.0+ / iOS 15+ 系统级画中画,画面自适应、进出过渡自然 |
| 小窗播放 | 统一入口 enterSmallWindow():Android 腾讯视频式分层浮窗(系统画中画 + 应用内浮窗兜底),iOS 系统画中画,支持离开 App 自动起窗 |
| 投屏 | Android DLNA/UPnP(设备搜索 + URL 推送)、iOS 系统 AirPlay |
| 熄屏/锁屏播放 | Android WakeLock + AudioFocus、iOS AVAudioSession 后台音频 |
| 后台播放(Android) | 后台保活、媒体通知栏 + 锁屏 MediaSession 控制、后台自动切纯音频 |
| 纯音频模式 | 听视频功能(仅播放音频不渲染画面) |
| 性能 | 本地缓存(边播边缓存)、网络自适应码率(HLS ABR) |
| 安全 | HLS AES-128 加密、阿里云私有加密 |
| 截图 | 截取当前帧并返回本地文件路径 |
平台支持
| 平台 | 支持 | 最低版本 |
|---|---|---|
| Android | ✅ | minSdkVersion 26(Android 8.0,PiP 要求) |
| iOS | ✅ | deploymentTarget 13.0(系统画中画要求 iOS 15+) |
| H5 | ❌ | 请使用 Aliplayer Web SDK |
| 微信小程序 | ❌ | — |
| HarmonyOS | ❌ | — |
本插件通过
// #ifdef APP-PLUS条件编译自动屏蔽非 App 端,不影响其他平台构建。
安装方式
方式一:从 uni-app 插件市场安装(推荐)
- 前往 DCloud 插件市场 搜索「阿里云播放器SDK」
- 点击「使用 HBuilderX 导入插件」,自动复制到项目
uni_modules/lord-aliyun-player/ - 完成 集成配置 后制作自定义基座
方式二:手动拷贝
本插件为标准
component-uts格式 UTS 插件,导入项目uni_modules/后开箱即用。
uni_modules/lord-aliyun-player/
├── utssdk/
│ ├── interface.uts # 类型定义与 Module API 契约
│ ├── app-android/ # Android 平台实现(含 License 证书与配置)
│ └── app-ios/ # iOS 平台实现(含 License 证书与配置)
├── pages/demo/ # 可运行示例 Demo
├── pages_init.json # Demo 路由自动注册清单
├── docs/ # 集成指南等使用者文档
├── changelog.md # 更新日志(面向使用者)
├── package.json
└── readme.md # 本文档(插件详情页正文)
集成配置
⚠️ 原生插件必须通过「自定义基座」或「正式打包」才能运行,不支持标准基座。
Android 配置
使用 UTS 插件格式(本插件)无需手动配置 build.gradle:
插件内部的 utssdk/app-android/config.json 已自动声明阿里云播放器 SDK 的 Maven 依赖(AliyunPlayer:7.14.0-full)与阿里云 Maven 仓库,HBuilderX 云打包时自动处理。
License 配置同样已内置:AndroidManifest.xml 的 licensekey / licensefile 两条 meta-data 与证书文件(assets/cert/AliVideoCert.crt)均已就位,详见 License 配置。
使用者仅需按需补充以下两处配置:
1. AndroidManifest.xml 添加权限
<!-- 网络相关(必须) -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- 本地缓存/截图(需要访问外部存储时加) -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28" />
<!-- 后台播放(如使用前台 Service) -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<!-- 熄屏播放保活(PARTIAL_WAKE_LOCK,不点亮屏幕) -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
2. 开启 PiP(画中画)支持
在 manifest.json → App原生配置 → AndroidManifest.xml 配置 中,为主 Activity 添加:
<activity
android:name="io.dcloud.PandoraEntry"
android:supportsPictureInPicture="true"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboardHidden|keyboard|navigation|fontScale|locale|uiMode|colorMode"
android:exported="true"
android:hardwareAccelerated="true"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustResize" />
iOS 配置
使用 UTS 插件格式(本插件)无需手动编辑 Podfile:
插件内部的 utssdk/app-ios/config.json 已自动声明 CocoaPods 依赖(AliPlayerSDK_iOS 7.16.0)、deploymentTarget(13.0)与所需系统 frameworks / libraries,HBuilderX 云打包时自动处理。
License 配置同样已内置:Info.plist 的 AlivcLicenseKey / AlivcLicenseFile 与证书文件(Resources/AliVideoCert.crt)均已就位,详见 License 配置。
使用者仅需按需补充以下配置:
1. 后台播放/PiP 与 HTTP 访问(manifest.json)
在 manifest.json → App 原生配置 → iOS Info.plist 配置 节点中添加以下内容(HBuilderX 云打包自动合并进原生工程,无需在 Xcode 中操作):
<!-- 允许 HTTP(如视频地址是 HTTP) -->
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<!-- 熄屏/锁屏后台播放 + PiP(画中画)必须添加 -->
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
</array>
不配置此项,iOS 熄屏后播放会被系统中止,PiP 也无法进入后台浮窗。
快速开始
基础播放示例
<template>
<view class="container">
<!-- 播放器视图组件(仅 APP 端渲染) -->
<!-- #ifdef APP-PLUS -->
<ali-player-view
ref="player"
:src="videoUrl"
:autoplay="true"
:show-controls="true"
:auto-hide-controls="true"
@ready="onReady"
@play="onPlay"
@pause="onPause"
@ended=""
@error="onError"
@timeupdate=""
@fullscreenchange=""
@pipchange="onPipChange"
@back="onPlayerBack"
/>
<!-- #endif -->
</view>
</template>
<script>
export default {
data() {
return {
videoUrl: 'https://example.com/video.mp4'
}
},
methods: {
// 准备完成,可获取时长等信息
onReady(e) {
console.log('播放器准备完成,时长:', e.duration)
},
onPlay() {
console.log('开始播放')
},
onPause() {
console.log('暂停播放')
},
() {
console.log('播放完成')
},
onError(e) {
console.error('播放错误:', e.code, e.message)
uni.showToast({ title: '播放失败', icon: 'none' })
},
(e) {
// e.currentTime 和 e.duration 为 Long 类型(毫秒)
console.log('播放进度:', e.currentTime, '/', e.duration)
},
(e) {
console.log('全屏状态:', e.fullScreen === 1 ? '全屏' : '竖屏')
},
onPipChange(e) {
console.log('PiP 状态:', e.isInPip === 1 ? '已进入' : '已退出')
},
// 竖屏时点击返回按钮触发,通常执行页面返回
onPlayerBack() {
uni.navigateBack()
},
// 通过 ref 调用组件方法
togglePlay() {
this.$refs.player.togglePlayPause()
},
seekTo(positionMs) {
this.$refs.player.seekTo(positionMs)
},
enterPip() {
this.$refs.player.enterPip()
},
toggleFullScreen() {
this.$refs.player.toggleFullScreen()
}
}
}
</script>
<style>
.container {
flex: 1;
background-color: #000;
}
</style>
VidAuth 播放示例
<template>
<!-- #ifdef APP-PLUS -->
<ali-player-view
ref="player"
vid="your-video-id"
play-auth="your-play-auth-token"
region="cn-shanghai"
:autoplay="true"
@ready="onReady"
@back="onPlayerBack"
/>
<!-- #endif -->
</template>
VidSts 播放示例
<template>
<!-- #ifdef APP-PLUS -->
<ali-player-view
ref="player"
vid="your-video-id"
access-key-id="STS_KEY_ID"
access-key-secret="STS_KEY_SECRET"
security-token="STS_TOKEN"
region="cn-shanghai"
:autoplay="true"
@ready="onReady"
@back="onPlayerBack"
/>
<!-- #endif -->
</template>
Props 属性
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| src | String | '' |
播放 URL(URL 播放模式) |
| vid | String | '' |
视频 ID(VidAuth / VidSts 模式) |
| playAuth | String | '' |
VidAuth 播放凭证 |
| accessKeyId | String | '' |
VidSts AccessKeyId |
| accessKeySecret | String | '' |
VidSts AccessKeySecret |
| securityToken | String | '' |
VidSts SecurityToken |
| title | String | '' |
视频标题 |
| subtitle | String | '' |
视频副标题(控制栏标题下方第二行/媒体通知栏副标题) |
| autoplay | Boolean | false |
是否自动播放 |
| muted | Boolean | false |
是否静音 |
| loop | Boolean | false |
是否循环播放 |
| playbackSpeed | Number | 1.0 |
初始播放速度 |
| playerId | String | '' |
播放器实例 ID(插件路由键)。组件自动管理:未传时自动生成全局唯一 id,并经 ready/viewready 事件 playerId 字段回传;多实例场景也可显式传入全局唯一 id(显式重复 id 会被拒绝注册并告警) |
| region | String | 'cn-shanghai' |
接入地域(VidAuth/VidSts 模式) |
| showControls | Boolean | true |
是否显示控制栏 |
| autoHideControls | Boolean | true |
是否自动隐藏控制栏(播放5秒后) |
| coverImage | String | '' |
封面图 URL。传入时作为海报(poster)在首帧渲染前全幅展示,首帧后自动隐藏;未传入时插件自动在播放前采样生成最优封面(同一视频再次进入秒显且画面一致);置空串可清除外部封面并回退自动生成封面 |
| pipOption | Object | { width: 0, height: 0 } |
画中画宽高比配置(0=自动从视频尺寸计算),保留参数,双端均由系统自动管理 |
| episodes | Array | [] |
选集列表(标准结构 EpisodeItem[],见下方说明)。长度 >1 且横屏全屏时,底部控制栏“选集”按钮替换全屏按钮,点击弹出右侧选集面板 |
| episodesJson | String | '' |
选集列表 JSON 字符串(EpisodeItem[] 序列化,与 episodes 等价的保底通道)。部分兼容场景下对象数组 prop 响应可能不稳定,字符串形态更可靠;非空时优先于 episodes 生效,推荐两者同时绑定(重复下发会被插件自动去重) |
| episodeIndex | Number | 0 |
当前播放集索引(0 基,选集面板高亮回显用)。切集后由调用者回灌保持同步 |
| favorited | Boolean | false |
当前视频是否已收藏(驱动“更多”抽屉收藏图标空心/实心)。收藏业务由调用者实现:监听 @moreaction(action='favorite')调业务接口,成功后回写此 prop 完成图标回显 |
| moreActions | Array | ['share','favorite','speed','timer','download'] |
“更多”抽屉条目与顺序(未知标识自动过滤)。空数组隐藏控制栏“更多”按钮;默认全量五项 |
| speedPresets | Array | [4.0,3.0,2.0,1.5,1.25,1.0,0.75] |
倍速弹层预设档位(顺序即宫格展示顺序,非正数档位自动过滤) |
| sleepTimerPresets | Array | [30,60] |
定时关闭倒计时档位分钟数(“不开启/播完当前”固定项不受影响) |
| themeColor | String | '#00A8F6' |
主题色(#RRGGBB/#AARRGGBB):控制栏进度条/投屏高亮/抽屉高亮/选集当前集同源换色 |
| texts | Object | {} |
UI 文案覆盖表(key 见下方文案定制,未覆盖项用默认中文文案) |
选集数据标准结构(EpisodeItem)
episodes 数组每项为一个 EpisodeItem 对象(类型定义见 utssdk/interface.uts):
[
{
"title": "第1集 开篇",
"url": "https://example.com/ep1.mp4",
"vid": "",
"coverUrl": "https://example.com/ep1.jpg",
"duration": 1260,
"extra": { "materialId": "10001" }
},
{ "title": "第2集 进阶" }
]
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| title | String | ✅ | 集标题(选集面板行文本,缺省回退“第X集”) |
| url | String | ✖ | 该集播放地址(URL 模式换源用,插件透传不消费) |
| vid | String | ✖ | 该集视频 ID(VidAuth/VidSts 模式换源用,插件透传不消费) |
| coverUrl | String | ✖ | 该集封面图 URL(透传) |
| duration | Number | ✖ | 该集时长(秒,透传) |
| extra | Any | ✖ | 业务自定义数据(episodeselect 事件原样回传) |
设计原则:插件仅消费
title渲染选集面板,不自动换源——播放模式(URL / VidAuth / VidSts)由业务层决定。 用户点选后插件派发episodeselect事件(携带index与完整episode条目),由调用者取源切集并回灌episodeIndex保持高亮同步;播完自动连播同理只需回灌episodeIndex。
// 典型接入:点选后取 episode.url 换源,并回灌 episodeIndex
onEpisodeSelect(e) {
const { index, episode } = e.detail || e;
this.currentEpisode = index; // 回灌 :episodeIndex
this.src = episode.url; // 或按 episode.vid 走 VidAuth/VidSts 换源
}
组件方法(通过 ref 调用)
平台列:
双端= Android + iOS 均支持;Android/iOS= 仅对应平台生效。标注@deprecated的方法仍可用,但建议改用统一入口。
| 方法 | 参数 | 平台 | 说明 |
|---|---|---|---|
| play() | — | 双端 | 播放 |
| pause() | — | 双端 | 暂停 |
| stop() | — | 双端 | 停止 |
| prepare() | — | 双端 | 准备播放(设置播放源后调用) |
| seekTo(positionMs, seekMode) | Long, String | 双端 | 跳转到指定位置(毫秒);seekMode:'accurate' 精确 / 'inaccurate' 快速(缺省精确) |
| setUrl(url) | String | 双端 | 设置 URL 播放源 |
| setAutoPlay(autoPlay) | Boolean | 双端 | 设置自动播放 |
| setSpeed(speed) | Number | 双端 | 设置播放速度 |
| setAudioOnlyMode(enabled) | Boolean | 双端 | 设置纯音频模式 |
| exitAudioOnlyMode() | — | 双端 | 退出纯音频模式(恢复视频播放) |
| setCoverImageUrl(url) | String | 双端 | 设置封面图(避免与 coverImage prop 自动 setter 冲突);传空串清除外部封面并回退首帧快照兜底(播放前窗口采帧择优结果) |
| enableKeepPlayingOnScreenOff() | — | 双端 | 开启熄屏播放 |
| disableKeepPlayingOnScreenOff() | — | 双端 | 关闭熄屏播放 |
| snapshot() | — | 双端 | 截图(结果通过 snapshot 事件返回) |
| toggleControls() | — | 双端 | 切换控制栏显隐 |
| togglePlayPause() | — | 双端 | 切换播放/暂停 |
| toggleFullScreen() | — | 双端 | 切换全屏 |
| getCurrentPosition(callback) | Function | 双端 | 获取当前播放位置(毫秒),callback 回调 |
| getDuration(callback) | Function | 双端 | 获取视频总时长(毫秒),callback 回调 |
| enterSmallWindow() | — | 双端 | 进入小窗(推荐统一入口,返回 Boolean)。Android 分层浮窗(系统画中画 + 应用内浮窗兜底),iOS 系统画中画 |
| exitSmallWindow() | — | 双端 | 退出小窗(自动识别当前小窗类型) |
| isInSmallWindow() | — | 双端 | 查询是否处于小窗(返回 Boolean) |
| setAutoSmallWindowOnLeave(enabled) | Boolean | 双端 | 设置“离开 App 自动进小窗”开关(默认开启) |
| setSmallWindowRequirePermission(enabled) | Boolean | 双端 | @deprecated 历史“小窗强依赖悬浮窗权限”开关;当前版本小窗已统一为系统画中画,为空实现占位,仅为兼容保留 |
| enterPip() | — | 双端 | 进入画中画(返回 Boolean)。@deprecated 请用 enterSmallWindow() |
| exitPip() | — | 双端 | 退出画中画。@deprecated 请用 exitSmallWindow() |
| isInPipMode() | — | 双端 | 查询是否处于画中画(返回 Boolean)。@deprecated 请用 isInSmallWindow() |
| enterPipWithRatio(videoWidth, videoHeight) | Number, Number | Android | 进入画中画并指定宽高比(0=自动计算) |
| showFloatWindow() | — | Android | 显示悬浮窗。@deprecated 请用 enterSmallWindow() |
| hideFloatWindow() | — | Android | 隐藏悬浮窗。@deprecated 请用 exitSmallWindow() |
| setMediaNotificationEnabled(enabled) | Boolean | Android | 媒体通知栏 + 锁屏 MediaSession 控制开关(默认开启) |
| setKeepPlayingInBackground(enabled) | Boolean | Android | App 退到后台是否继续播放(默认 true,不自动暂停) |
| setBackgroundAudioEnabled(enabled) | Boolean | Android | 后台自动切纯音频开关(默认开启,回前台自动恢复视频) |
| showDlnaDeviceList() | — | 双端 | 打开投屏入口(Android:设备列表弹窗;iOS:系统 AirPlay 选择器) |
| startDlnaCasting(deviceId, deviceName) | String, String | 双端 | 开始投屏(iOS 忽略参数,直接调起系统选择器) |
| stopDlnaCasting() | — | 双端 | 停止投屏(iOS 无法强制断开,调起系统选择器由用户断开) |
| isDlnaCasting() | — | 双端 | 查询是否正在投屏(返回 Boolean) |
| pauseDlnaCasting() | — | 双端 | 暂停投屏播放(iOS 映射为本地播放器暂停) |
| resumeDlnaCasting() | — | 双端 | 继续投屏播放(iOS 映射为本地播放器继续) |
| seekDlnaCasting(positionMs) | Long | 双端 | 投屏 seek(毫秒,iOS 映射为本地播放器 seek) |
| setDlnaVolume(level) | Int | 双端 | 设置投屏音量(0-100,iOS 映射为本地播放器音量) |
| showSleepTimerSheet() | — | 双端 | 弹出“定时关闭”选择弹层 |
| setSleepTimer(mode, minutes) | String, Number | 双端 | 设置定时关闭(mode: off/current/countdown,minutes 仅 countdown 有效) |
| showSpeedSelectSheet() | — | 双端 | 弹出“倍速设置”选择弹层 |
| startDownload() | — | 双端 | 开始下载当前视频(抽屉“下载”条目点击时原生已自动处理,此方法供自定义 UI 主动发起) |
| stopDownload() | — | 双端 | 停止当前下载任务 |
| isDownloading() | — | 双端 | 查询是否有下载任务进行中(返回 Boolean) |
| setSecureDownloadKeyFile(path) | String | 双端 | 配置安全下载密钥文件(encryptedApp.dat 本地绝对路径,加密视频下载必需,全局一次即可) |
Module API(跨页面调用)
除上述 ref 方法外,插件另导出一套同步 Module API(共 70 个)。二者底层驱动同一个原生 View,选用原则:
- 优先用
ref方法:同页面内调用,无需关心playerId - 用 Module API:调用方与播放器组件不在同一页面时(如独立投屏页、全局音频控制器),此时拿不到
ref
import { play, pause, setAudioOnly, getCurrentPosition } from '@/uni_modules/lord-aliyun-player'
// 入参统一为单个 options 对象,playerId 缺省 'default'(需与组件的 player-id 属性一致)
play({ playerId: 'main-player' })
setAudioOnly({ playerId: 'main-player', enabled: true })
// 出参统一 { code, message?, ...data },code === 0 为成功
const res = getCurrentPosition({ playerId: 'main-player' })
if (res.code === 0) {
console.log('当前位置', res.position)
}
// 日志降噪(全局生效,与 playerId 无关):release 环境建议 'warn' 或 'off'
import { setPlayerLogLevel } from '@/uni_modules/lord-aliyun-player'
setPlayerLogLevel({ level: 'warn' })
调用前提:绝大多数 API 需播放器 View 已挂载(组件已渲染),View 不存在时返回
{ code: -1, message: 'View not found for playerId: xxx' }。完整函数清单、参数与返回结构见utssdk/interface.uts。
事件列表
平台列:
双端= Android + iOS 均派发;Android= 仅 Android 派发(iOS 不派发,调用方不应在 iOS 上依赖)。 注意:为保证双端序列化一致,布尔字段统一以Int(1/0)传递,判断时用e.xxx === 1或直接真值判断。
| 事件名 | detail 结构 | 平台 | 说明 |
|---|---|---|---|
| play | — | 双端 | 播放 |
| pause | — | 双端 | 暂停 |
| timeupdate | { currentTime: Long, duration: Long } |
双端 | 播放进度更新 |
| ended | — | 双端 | 播放完成 |
| error | { code: Int, message: String } |
双端 | 播放错误 |
| fullscreenchange | { fullScreen: Int(1/0), direction: String } |
双端 | 全屏状态变化 |
| ready | { duration: Long, playerId: String } |
双端 | 准备完成;playerId 为生效的路由 id,供 Module API 使用 |
| viewready | { playerId: String, initOk: Int(1/0) } |
双端 | 原生视图就绪:原生视图初始化完成、事件通道已挂接时发射,早于一切播放事件。Module API 调用建议据此门控;initOk=0 表示实例创建失败,不应再重试 |
| pipchange | { isInPip: Int(1/0) } |
双端 | PiP 状态变化 |
| smallwindowchange | { active: Int(1/0), mode: String } |
双端 | 小窗状态变化(mode:'pip' 系统画中画 / 'float' 应用内浮窗;iOS 恒为 'pip',Android 按权限择优) |
| audioonlychange | { isAudioOnly: Int(1/0) } |
双端 | 纯音频模式变化 |
| exitaudioonly | — | 双端 | 退出纯音频模式 |
| audiofocuschange | { focusChange: String } |
双端 | 音频焦点/会话打断变化(Android AudioFocus;iOS 来电、闹钟、其他 App 抢占,取值口径与 Android 对齐:LOSS_TRANSIENT/GAIN) |
| mutedchange | { isMuted: Int(1/0) } |
双端 | 静音状态变化(手势调音量自动取消静音时通知) |
| loading | { isLoading: Int(1/0) } |
双端 | 缓冲状态 |
| seekcomplete | — | 双端 | Seek 完成 |
| videosizechanged | { width: Int, height: Int } |
双端 | 视频尺寸变化 |
| statechanged | { state: Int, stateName: String } |
双端 | 播放器状态变化 |
| snapshot | { path: String } |
双端 | 截图完成 |
| trackchanged | { success: Int(1/0), trackIndex: Int, trackType: String, errorCode: Int, errorMsg: String } |
双端 | 轨道切换 |
| renderingstart | — | 双端 | 首帧渲染 |
| controlchange | { show: Int(1/0) } |
双端 | 控制栏显隐变化 |
| back | — | 双端 | 竖屏返回按钮点击(通常执行 uni.navigateBack()) |
| castingstart | { deviceName: String } |
双端 | 投屏已开始 |
| castingstop | — | 双端 | 投屏已停止 |
| castingerror | { code: Int, message: String } |
双端 | 投屏出错(code 对应 CastingErrorCode) |
| castingstatechange | { state: Int, stateName: String, deviceName: String, code: Int, message: String } |
双端 | 统一投屏会话状态变更(推荐监听,state 对应 CastState) |
| castprogress | { currentTime: Long, duration: Long } |
双端 | 投屏播放进度回传(毫秒) |
| episodeselect | { index: Int, episode: EpisodeItem } |
双端 | 选集面板点选非当前集。index 为 0 基集索引,episode 为 episodes 中对应条目原样回传(含 url/vid/extra 等透传字段);插件不自动换源,由调用者切集后回灌 episodeIndex |
| moreaction | { action: String } |
双端 | “更多”抽屉条目点击(share/favorite/speed/timer/download)。speed/timer/download 原生已自动处理(仍派发通知);share/favorite 需调用者实现业务 |
| ratechange | { rate: Number } |
双端 | 倍速变更(弹层宫格/自定义滑杆/setSpeed 调用均派发) |
| sleeptimerchange | { mode: String, remainingMs: Long } |
双端 | 定时关闭状态变更(mode: off/current/countdown,非 countdown 时 remainingMs 为 0) |
| sleeptimerfinish | { mode: String } |
双端 | 定时关闭已生效(倒计时到点已暂停 / 播完当前即将 ended) |
| downloadprogress | { percent: Int } |
双端 | 下载进度(0-100);Android 同步刷新通知栏常驻进度通知 |
| downloadcomplete | { filePath: String } |
双端 | 下载完成(本地文件绝对路径)。Android 完成后自动导出到系统公共「下载」目录(Download/<应用名>/,文件管理器可见,filePath 为导出后路径),并展示可点击打开的完成通知;iOS 保存在沙盒 Documents/aliplayer_download,宿主工程开启 UIFileSharingEnabled + LSSupportsOpeningDocumentsInPlace 后可在「文件」App 中找到 |
| downloaderror | { code: String, message: String } |
双端 | 下载失败(code 为字符串错误码,见 interface.uts 的 DownloadErrorEventData) |
back事件说明:内置控制栏的返回按钮行为根据横竖屏自动区分:
- 横屏(全屏):点击返回 → 退出全屏回到竖屏
- 竖屏:点击返回 → 触发
back事件,由 Vue 层决定行为(通常uni.navigateBack())
示例 Demo(随插件内置)
插件内置一个可直接运行的完整 Demo(位于插件包内,符合 uni_modules 目录规范):
| 文件 | 说明 |
|---|---|
pages/demo/index.nvue |
Demo 播放页:Props/事件/ref 方法全演示,含选集换源、断点续播、错误重试、生命周期释放等企业级写法 |
pages/demo/demo-data.json |
示例数据(模拟服务端“视频详情接口”响应) |
pages/demo/api.js |
服务端接口封装示例(Mock/真实接口一键切换,基于 uni.request 自包含实现) |
pages_init.json |
页面注册清单(HBuilderX 3.5+ 导入插件时自动弹窗合并到项目 pages.json) |
docs/lord-aliyun-player-integration-guide.md |
初学者集成指南(含服务端 Node.js/Java 实现示例、上线 Checklist) |
运行步骤:
- 通过 HBuilderX 导入插件时,根据
pages_init.json弹窗确认即可自动注册 Demo 路由; 若未弹窗(或手动复制的插件),在项目pages.json手动添加:
{
"path": "uni_modules/lord-aliyun-player/pages/demo/index",
"style": { "navigationBarTitleText": "阿里云播放器Demo" }
}
- 制作自定义调试基座并真机运行(原生插件不在标准基座内);
- 任意入口跳转:
uni.navigateTo({ url: '/uni_modules/lord-aliyun-player/pages/demo/index' })。
Demo 默认 USE_MOCK = true(数据来自 demo-data.json),无需服务端即可跑通;
接入自己服务端后将 api.js 中开关改为 false 并替换 BASE_URL。
Demo 不依赖宿主项目任何文件,可随插件分发直接使用。
进阶用法
熄屏/锁屏播放
// 开始播放后调用,申请保活锁
this.$refs.player.enableKeepPlayingOnScreenOff()
// 暂停 / 完成 / 出错时释放
this.$refs.player.disableKeepPlayingOnScreenOff()
组件内已在
play()时自动调用enableKeepPlayingOnScreenOff,在播放完成/出错时自动释放,通常无需手动调用。
纯音频模式(听视频)
// 开启纯音频模式(仅播放音频不渲染画面)
this.$refs.player.setAudioOnlyMode(true)
// 关闭纯音频模式
this.$refs.player.setAudioOnlyMode(false)
监听纯音频模式变化:
<ali-player-view @audioonlychange="onAudioOnlyChange" />
<script>
methods: {
onAudioOnlyChange(e) {
console.log('纯音频模式:', e.isAudioOnly ? '已开启' : '已关闭')
}
}
</script>
小窗播放(统一入口)
系统要求:Android 8.0+(API 26)/ iOS 15+。 Android 为腾讯视频式分层浮窗(已授悬浮窗权限时系统画中画,未授权时应用内浮窗,App 不退后台),iOS 为系统画中画;离开 App 自动起窗双端体验一致,接入方无需处理悬浮窗权限编排。
// 进入小窗(返回 Boolean 表示是否成功)
const ok = this.$refs.player.enterSmallWindow()
// 退出小窗(自动识别当前小窗类型)
this.$refs.player.exitSmallWindow()
// 查询是否处于小窗
const inSmall = this.$refs.player.isInSmallWindow()
统一监听 smallwindowchange(跨平台一致,mode 区分底层实现):
<ali-player-view
ref="player"
@smallwindowchange="onSmallWindowChange"
/>
<script>
methods: {
onSmallWindowChange(e) {
// e.active === 1 表示已进入小窗(mode: 'pip'=系统画中画 / 'float'=应用内浮窗;iOS 恒为 'pip')
console.log('小窗状态:', e.active === 1 ? '已进入' : '已退出')
}
}
</script>
离开 App 自动进小窗(默认开启):
// 关闭“离开 App 自动进小窗”(默认开启)
this.$refs.player.setAutoSmallWindowOnLeave(false)
画中画旧 API:
enterPip()/exitPip()/isInPipMode()已标记@deprecated,仍可用但建议迁移到enterSmallWindow()系列。Android 如需指定宽高比可用enterPipWithRatio(w, h)。
后台播放与媒体通知栏(Android)
以下能力仅 Android 生效。iOS 后台音频由系统
UIBackgroundModes: audio+ AVAudioSession 自动承载(见「熄屏/锁屏播放」)。
默认行为(无需额外调用):App 退到后台时继续播放,并自动切为纯音频 + 显示媒体通知栏(锁屏 MediaSession 控制),回到前台自动恢复视频。可按需覆盖默认开关:
// 媒体通知栏 + 锁屏 MediaSession 控制开关(默认开启)
// 开启后进入小窗/后台且正在播放/暂停时显示通知栏(播放·暂停 / 快退 / 快进 / 关闭),关闭时立即移除
this.$refs.player.setMediaNotificationEnabled(true)
// App 退到后台是否继续播放(默认 true)
// 设为 false 恢复旧行为:退到后台自动暂停、回到前台自动恢复
this.$refs.player.setKeepPlayingInBackground(true)
// 后台自动切纯音频开关(腾讯视频式,默认开启)
// 正在播放视频时退到后台(非小窗)自动切纯音频并显示通知栏,回前台自动恢复视频
this.$refs.player.setBackgroundAudioEnabled(true)
需在
AndroidManifest.xml声明FOREGROUND_SERVICE、WAKE_LOCK等权限(见 Android 配置)。手势调音量自动取消静音会派发mutedchange事件;音频焦点变化(如来电、其他 App 抢占)会派发audiofocuschange事件。注:这两个事件本身是双端的(iOS 由 AVAudioSession 打断通知驱动),仅上述后台/通知栏开关 API 为 Android 专属。
投屏(Android DLNA / iOS AirPlay)
组件对外提供统一的投屏 API,底层按平台自动路由:
| 平台 | 投屏通道 | 设备发现 | URL 推送 | 说明 |
|---|---|---|---|---|
| Android | DLNA / UPnP | ✅ 应用内设备列表 | ✅ 推送播放 URL 到设备 | 走完整链路:搜索 → 选择 → 连接 → 投屏;仅 URL 播放源可投屏 |
| iOS | 系统 AirPlay | ❌ 由系统选择器负责 | ❌ 仅镜像/音频路由当前播放 | 由系统被动驱动,无法程序化搜索/断开;不受源模式限制 |
Android 投屏源限制: DLNA 需向电视下发可直接播放的媒体地址,因此仅 URL 播放源(http/https 直链) 支持投屏;投屏地址由组件自动取当前播放 URL,无需额外传入。VidAuth/VidSts 的真实播放地址由 AliPlayer SDK 内部解析、应用层无公开 API 获取,故不支持投屏;此时点击投屏按钮会提示“当前播放源不支持投屏”。iOS AirPlay 为屏幕镜像,不受此限制。
iOS 说明:阿里云
AVPPlayer不支持真正的 AirPlay 视频外部播放(自有渲染管线),音频跟随 AirPlay 路由、视频由系统镜像;实际投屏状态以系统路由检测为准,因此startDlnaCasting/stopDlnaCasting均只是调起系统 AirPlay 选择器,真实开始/断开由用户在选择器中操作、由路由回调更新状态。
基本用法
// 打开投屏入口(Android 弹设备列表;iOS 弹系统 AirPlay 选择器)
this.$refs.player.showDlnaDeviceList()
// 查询是否正在投屏
const casting = this.$refs.player.isDlnaCasting()
// 投屏中的远端控制(AirPlay 场景映射为本地播放器操作)
this.$refs.player.pauseDlnaCasting()
this.$refs.player.resumeDlnaCasting()
this.$refs.player.seekDlnaCasting(60000) // 跳到 60s
this.$refs.player.setDlnaVolume(50) // 音量 0-100
投屏页(组件默认实现)
点击控制栏投屏按钮即打开原生全屏投屏页(零配置,右侧滑入):
- Android:设备搜索 / 设备列表 / “找不到投屏设备?”提示;已在投屏中时打开投屏控制页(遥控/切换/断开);
- iOS:AirPlay 引导 + “打开 AirPlay”按钮(调起系统选择器);已在投屏中时改弹“断开投屏”确认。
监听投屏状态与进度
推荐统一监听 castingstatechange(状态机驱动,跨平台语义一致),旧事件 castingstart/castingstop/castingerror 并行保留做兼容:
<ali-player-view
ref="player"
@castingstatechange="onCastingStateChange"
@castprogress="onCastProgress"
/>
<script>
methods: {
onCastingStateChange(e) {
// e.state 对应 CastState:0=Idle 4=Casting 5=Paused 6=Stopped -1=Error
console.log('投屏状态:', e.stateName, '设备:', e.deviceName)
if (e.state === -1) {
console.error('投屏出错:', e.code, e.message) // code 对应 CastingErrorCode
}
},
onCastProgress(e) {
// 投屏播放进度(毫秒)
console.log('投屏进度:', e.currentTime, '/', e.duration)
}
}
</script>
跨平台对齐说明(iOS ↔ Android)
castprogress进度回传:Android 由 DLNA 设备真实回传播放位置;iOS 因 AirPlay 镜像本地AVPPlayer,本地播放位置即投屏位置,故复用进度 Timer 在投屏中并行派发castprogress。两端事件负载{ currentTime, duration }一致。- 投屏日志桥接 JS 控制台:投屏关键日志会桥接到前端
console,便于排查。Android 前缀[DlnaCasting]、iOS 前缀[AirPlayCasting];带错误标签(Android[DLNA-ERROR]/ iOS[AIRPLAY-ERROR])的日志走console.error,其余走console.log。 - iOS AirPlay 自动重连(路由恢复):当用户经系统控制中心断开后再次接入同一 AirPlay 路由时,组件通过
AVAudioSession.routeChangeNotification检测到路由恢复,会自动将投屏会话从Error/Stopped状态转回Casting并重新派发castingstart/castingstatechange,无需应用层额外处理。
“更多”抽屉与 UI 定制
控制栏右上角“更多”按钮弹出底部抽屉,内置五个条目:分享、收藏、倍速播放、定时关闭、下载。
条目与顺序通过 moreActions 配置,主题色与全部文案均可定制,适配不同产品风格与多语言场景。
条目配置(moreActions)
<!-- 只保留倍速与定时关闭,隐藏分享/收藏/下载 -->
<ali-player-view :moreActions="['speed', 'timer']" />
<!-- 传空数组隐藏控制栏“更多”按钮 -->
<ali-player-view :moreActions="[]" />
条目行为分两类:
| 条目 | 点击行为 |
|---|---|
speed / timer / download |
原生自动处理(弹层/下载),同时派发 moreaction 事件供埋点 |
share / favorite |
仅派发 moreaction 事件,业务由调用者实现 |
<template>
<ali-player-view :favorited="isFav" @moreaction="onMoreAction" />
</template>
<script>
export default {
data() { return { isFav: false } },
methods: {
onMoreAction(e) {
const { action } = e.detail || e
if (action === 'favorite') {
// 调业务收藏接口,成功后回写 favorited 完成图标回显
this.isFav = !this.isFav
} else if (action === 'share') {
uni.share({ /* ... */ })
}
}
}
}
</script>
主题色(themeColor)
<ali-player-view themeColor="#FF6B00" />
一处配置全局生效:控制栏进度条、投屏/纯音频激活态、抽屉高亮、选集当前集高亮同源换色。
支持 #RRGGBB / #AARRGGBB,非法值忽略并保留默认蓝色(#00A8F6)。
文案定制(texts)
全部内置 UI 文案可通过 texts 覆盖(未覆盖项用默认中文),双端 key 同名同义,类型定义见 interface.uts 的 PlayerTextsConfig:
<ali-player-view :texts="{
share: 'Share',
favorite: 'Favorite',
favorited: 'Favorited',
speed: 'Speed',
sleepTimer: 'Sleep Timer',
download: 'Download',
cancel: 'Cancel',
loading: 'Loading...',
speedChangedToast: 'Switched to {rate}'
}" />
| key | 默认文案 | 说明 |
|---|---|---|
| share | 分享 | 抽屉条目 |
| favorite | 收藏 | 抽屉条目(未收藏态) |
| favorited | 已收藏 | 抽屉条目(已收藏态) |
| speed | 倍速播放 | 抽屉条目 |
| sleepTimer | 定时关闭 | 抽屉条目 |
| download | 下载 | 抽屉条目 |
| cancel | 取消 | 弹层通用按钮 |
| sleepTimerOff | 不开启 | 定时关闭弹层固定项 |
| sleepTimerCurrent | 播完当前 | 定时关闭弹层固定项 |
| speedTitle | 倍速播放 | 倍速弹层标题 |
| speedCustom | 自定义 | 倍速弹层自定义档位按钮 |
| speedCustomTitle | 自定义倍速 | 自定义滑杆标题 |
| speedCustomHint | 拖动滑块调节倍速 | 自定义滑杆提示 |
| episodeTitle | 选集 | 选集面板标题 |
| episodeCount | 共{count}集 | 选集面板副标题,{count}=总集数 |
| loading | 加载中... | 控制栏缓冲提示 |
| castSourceNotSupported | 当前视频源不支持投屏 | 轻提示 |
| sleepTimerCurrentToast | 将在播完当前视频后停止播放 | 轻提示 |
| sleepTimerCountdownToast | 将在 {minutes} 分钟后停止播放 | 轻提示,{minutes}=分钟数 |
| sleepTimerFiredToast | 定时关闭已生效,播放已停止 | 轻提示 |
| speedChangedToast | 已切换至 {rate} 倍速播放 | 轻提示,{rate}=倍速文本 |
| castSpeedSentToast | 已发送 {rate} 倍速,部分电视可能不支持变速 | 投屏倍速系统 Toast,{rate}=倍速文本 |
| castSpeedUnsupportedToast | 电视不支持该倍速 | 投屏设备拒绝该档位时的系统 Toast |
| downloadSourceNotSupported | 当前视频源不支持下载 | 轻提示 |
| downloadInProgress | 已有下载任务进行中 | 轻提示 |
| downloadStarted | 开始下载 | 轻提示 |
| downloadComplete | 下载完成 | 轻提示(未导出公共目录时兜底) |
| downloadEncrypted | 加密视频需先配置安全下载密钥 | 轻提示 |
| downloadFailed | 下载失败:{message} | 轻提示,{message}=失败原因 |
| downloadNotificationDownloading | 正在下载 | Android 下载进度通知状态文案(拼接百分比) |
| downloadCompleteSaved | 下载完成,已保存到手机「下载」目录 | 完成提示(Android 导出公共目录成功后;iOS 默认“可在「文件」App 本应用目录中查看”) |
占位符(
{count}/{minutes}/{rate}/{message})由原生侧运行时替换,覆盖文案时请保留占位符。
倍速播放
内置倍速弹层:预设档位宫格 + 自定义滑杆(0.5~4.0 无级调节),横屏竖屏均可用。
<!-- 自定义预设档位(顺序即宫格展示顺序) -->
<ali-player-view :speedPresets="[2.0, 1.5, 1.0, 0.5]" @ratechange="" />
// 也可不走弹层,直接设速 / 主动唤起弹层
this.$refs.player.setSpeed(1.5)
this.$refs.player.showSpeedSelectSheet()
(e) {
const { rate } = e.detail || e // 所有设速路径(弹层/滑杆/API)均派发
}
定时关闭
内置“定时关闭”弹层:不开启 / 播完当前 / 倒计时档位(默认 30/60 分钟,可配置)。
到点自动暂停播放并派发 sleeptimerfinish。
<!-- 自定义倒计时档位(“不开启/播完当前”固定项不受影响) -->
<ali-player-view :sleepTimerPresets="[15, 30, 60, 90]"
@sleeptimerchange="Change" @sleeptimerfinish="Finish" />
// 不走弹层,直接设置 / 主动唤起弹层
this.$refs.player.setSleepTimer('countdown', 30) // 30 分钟后停止
this.$refs.player.setSleepTimer('current', 0) // 播完当前停止
this.$refs.player.setSleepTimer('off', 0) // 取消
this.$refs.player.showSleepTimerSheet()
视频下载
抽屉“下载”条目点击后原生自动处理,无需 JS 层参与;也可通过组件方法在自定义 UI 中主动发起。
| 播放源 | 下载方式 | 保存位置 |
|---|---|---|
| VidSts / VidAuth | 阿里云 SDK 下载器(支持加密视频) | Android 应用专属目录 / iOS 沙盒 Documents |
| URL(http/https) | 插件自实现 HTTP 下载(直链流式;m3u8 逐分片合并为 .ts) | 同上 |
<ali-player-view ref="player"
@downloadprogress="" @downloadcomplete="onComplete" @downloaderror="onError" />
// 加密视频(vid 源):先配置密钥文件,全局一次即可
this.$refs.player.setSecureDownloadKeyFile('/data/user/0/xxx/files/encryptedApp.dat')
this.$refs.player.startDownload() // 开始下载当前视频
this.$refs.player.stopDownload() // 取消下载
const busy = this.$refs.player.isDownloading() // 查询下载中
(e) { const { percent } = e.detail || e } // 0-100
onComplete(e) { const { filePath } = e.detail || e } // 本地绝对路径
onError(e) { const { code, message } = e.detail || e } // 字符串错误码
限制:同一播放器同时仅支持一个下载任务;HLS 加密流(EXT-X-KEY)不支持下载; 直播流(RTMP/RTS)不支持下载。不支持时原生轻提示并派发
downloaderror。
截图
<ali-player-view ref="player" @snapshot="onSnapshot" />
<script>
methods: {
async takeSnapshot() {
// 触发截图,结果异步通过 snapshot 事件返回
this.$refs.player.snapshot()
},
onSnapshot(e) {
console.log('截图路径:', e.path)
uni.saveImageToPhotosAlbum({
filePath: e.path,
success: () => uni.showToast({ title: '截图已保存' })
})
}
}
</script>
直播播放
<template>
<!-- #ifdef APP-PLUS -->
<ali-player-view
ref="player"
src="rtmp://live.example.com/live/stream"
:autoplay="true"
@ready="onReady"
@error="onError"
/>
<!-- #endif -->
</template>
支持格式:RTMP、HLS (M3U8)、FLV、RTS 超低延时直播。
切换播放源
// 方式1:通过 setUrl 方法
this.$refs.player.setUrl('https://example.com/new-video.mp4')
this.$refs.player.prepare()
// 方式2:通过修改 src prop(响应式)
this.videoUrl = 'https://example.com/new-video.mp4'
获取播放信息
// 获取当前播放位置(毫秒)
this.$refs.player.getCurrentPosition((pos) => {
console.log('当前位置:', pos, 'ms')
})
// 获取视频总时长(毫秒)
this.$refs.player.getDuration((duration) => {
console.log('总时长:', duration, 'ms')
})
License 配置(SDK 7.0.0+)
⚠️ 自 7.0.0 版本起,阿里云播放器 SDK 在 Android 与 iOS 两端均需要有效的 License 才能使用,否则会报
LICENSE_ERROR_INVALID错误;且 7.6.0+ 版本必须同时配置 License 证书文件(仅配 LicenseKey 在弱网/无网环境下会鉴权失败)。
鉴权要素与双端存放规划
| 要素 | 作用 | Android 位置 | iOS 位置 |
|---|---|---|---|
| LicenseKey | SDK 启动时联网请求/刷新证书(必填) | AndroidManifest.xml → com.aliyun.alivc_license.licensekey |
Info.plist → AlivcLicenseKey |
| License 证书文件(.crt) | 弱网/离线时本地鉴权兜底(7.6.0+ 必填) | assets/cert/AliVideoCert.crt |
Resources/AliVideoCert.crt |
| 证书路径配置 | 告知 SDK 证书位置 | AndroidManifest.xml → com.aliyun.alivc_license.licensefile = assets/cert/AliVideoCert.crt |
Info.plist → AlivcLicenseFile = AliVideoCert.crt |
插件内的完整目录布局:
uni_modules/lord-aliyun-player/utssdk/
├── app-android/
│ ├── AndroidManifest.xml ← licensekey + licensefile 两条 meta-data
│ └── assets/
│ └── cert/
│ └── AliVideoCert.crt ← Android 证书(云打包合并到 APK assets/cert/)
└── app-ios/
├── Info.plist ← AlivcLicenseKey + AlivcLicenseFile(云打包合并进原生工程 Info.plist)
└── Resources/
└── AliVideoCert.crt ← iOS 证书(云打包合并进 App main bundle)
设计说明(企业级规范):
- 证书采用固定文件名
AliVideoCert.crt(而非阿里云下载时带日期戳的原始文件名),证书续期/权益变更时只需替换两端 .crt 文件本身,无需改动任何配置。- Android 证书独立存放在
assets/cert/子目录,与控制栏图标(image/)、字体(fonts/)隔离,路径写法对齐阿里云官方文档示例(assets/cert/xxx.crt)。- 同一张 License 同时绑定 Android PackageName 与 iOS BundleId,双端共用同一个 LicenseKey 与同一份证书文件。
1. 申请 License
前往阿里云控制台申请:接入 License
申请时需要填写 App 的 Android PackageName 和 iOS BundleId(即 uni-app 打包时使用的包名),License 与应用标识强绑定。申请成功后可获得 LicenseKey 与 *License 证书文件(AliVideoCert-.crt)**。
2. Android 端配置
① 放置证书:将下载的 .crt 重命名为 AliVideoCert.crt,放入:
utssdk/app-android/assets/cert/AliVideoCert.crt
HBuilderX 打包时会自动将 UTS 插件
utssdk/app-android/assets/下的文件(含子目录)合并到 APK 的assets/目录。
② 配置 meta-data:插件的 utssdk/app-android/AndroidManifest.xml 中已预置(<meta-data> 必须位于 <application> 节点内):
<meta-data
android:name="com.aliyun.alivc_license.licensekey"
android:value="你的LicenseKey" />
<meta-data
android:name="com.aliyun.alivc_license.licensefile"
android:value="assets/cert/AliVideoCert.crt" />
3. iOS 端配置
① 放置证书:将同一张证书(重命名为 AliVideoCert.crt)放入:
utssdk/app-ios/Resources/AliVideoCert.crt
按 UTS 插件规范,云打包时
Resources/下的文件会自动添加到应用 main bundle,无需手动操作 Xcode 工程。
② 配置 Info.plist:插件的 utssdk/app-ios/Info.plist 中已预置(云打包时自动合并进原生工程 Info.plist):
<key>AlivcLicenseKey</key>
<string>你的LicenseKey</string>
<key>AlivcLicenseFile</key>
<string>AliVideoCert.crt</string>
AlivcLicenseFile填相对 main bundle 的路径;证书在Resources/根目录时直接填文件名即可。
4. 证书续期 / 更换 License
| 场景 | 操作 |
|---|---|
| 证书续期、新开通增值服务(LicenseKey 不变) | 仅替换两端证书文件:app-android/assets/cert/AliVideoCert.crt 和 app-ios/Resources/AliVideoCert.crt,配置零改动 |
| 更换 License(如换包名/换主体,LicenseKey 变化) | 替换两端证书文件 + 同步修改 AndroidManifest.xml 的 licensekey 和 Info.plist 的 AlivcLicenseKey |
修改后需重新制作自定义基座才能生效。
5. 验证与排查
- 鉴权失败时播放器会派发
@error事件(License 相关错误码LICENSE_ERROR_*),可据此快速定位。 - Android 检查要点:
<meta-data>是否在<application>内、LicenseKey 与控制台一致、打包包名与申请时填写的 PackageName 一致。 - iOS 检查要点:
AlivcLicenseKey与控制台一致、BundleId 与申请时填写一致、证书已随包进入 main bundle。 - 更多排查见:License 相关常见问题。
常见问题
Q1:为什么在 HBuilderX 标准基座上运行没有效果 / 报「插件不存在」?
原生插件必须使用自定义调试基座或正式包,请在 HBuilderX 中选择「运行 → 运行到手机或模拟器 → 制作自定义调试基座」完成打包后再运行。
Q2:Android 模拟器无法播放视频?
阿里云播放器 Android SDK 不支持模拟器,请使用真机调试。
Q3:iOS 播放 HTTP 地址报网络错误?
在 manifest.json → App 原生配置 → iOS Info.plist 配置 中添加 NSAllowsArbitraryLoads: true,或将视频地址改为 HTTPS。
Q4:切换播放源(换 URL)不生效?
需先调用 stop(),再通过 setUrl() 设置新地址并 prepare()(setAutoPlay(true) 可在换源后自动起播):
this.$refs.player.stop()
this.$refs.player.setUrl('https://new-url.mp4')
this.$refs.player.setAutoPlay(true) // 可选:换源后自动起播
this.$refs.player.prepare()
Q5:如何监听播放进度?
通过 @timeupdate 事件,e.currentTime 即为当前播放位置(毫秒):
onTimeUpdate(e) {
console.log('播放进度:', e.currentTime, '/', e.duration)
}
Q6:VidAuth 播放凭证过期怎么处理?
监听 @error 事件,判断错误码为凭证过期后,重新向服务端换取 PlayAuth,再更新 playAuth prop 或调用 prepare()。
Q7:PiP 进入后视频停止了怎么办?
检查 AndroidManifest 的主 Activity 是否有 android:supportsPictureInPicture="true" 和 android:configChanges 属性。
Q8:熄屏后音频也停了?
调用 enableKeepPlayingOnScreenOff() 后,播放器会自动申请 WakeLock 保活。如仍不生效,检查是否在播放完成/出错后未重新启用。
Q9:报 LICENSE_ERROR_INVALID 或提示 License 鉴权失败?
按 License 配置 逐项检查:两端 LicenseKey 是否与控制台一致、打包包名(PackageName/BundleId)是否与申请 License 时填写的一致、证书文件是否已按规划路径放置(Android assets/cert/AliVideoCert.crt、iOS Resources/AliVideoCert.crt)、证书是否已过期。注意:修改 License 配置后必须重新制作自定义基座。
更新日志
完整版本更新记录请查看 changelog.md。
版本:v5.1.0 | 基于阿里云 ApsaraVideo Player SDK(Android / iOS)| 最低 HBuilderX:3.99

收藏人数:
购买普通授权版(
试用
赞赏(0)
下载 0
赞赏 0
下载 12550864
赞赏 1948
赞赏
京公网安备:11010802035340号