更新记录
1.1.0(2026-05-25) 下载此版本
CHANGELOG
All notable changes to the ali-player (阿里云播放器SDK) uni-app 原生插件 will be documented in this file.
[1.1.0] - 2026-05-25
新增(Features)
-
PiP 画中画(Picture-in-Picture)
- Android:
Activity.enterPictureInPictureMode()+ PiP 状态回调 - iOS:
AVPictureInPictureController+ AVPlayerLayer 自动检测 - JS 接口:
enterPip()/exitPip()/isInPipMode() - Vue 事件:
@pipStateChanged
- Android:
-
熄屏/锁屏保活播放
- Android:
PARTIAL_WAKE_LOCK+AudioFocus管理 - iOS:
AVAudioSession(.playback)+setActive(true) - JS 接口:
enableKeepPlayingOnScreenOff()/disableKeepPlayingOnScreenOff() - Vue 事件:
@audioFocusChanged
- Android:
-
Registry 扩展: 新增
componentRegistry,支持 Module 跨组件调用 PiP/熄屏方法
改进(Changes)
| 文件 | 变更 |
|---|---|
android/.../AliPlayerComponent.java |
重写:Lambda 化 + PiP/熄屏实现 |
android/.../AliPlayerModule.java |
新增 5 个 @UniJSMethod |
android/.../AliPlayerRegistry.java |
重写:新增 componentRegistry |
ios/.../AliPlayerComponent.{h,m} |
新增 PiP 属性/方法/Delegate |
ios/.../AliPlayerModule.m |
新增 PiP/熄屏方法 + 修复 stateToName |
ios/.../AliPlayerRegistry.{h,m} |
新增 components 字典 + componentForId |
js/uni.ali-player.js |
新增 5 个 JS 方法 |
components/ali-player/ali-player.vue |
新增 pipStateChanged/audioFocusChanged 事件转发 |
package.json |
补全元数据(version/dcloudext/declaration/platforms) |
README.md |
按插件市场标准全面重写 |
修复(Fixes)
- 修复 AliPlayerModule.m 中
stateToName:方法定义缺失的回归问题 - 清理 ali-player.vue onInfo 中的进度日志输出
平台配置要求(用户需手动操作)
| 平台 | 配置项 |
|---|---|
| Android | manifest.json 添加 androidManifest.activities[0].supportsPictureInPicture=true + configChanges |
| iOS | Xcode → Signing & Capabilities → Background Modes → Audio, AirPlay, and Picture in Picture |
[1.0.0] - 初始版本
新增
- 基于 阿里云 ApsaraVideo Player SDK 7.14.0 封装,支持 iOS / Android 双端
- 三种播放方式: VidAuth / VidSts / URL
- 核心能力:
- 点播 / 直播 / 列表播放
- 播放控制(播放/暂停/停止/Seek/重播)
- 本地缓存管理
- 画质切换(清晰度列表 + 切换)
- 截图功能
- 音量/亮度/倍速调节
- 全屏切换
- Vue 组件化封装 (
<ali-player>) + Module 调用方式 (uni.requireNativePlugin)
平台兼容性
uni-app(3.7.7)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|
| - | - | - | - | - | - | - | - | - |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| - | - | - | - | - | - | - | - | - | - | - | - |
阿里云播放器 SDK for uni-app
uni-app 版 ApsaraVideo Player SDK
对齐阿里云官方 Android / iOS / Flutter SDK 交付规范,完整封装播放器能力。
仅支持 App 端(Android / iOS),H5/小程序请使用官方 Web 版 SDK。
目录
功能概览
| 功能类别 | 支持能力 |
|---|---|
| 播放方式 | URL 直播/点播、VidAuth(推荐)、VidSts |
| 视频格式 | MP4、HLS (M3U8)、FLV、RTMP、RTS 超低延时直播 |
| 播放控制 | 播放/暂停/停止/Seek/重加载/续播 |
| 画面控制 | 缩放模式、旋转、镜像 |
| 音频控制 | 音量、静音 |
| 画中画(PiP) | Android 8.0+、iOS 15+ 系统级 PiP |
| 熄屏/锁屏播放 | Android WakeLock + AudioFocus;iOS AVAudioSession |
| 性能 | 本地缓存(边播边缓存)、网络自适应码率(HLS ABR) |
| 安全 | HLS AES-128 加密、阿里云私有加密 |
| 多实例 | 支持页面内同时创建多个播放器 |
| 列表播放 | 短视频列表预加载(AliListPlayer) |
| 截图 | 截取当前帧并返回本地文件路径 |
| 质量监控 | 播放日志上报(需阿里云账号) |
平台支持
| 平台 | 支持 | 最低版本 |
|---|---|---|
| Android | ✅ | minSdkVersion 21(Android 5.0) |
| iOS | ✅ | iOS 12.0+ |
| H5 | ❌ | 请使用 Aliplayer Web SDK |
| 微信小程序 | ❌ | — |
| HarmonyOS | ❌ | — |
本插件通过
// #ifdef APP-PLUS条件编译自动屏蔽非 App 端,不影响其他平台构建。
安装方式
方式一:从 uni-app 插件市场安装(推荐)
- 前往 DCloud 插件市场 搜索「阿里云播放器SDK」
- 点击「使用 HBuilderX 导入插件」,自动复制到项目
uni_modules/ali-player/ - 完成 集成配置 后制作自定义基座
方式二:手动拷贝
将 uni_modules/ali-player/ 整个目录拷贝到目标项目的 uni_modules/ 下,目录结构如下:
uni_modules/
└── ali-player/
├── android/ # Android 原生插件源码
│ ├── build.gradle
│ ├── dcloud_uniplugins.json # 插件注册声明
│ └── src/main/java/com/aliyun/player/uniapp/
│ ├── AliPlayerModule.java # Module(供 JS 调用)
│ ├── AliPlayerComponent.java # Component(播放器渲染视图)
│ └── AliPlayerRegistry.java # 多实例注册表
├── ios/ # iOS 原生插件源码
│ ├── Classes/
│ │ ├── AliPlayerModule.h/.m # Module
│ │ ├── AliPlayerComponent.h/.m # Component
│ │ └── AliPlayerRegistry.h/.m # 多实例注册表
│ ├── ali-player.podspec
│ └── dcloud_uniplugins.json
├── components/
│ └── ali-player/
│ └── ali-player.vue # Vue 组件(视图层桥接)
├── js/
│ └── uni.ali-player.js # JS SDK 核心(工厂/实例/常量)
└── package.json
集成配置
⚠️ 原生插件必须通过「自定义基座」或「正式打包」才能运行,不支持标准基座。
Android 配置
1. build.gradle 添加依赖
在项目 android/app/build.gradle 中添加:
repositories {
// 阿里云 Maven 仓库
maven { url "https://maven.aliyun.com/nexus/content/repositories/releases" }
}
android {
defaultConfig {
minSdkVersion 21
}
}
dependencies {
// 完整版(含软解码),体积约 25MB;lite 版约 9MB(仅硬解码)
implementation 'com.aliyun.sdk.android:AliyunPlayer:7.14.0-full'
// 可选:RTS 超低延时直播
// implementation 'com.aliyun.rts.android:RtsSDK:2.x.x'
// implementation 'com.aliyun.sdk.android:AlivcArtc:7.14.0'
}
2. 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" />
3. 开启 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" />
HBuilderX 3.x 的主 Activity 名称通常为
io.dcloud.PandoraEntry,请以实际生成的 AndroidManifest 为准。
iOS 配置
1. Podfile 添加依赖
target 'HBuilder' do
pod 'AliPlayerSDK_iOS', '7.14.0'
# 可选:RTS 超低延时直播
# pod 'AliPlayerSDK_iOS_ARTC', '7.14.0'
# pod 'RtsSDK', '2.x.x'
end
执行 pod install。
2. Info.plist 配置
<!-- 允许 HTTP(如视频地址是 HTTP) -->
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<!-- 熄屏/锁屏后台播放 + PiP(画中画)必须添加) -->
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
</array>
3. Xcode 开启 Background Modes
- 在 Xcode 中打开项目 → 选择 Target → Signing & Capabilities
- 点击「+ Capability」→ 添加 Background Modes
- 勾选 ☑ Audio, AirPlay, and Picture in Picture
不开启此项,iOS 熄屏后播放会被系统中止,PiP 也无法进入后台浮窗。
快速开始
基础播放示例
<template>
<view class="container">
<!-- 播放器视图组件(仅 APP 端渲染) -->
<!-- #ifdef APP-PLUS -->
<ali-player
ref="aliPlayer"
player-id="main-player"
:width="750"
:height="422"
@prepared="onPrepared"
@info="onInfo"
@completion="onCompletion"
@error="onError"
/>
<!-- #endif -->
<!-- 控制栏 -->
<view class="controls">
<button @tap="togglePlay">{{ isPlaying ? '暂停' : '播放' }}</button>
<slider
:value="currentPosition"
:max="duration"
@change="onSliderChange"
/>
<text>{{ formatTime(currentPosition) }} / {{ formatTime(duration) }}</text>
</view>
</view>
</template>
<script>
// #ifdef APP-PLUS
import { AliPlayerFactory, SeekMode } from '@/uni_modules/ali-player/js/uni.ali-player.js'
// #endif
export default {
data() {
return {
player: null,
isPlaying: false,
currentPosition: 0,
duration: 0
}
},
onLoad() {
// #ifdef APP-PLUS
this.initPlayer()
// #endif
},
onUnload() {
// 页面销毁时必须释放播放器,否则原生资源会泄漏
if (this.player) {
this.player.release()
}
},
methods: {
async initPlayer() {
// 1. 创建播放器实例(playerId 需与 <ali-player> 的 player-id 一致)
this.player = AliPlayerFactory.createAliPlayer('main-player')
// 2. 可选:配置缓冲参数
await this.player.setConfig({
startBufferDuration: 500,
highBufferDuration: 3000,
maxBufferDuration: 50000,
networkTimeout: 15000,
networkRetryCount: 3
})
// 3. 设置自动播放
await this.player.setAutoPlay(true)
// 4. 设置播放源(三选一)
// 方式 A:URL 直接播放
await this.player.setUrl('https://example.com/video.mp4')
// 方式 B:VidAuth 播放(推荐生产环境,凭证有效期约 100s)
// await this.player.setVidAuth({
// vid: 'your-video-id',
// playAuth: 'your-play-auth-token',
// region: 'cn-shanghai'
// })
// 方式 C:VidSts 播放
// await this.player.setVidSts({
// vid: 'your-video-id',
// region: 'cn-shanghai',
// accessKeyId: 'STS_KEY_ID',
// accessKeySecret: 'STS_KEY_SECRET',
// securityToken: 'STS_TOKEN'
// })
// 5. 开始准备
await this.player.prepare()
},
async onPrepared() {
// 准备完成后获取媒体信息
const info = await this.player.getMediaInfo()
this.duration = info.duration
console.log('时长:', info.duration, '轨道:', info.tracks)
},
onInfo(detail) {
// infoCode === 0:当前播放位置(ms)
if (detail.infoCode === 0) {
this.currentPosition = detail.extraValue
}
},
onCompletion() {
this.isPlaying = false
},
onError(detail) {
uni.showToast({ title: '播放失败: ' + detail.errorMsg, icon: 'none' })
},
async togglePlay() {
if (this.isPlaying) {
await this.player.pause()
} else {
await this.player.play()
}
this.isPlaying = !this.isPlaying
},
async onSliderChange(e) {
await this.player.seekTo(e.detail.value, SeekMode.INACCURATE)
},
formatTime(ms) {
const s = Math.floor(ms / 1000)
const m = Math.floor(s / 60)
const ss = s % 60
return `${String(m).padStart(2, '0')}:${String(ss).padStart(2, '0')}`
}
}
}
</script>
<style>
.container { flex: 1; background-color: #000; }
.controls { padding: 20rpx; background-color: #fff; }
</style>
API 参考
AliPlayerFactory(工厂)
import { AliPlayerFactory } from '@/uni_modules/ali-player/js/uni.ali-player.js'
AliPlayerFactory.createAliPlayer([playerId])
创建普通播放器实例。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| playerId | string | 否 | 播放器 ID,需与 <ali-player> 的 player-id 属性一致;不传则自动生成 UUID |
返回:AliPlayerInstance
AliPlayerFactory.createAliListPlayer([playerId])
创建列表播放器(适合短视频列表场景),拥有预加载、快速切换能力。
返回:AliListPlayerInstance
AliPlayerInstance(播放器实例)
播放源设置
| 方法 | 参数 | 说明 |
|---|---|---|
setUrl(url) |
url: string |
设置 URL 播放源(MP4/M3U8/FLV/RTMP 等) |
setVidAuth(options) |
见下表 | VidAuth 鉴权播放(推荐生产环境) |
setVidSts(options) |
见下表 | STS 临时凭证播放 |
setVidAuth options:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| vid | string | ✅ | 阿里云点播视频 ID |
| playAuth | string | ✅ | 播放凭证(服务端签发,有效期约 100s) |
| region | string | — | 接入区域,默认 cn-shanghai |
| definition | string | — | 指定清晰度:FD/LD/SD/HD/OD/2K/4K |
setVidSts options:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| vid | string | ✅ | 视频 ID |
| region | string | ✅ | 接入区域 |
| accessKeyId | string | ✅ | STS AccessKeyId |
| accessKeySecret | string | ✅ | STS AccessKeySecret |
| securityToken | string | ✅ | STS SecurityToken |
播放控制
| 方法 | 说明 | 返回 |
|---|---|---|
prepare() |
准备播放(设置播放源后调用) | Promise |
play() |
开始 / 恢复播放 | Promise |
pause() |
暂停(调用 play() 恢复) |
Promise |
stop() |
停止(需重新 prepare() 才可播放) |
Promise |
seekTo(position, seekMode?) |
Seek 到指定位置(毫秒) | Promise |
reload() |
重新加载当前播放源 | Promise |
release() |
销毁播放器,释放所有原生资源 | Promise |
seekTo 参数说明:
| 参数 | 类型 | 说明 |
|---|---|---|
| position | number | 目标时间(毫秒) |
| seekMode | SeekMode | ACCURATE(精准,较慢)/ INACCURATE(跳至关键帧,较快,默认) |
播放参数
| 方法 | 参数 | 说明 |
|---|---|---|
setAutoPlay(autoPlay) |
boolean | 是否自动播放(在 prepare() 前调用) |
setLoop(loop) |
boolean | 循环播放 |
setMute(mute) |
boolean | 静音 |
setVolume(volume) |
0.0 ~ 1.0 | 音量 |
setRate(rate) |
0.5 / 1.0 / 1.5 / 2.0 | 播放速率 |
setScalingMode(mode) |
ScalingMode | 缩放模式 |
setRotateMode(degree) |
RotateMode | 旋转角度 |
setMirrorMode(mode) |
MirrorMode | 镜像模式 |
播放器配置
// setConfig —— 需在 prepare() 前调用
await player.setConfig({
startBufferDuration: 500, // ms,起播缓冲
highBufferDuration: 3000, // ms,高水位缓冲
maxBufferDuration: 50000, // ms,最大缓冲
maxDelayTime: 5000, // ms,最大延迟(直播场景)
networkTimeout: 15000, // ms,网络超时
networkRetryCount: 3, // 网络重试次数
referrer: 'https://example.com',
httpProxy: 'http://proxy:8080',
enableSEI: false, // 是否启用 SEI
clearFrameWhenStop: true, // 停止后是否清空画面
disableVideo: false, // 纯音频时设为 true
disableAudio: false
})
// setCacheConfig —— 边播边缓存(需在 prepare() 前调用)
await player.setCacheConfig({
enable: true,
maxSizeMB: 200, // 最大缓存总容量(MB)
maxDurationS: 3600, // 单文件最大缓存时长(秒)
dir: '/path/to/cache'
})
播放状态查询
| 方法 | 返回 | 说明 |
|---|---|---|
getCurrentPosition() |
Promise<number> |
当前播放位置(ms) |
getDuration() |
Promise<number> |
视频总时长(ms) |
getPlayerState() |
Promise<{state, stateName}> |
当前播放器状态 |
getMediaInfo() |
Promise<MediaInfo> |
媒体信息(prepared 事件后可用) |
selectTrack(trackIndex) |
Promise |
切换清晰度轨道;-1 = 自动 ABR |
snapshot() |
Promise |
截图(结果通过 snapshot 事件返回) |
MediaInfo 结构:
{
title: string, // 视频标题
duration: number, // 总时长(ms)
coverUrl: string, // 封面地址
tracks: [{
trackIndex: number, // 轨道索引(用于 selectTrack)
trackType: string, // 'video' | 'audio'
trackBitrate: number,
videoWidth: number,
videoHeight: number,
definition: string // 'FD'|'LD'|'SD'|'HD'|'OD'|'2K'|'4K'
}]
}
AliListPlayerInstance(列表播放器)
继承 AliPlayerInstance 全部方法,额外提供:
| 方法 | 参数 | 说明 |
|---|---|---|
addUrlSource(url, uid) |
url: string, uid: string | 添加 URL 播放源 |
addVidSource(vid, uid) |
vid: string, uid: string | 添加 VID 播放源 |
removeSource(uid) |
uid: string | 移除指定播放源 |
setPreloadCount(count) |
count: number | 设置预加载数量(建议 2~3) |
moveTo(uid, stsInfo?) |
uid: string | 切换播放指定 UID 的视频 |
AliPlayer(全局静态方法)
import { AliPlayer } from '@/uni_modules/ali-player/js/uni.ali-player.js'
日志
| 方法 | 参数 | 说明 |
|---|---|---|
setLogLevel(level) |
'verbose'|'debug'|'info'|'warn'|'error'|'none' |
设置 SDK 日志等级 |
enableConsoleLog(enable) |
boolean | 开启 / 关闭控制台日志 |
画中画
| 方法 | 参数 | 说明 |
|---|---|---|
enterPip(playerId, videoWidth?, videoHeight?, callback?) |
— | 进入画中画(Android 8.0+、iOS 15+) |
exitPip(playerId, callback?) |
— | 退出画中画 |
isInPipMode(playerId, callback) |
callback: (result) => void |
查询是否处于画中画,result.inPip: boolean |
熄屏/锁屏播放
| 方法 | 参数 | 说明 |
|---|---|---|
enableKeepPlayingOnScreenOff(playerId, callback?) |
— | 启用熄屏保活(开始播放后调用) |
disableKeepPlayingOnScreenOff(playerId, callback?) |
— | 释放保活(暂停/完成/出错时调用) |
ali-player 组件
<ali-player
ref="aliPlayer"
player-id="main-player"
:width="750"
:height="422"
background-color="#000000"
@prepared="onPrepared"
@renderingStart="onRenderingStart"
@stateChanged="onStateChanged"
@info="onInfo"
@completion="onCompletion"
@error="onError"
@loadingBegin="onLoadingBegin"
@loadingProgress="onLoadingProgress"
@loadingEnd="onLoadingEnd"
@seekComplete="Complete"
@videoSizeChanged="onVideoSizeChanged"
@trackChanged="d"
@snapshot="onSnapshot"
@pipStateChanged="onPipStateChanged"
@audioFocusChanged="onAudioFocusChanged"
/>
Props:
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| player-id | string | 'default' |
播放器 ID,必须与 AliPlayerFactory.createAliPlayer 传入的 playerId 一致 |
| width | number / string | 750 |
宽度(rpx 或带单位字符串) |
| height | number / string | 422 |
高度 |
| background-color | string | '#000000' |
播放器背景色 |
常量
import {
PlayerState,
SeekMode,
ScalingMode,
RotateMode,
MirrorMode,
InfoCode
} from '@/uni_modules/ali-player/js/uni.ali-player.js'
// 播放器状态
PlayerState.IDLE // 'idle' — 空闲
PlayerState.INITIALIZED // 'initialized' — 已初始化
PlayerState.PREPARED // 'prepared' — 准备完成
PlayerState.STARTED // 'started' — 播放中
PlayerState.PAUSED // 'paused' — 已暂停
PlayerState.STOPPED // 'stopped' — 已停止
PlayerState.COMPLETION // 'completion' — 播放完成
PlayerState.ERROR // 'error' — 错误
// Seek 模式
SeekMode.ACCURATE // 精准 seek(帧级别,较慢)
SeekMode.INACCURATE // 非精准 seek,跳至最近关键帧(较快,推荐)
// 缩放模式
ScalingMode.SCALE_TO_FILL // 拉伸填充(会变形)
ScalingMode.ASPECT_FIT // 等比缩放,留黑边
ScalingMode.ASPECT_FILL // 等比缩放填满,裁剪超出部分
// 旋转角度
RotateMode.ROTATE_0 // 不旋转
RotateMode.ROTATE_90 // 顺时针 90°
RotateMode.ROTATE_180 // 顺时针 180°
RotateMode.ROTATE_270 // 顺时针 270°
// 镜像模式
MirrorMode.NONE // 不镜像
MirrorMode.HORIZONTAL // 水平镜像
MirrorMode.VERTICAL // 垂直镜像
// info 事件码(detail.infoCode)
InfoCode.CURRENT_POSITION // 0 — 当前播放位置(extraValue 单位 ms)
InfoCode.BUFFERED_POSITION // 1 — 缓冲位置
InfoCode.AUTO_PLAY_START // 2 — 自动播放开始
InfoCode.LOOPING_START // 3 — 循环播放重头开始
InfoCode.NETWORK_RETRY // 5 — 网络重试
InfoCode.NETWORK_BANDWIDTH // 6 — 当前网络带宽(extraValue 单位 bps)
事件参考
| 事件名 | detail 结构 | 说明 |
|---|---|---|
prepared |
{ playerId } |
准备完成,此时可调用 getMediaInfo() |
renderingStart |
{ playerId } |
首帧画面渲染,可在此隐藏封面图 |
stateChanged |
{ playerId, state, stateName } |
播放状态变化(见 PlayerState) |
videoSizeChanged |
{ playerId, width, height, rotation } |
视频分辨率或旋转角度变化 |
loadingBegin |
{ playerId } |
开始缓冲(转圈) |
loadingProgress |
{ playerId, percent, netSpeed } |
缓冲进度(0~100,netSpeed 单位 kbps) |
loadingEnd |
{ playerId } |
缓冲结束 |
seekComplete |
{ playerId } |
Seek 完成 |
info |
{ playerId, infoCode, infoCodeName, extraValue, extraMsg } |
播放器信息回调(进度/缓冲/带宽等) |
completion |
{ playerId } |
点播播放完成 |
error |
{ playerId, errorCode, errorMsg, errorExtra } |
播放错误 |
trackChanged |
{ playerId, success, trackIndex, trackType } |
清晰度切换结果 |
snapshot |
{ playerId, path } |
截图完成,path 为本地文件路径 |
pipStateChanged |
{ playerId, pipState, message } |
PiP 状态变化(见下方说明) |
audioFocusChanged |
{ playerId, focusChange } |
Android AudioFocus 变化(见下方说明) |
pipState 值说明:
| 值 | 说明 |
|---|---|
willEnter |
即将进入画中画 |
entered |
已进入画中画 |
willExit |
即将退出画中画 |
exited |
已退出画中画,回到 App |
restoring |
从 PiP 还原到全屏 |
error |
进入 PiP 失败 |
unsupported |
系统不支持 PiP(< Android 8.0 / < iOS 15) |
focusChange 值说明(Android):
| 值 | 说明 |
|---|---|
GAIN |
重新获得音频焦点(可继续播放) |
LOSS |
永久失去焦点(建议停止播放) |
LOSS_TRANSIENT |
临时失去焦点(建议暂停) |
LOSS_TRANSIENT_CAN_DUCK |
短暂被抢占(可降低音量继续) |
进阶用法
多实例播放
页面内同时渲染多个播放器,各自独立,通过不同的 playerId 区分:
<template>
<!-- #ifdef APP-PLUS -->
<ali-player player-id="player-1" :width="375" :height="211" @prepared="() => onReady(1)" />
<ali-player player-id="player-2" :width="375" :height="211" @prepared="() => onReady(2)" />
<!-- #endif -->
</template>
<script>
// #ifdef APP-PLUS
import { AliPlayerFactory } from '@/uni_modules/ali-player/js/uni.ali-player.js'
// #endif
export default {
onLoad() {
// #ifdef APP-PLUS
this.player1 = AliPlayerFactory.createAliPlayer('player-1')
this.player2 = AliPlayerFactory.createAliPlayer('player-2')
this.player1.setUrl('https://example.com/video1.mp4')
this.player1.prepare()
this.player2.setUrl('https://example.com/video2.mp4')
this.player2.prepare()
// #endif
},
onUnload() {
this.player1?.release()
this.player2?.release()
}
}
</script>
列表/短视频播放
// #ifdef APP-PLUS
import { AliPlayerFactory } from '@/uni_modules/ali-player/js/uni.ali-player.js'
const listPlayer = AliPlayerFactory.createAliListPlayer('list-player')
// 设置预加载(建议 2~3,过多消耗内存)
await listPlayer.setPreloadCount(3)
// 批量添加播放源
const videos = [
{ url: 'https://cdn.example.com/v1.mp4', uid: 'video_001' },
{ url: 'https://cdn.example.com/v2.mp4', uid: 'video_002' },
{ url: 'https://cdn.example.com/v3.mp4', uid: 'video_003' },
]
for (const v of videos) {
await listPlayer.addUrlSource(v.url, v.uid)
}
// 播放第一个
await listPlayer.moveTo('video_001')
// 滑动到下一个
await listPlayer.moveTo('video_002')
// #endif
直播播放
// RTMP
await player.setUrl('rtmp://live.example.com/live/stream')
// HLS
await player.setUrl('https://live.example.com/live/stream.m3u8')
// FLV
await player.setUrl('https://live.example.com/live/stream.flv')
// RTS 超低延时(需引入 RTS SDK)
await player.setUrl('artc://live.example.com/live/stream')
// 直播推荐配置(低延迟优先)
await player.setConfig({ maxDelayTime: 5000, maxBufferDuration: 5000 })
await player.prepare()
本地缓存下载
// 在 prepare() 前配置,首次播放后相同 URL 自动读本地缓存
const cacheDir = plus.io.convertLocalFileSystemURL('_doc/video_cache/')
await player.setCacheConfig({
enable: true,
maxSizeMB: 500, // 最大 500 MB
maxDurationS: 7200, // 单文件最大 2 小时
dir: cacheDir
})
await player.setUrl('https://example.com/video.mp4')
await player.prepare()
画质切换
async function onPrepared() {
const info = await player.getMediaInfo()
const tracks = info.tracks.filter(t => t.trackType === 'video')
console.log('可选清晰度:', tracks.map(t => t.definition))
// 切换到 HD
const hd = tracks.find(t => t.definition === 'HD')
if (hd) await player.selectTrack(hd.trackIndex)
// 开启自动码率(ABR)
// await player.selectTrack(-1)
}
// 切换结果在 trackChanged 事件中返回
截图
<ali-player player-id="main" @snapshot="onSnapshot" />
<script>
methods: {
async takeSnapshot() {
// 触发截图,结果异步通过 snapshot 事件返回
await this.player.snapshot()
},
onSnapshot(detail) {
console.log('截图路径:', detail.path)
uni.saveImageToPhotosAlbum({
filePath: detail.path,
success: () => uni.showToast({ title: '截图已保存' })
})
}
}
</script>
画中画(PiP)
系统要求:Android 8.0+(API 26)/ iOS 15+
必须完成 iOS Background Modes 配置,否则进入后台后 PiP 窗口会消失。
// #ifdef APP-PLUS
import { AliPlayer } from '@/uni_modules/ali-player/js/uni.ali-player.js'
// 进入画中画(视频宽高比 16:9)
AliPlayer.enterPip('main-player', 16, 9, (result) => {
if (result.code !== 0) {
console.error('进入 PiP 失败:', result.message)
}
})
// 退出画中画
AliPlayer.exitPip('main-player')
// 查询是否处于画中画模式
AliPlayer.isInPipMode('main-player', (result) => {
console.log('当前 PiP 状态:', result.inPip)
})
// #endif
监听 PiP 状态变化:
<ali-player
player-id="main-player"
@pipStateChanged="onPipStateChanged"
/>
<script>
methods: {
onPipStateChanged(detail) {
const { pipState, message } = detail
if (pipState === 'entered') {
// 已进入画中画,可隐藏自定义控制条
} else if (pipState === 'exited') {
// 已退出画中画,恢复 UI
} else if (pipState === 'error' || pipState === 'unsupported') {
uni.showToast({ title: message || '不支持画中画', icon: 'none' })
}
}
}
</script>
熄屏/锁屏播放
Android 需在
AndroidManifest.xml中声明WAKE_LOCK权限(见 集成配置)。
iOS 需在Info.plist中加UIBackgroundModes: audio,并在 Xcode 开启 Background Modes(见 iOS 配置)。
// #ifdef APP-PLUS
import { AliPlayer } from '@/uni_modules/ali-player/js/uni.ali-player.js'
// 开始播放后调用,申请保活锁
// Android: PARTIAL_WAKE_LOCK(CPU 保活,屏幕不亮)+ AudioFocus
// iOS: AVAudioSession category = .playback
AliPlayer.enableKeepPlayingOnScreenOff('main-player')
// 暂停 / 完成 / 出错时释放
AliPlayer.disableKeepPlayingOnScreenOff('main-player')
// #endif
💡 组件内已在
play()时自动调用enableKeepPlayingOnScreenOff,在onCompletion/onError时自动释放,通常无需手动调用。
License 配置(SDK 7.0.0+)
⚠️ 自 7.0.0 版本起,阿里云播放器 SDK 需要有效的 License 才能使用,否则会提示鉴权失败。
// 在 App.vue 的 onLaunch 中尽早配置
// #ifdef APP-PLUS
const aliModule = uni.requireNativePlugin('AliPlayer-AliPlayerModule')
if (aliModule && aliModule.setLicenseKey) {
aliModule.setLicenseKey({
licenseKey: 'YOUR_LICENSE_KEY',
licenseFile: 'alivc_license' // 证书文件名(Android,不含扩展名)
})
}
// #endif
申请 License:阿里云点播播放器 License 申请
常见问题
Q1:为什么在 HBuilderX 标准基座上运行没有效果 / 报「插件不存在」?
原生插件必须使用自定义调试基座或正式包,请在 HBuilderX 中选择「运行 → 运行到手机或模拟器 → 制作自定义调试基座」完成打包后再运行。
Q2:Android 模拟器无法播放视频?
阿里云播放器 Android SDK 不支持模拟器,请使用真机调试。
Q3:iOS 播放 HTTP 地址报网络错误?
在 Info.plist 中添加 NSAllowsArbitraryLoads: true,或将视频地址改为 HTTPS。
Q4:切换播放源(换 URL)不生效?
需先 stop(),再重新 setUrl() + prepare():
await player.stop()
await player.setUrl('https://new-url.mp4')
await player.prepare()
Q5:如何监听播放进度?
通过 info 事件,infoCode === 0 时 extraValue 即为当前播放位置(ms):
onInfo(detail) {
if (detail.infoCode === 0) {
this.currentPosition = detail.extraValue // ms
}
}
Q6:VidAuth 播放凭证过期怎么处理?
监听 error 事件,判断 errorCode 为凭证过期后,重新向服务端换取 PlayAuth,再调用 setVidAuth + prepare()。
Q7:多实例内存占用高怎么办?
- 不可见的播放器及时调用
pause()或stop() - 页面卸载时必须调用
release()释放原生资源 - 列表场景使用
AliListPlayerInstance配合setPreloadCount控制预加载数量(建议 ≤ 3)
Q8:PiP 进入后视频停止了怎么办?
- iOS:检查是否已在 Xcode 开启
Background Modes → Audio, AirPlay, and Picture in Picture,以及Info.plist是否有UIBackgroundModes: audio - Android:检查 AndroidManifest 的主 Activity 是否有
android:supportsPictureInPicture="true"
Q9:熄屏后音频也停了(iOS)?
检查 Info.plist 中是否有 UIBackgroundModes: audio,且 Xcode Background Modes 已勾选 Audio。
Q10:如何在页面隐藏(进后台)时不停止播放(Android)?
调用 enableKeepPlayingOnScreenOff 后,只要不调用 pause(),App 进后台时播放器会继续运行。如需后台通知栏控制,需配合前台 Service 实现,这不在本插件范围内。
更新日志
v1.1.0(2026-05-25)
新增功能:
- 🆕 画中画(PiP):Android 8.0+ 和 iOS 15+ 系统级 PiP 支持
AliPlayer.enterPip()/exitPip()/isInPipMode()- 组件新增
@pipStateChanged事件(willEnter / entered / willExit / exited / restoring / error / unsupported)
- 🆕 熄屏/锁屏播放:Android WakeLock + AudioFocus;iOS AVAudioSession
AliPlayer.enableKeepPlayingOnScreenOff()/disableKeepPlayingOnScreenOff()- 组件新增
@audioFocusChanged事件(Android AudioFocus 变化回调)
AliPlayerRegistry新增 Component 注册表,支持 Module 调用 Component 层方法
优化:
VideoPlayer.nvue自动在play()时申请保活锁,在onCompletion/onError时释放
v1.0.0(2026-05-20)
- 🎉 首次发布
- 支持 URL / VidAuth / VidSts 三种播放源
- 支持点播、直播、列表播放
- 支持截图、本地缓存、画质切换、续播
- 双端完整实现(Android Java + iOS Objective-C)
- JS 工厂模式(AliPlayerFactory),API 对齐阿里云 Flutter SDK 规范
版本:v1.1.0 | 对应阿里云播放器 SDK:7.14.0 | 最低 HBuilderX:3.0.0

收藏人数:
下载插件并导入HBuilderX
下载插件ZIP
赞赏(0)
下载 5
赞赏 0
下载 12031900
赞赏 1917
赞赏
京公网安备:11010802035340号