更新记录
1.0.0(2026-10-30)
- VLC 视频播放器组件(Android / uvue,uni-app x 标准模式,支持蒸汽模式)
- 支持网络流(rtsp / rtmp / http-flv / hls)、本地文件、assets 资源播放
- 提供 play / playUrl / pause / resume / stop / setVolume / setTime / setRate / setVideoScale / getPlayerData / isPlaying / takeSnapShot / startRecording / stopRecording / changeScreenDirection / checkMediaValid / checkPermissions / requestPermissions / release / setConfig 等方法,并支持 success / fail 回调
- 提供 onPlayStatus / onError / onResult 事件
- 提供 url / sourceType / autoPlay / scaleType / useSurfaceView / fullScreenIsLandscape / decoderEnabled / decoderForce / startTime / imageDir / videoDir 等组件属性,url 变化自动重新播放
- 画面比例支持 SURFACE_BEST_FIT / SURFACE_FIT_SCREEN / SURFACE_FILL / SURFACE_16_9 / SURFACE_4_3 / SURFACE_ORIGINAL,旋转、全屏进出与布局变化时自动重新布局画面
- 支持全屏切换(可配置全屏强制横屏)、全屏底部操作条显隐与自动收起
平台兼容性
uni-app x(4.27)
| Chrome | Safari | Android | Android插件版本 | iOS | 鸿蒙 | 微信小程序 |
|---|---|---|---|---|---|---|
| - | - | 5.0 | 1.0.0 | - | - | - |
其他
| 多语言 | 暗黑模式 | 宽屏模式 | 蒸汽模式 |
|---|---|---|---|
| × | × | √ | √ |
zy-vlc-play-x
基于VLC的 uni-app x 标准模式视频播放器组件,支持网络流(rtsp / rtmp / http-flv / hls)、本地文件、assets 资源,延迟低,提供播放控制、倍速、音量、进度、画面比例、截图、录制、全屏切换和播放源有效性检测。
平台支持
- uni-app x(app-android / uvue 页面)
- 组件只能在 uni-app x 页面中使用,支持蒸汽(Vapor)模式
- 需自定义基座或云打包验证制作自定义基座,标准基座不包含该库。
权限
android.permission.INTERNET
android.permission.ACCESS_NETWORK_STATE
android.permission.READ_EXTERNAL_STORAGE
android.permission.WRITE_EXTERNAL_STORAGE
截图、录像默认保存到应用外部私有目录(
getExternalFilesDir()/zyVlcPlay/pictures|videos),不需要存储权限;只有显式指定imageDir/videoDir到公共目录时才需要存储权限。
插件 config.json / AndroidManifest.xml 已声明:
android.permission.INTERNET // 安装时权限,网络播放自动授予,无需申请
android.permission.ACCESS_NETWORK_STATE // 安装时权限
android.permission.READ_EXTERNAL_STORAGE // Android 6+ 危险权限,maxSdkVersion=32,按需申请
android.permission.WRITE_EXTERNAL_STORAGE// Android 6+ 危险权限,maxSdkVersion=29,按需申请
- 默认播放网络流、播放应用私有目录文件、默认目录(
Android/data/<包名>/files/zyVlcPlay/...)截图录像,都不需要运行时权限。 - 只有把
imageDir/videoDir指到公共目录(如/storage/emulated/0/Pictures/...)时才需要存储权限;Android 13+ 这两个权限已失效,建议改用MediaStore或应用私有目录。 checkPermissions/requestPermissions不传permissions时按 targetSdkVersion 自动选择:<=29申请读写存储、30~32只申请读、>=33不申请(直接返回已授予)。注意 targetSdk ≥ 33 时显式传READ_EXTERNAL_STORAGE会被系统框架拒绝(IllegalArgumentException),此时应改用READ_MEDIA_IMAGES/READ_MEDIA_VIDEO或继续使用应用私有目录。- 需要时用组件方法申请,结果走
onResult事件或success/fail回调:
// 检查(不传则默认检查存储权限)
playerRef.value?.checkPermissions()
// 申请(权限结果回调由框架托管,插件不接管 onRequestPermissionsResult)
playerRef.value?.requestPermissions({ permissions: ['android.permission.READ_EXTERNAL_STORAGE'] })
function onResult(action: string, code: number, msg: string, data: UTSJSONObject) {
if (action == 'requestPermissions') {
const granted = data['granted'] as boolean
if (!granted) {
// data['deniedPermissions'] 为被拒项;data['doNotAskAgain'] 为 true 时需引导去系统设置
}
}
}
基础用法
<template>
<view style="flex: 1;">
<zy-vlc-play-x ref="playerRef" :url="url" :autoPlay="true" :scaleType="scaleType"
style="flex: 1; height: 400rpx;"
@load="onload" @onPlayStatus="onPlayStatus" @onError="onError" @onResult="onResult"></zy-vlc-play-x>
</view>
</template>
<script setup lang="uts">
import { ref } from 'vue'
const playerRef = ref<any | null>(null)
const url = ref<string>('https://example.com/demo.mp4')
const scaleType = ref<string>('SURFACE_BEST_FIT')
function onload() {
console.log('组件已就绪')
}
function onPlayStatus(data: UTSJSONObject) {
console.log('播放状态', data['status'], data['time'], data['length'])
}
function onError(data: UTSJSONObject) {
console.log('播放器错误', data['code'], data['msg'])
}
function onResult(action: string, code: number, msg: string, data: UTSJSONObject) {
console.log('方法结果', action, code, msg, data)
}
</script>
调用组件方法:
playerRef.value?.playUrl('rtsp://127.0.0.1/live/test')
playerRef.value?.pause()
playerRef.value?.setVideoScale('SURFACE_16_9')
配置项(props / setConfig 参数 / play 参数)
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| url | string | '' |
播放地址(本地路径、网络地址、assets 内的相对路径);props 中赋值后按 autoPlay 自动播放,运行中变化会重新播放 |
| autoPlay | boolean | true |
url 赋值后是否自动播放(对应 isAutoPlay) |
| sourceType | string | URL |
URL(默认)/ PATH(本地绝对路径)/ ASSETS(assets 内文件) |
| options | string[] | — | LibVLC 实例参数,如 ['--network-caching=300'](仅方法入参) |
| mediaOptions | string[] | — | Media 参数(media.addOption,仅方法入参) |
| decoderEnabled | boolean | true |
是否启用硬解码(setHWDecoderEnabled) |
| decoderForce | boolean | false |
是否强制硬解码 |
| time / startTime | number | 0 |
起播/续播位置,毫秒(props 中为 startTime,方法入参为 time) |
| scaleType | string | SURFACE_BEST_FIT |
画面比例,props 中变化即时生效 |
| useSurfaceView | boolean | false |
是否使用 SurfaceView,默认 false(TextureView,支持截图/动画) |
| fullScreenIsLandscape | boolean | false |
全屏时是否强制横屏 |
| imageDir | string | '' |
截图保存目录,需以 / 结尾(不传写入应用私有目录) |
| videoDir | string | '' |
录像保存目录,需以 / 结尾(不传写入应用私有目录) |
scaleType 取值:SURFACE_BEST_FIT(默认,等比适应)、SURFACE_FIT_SCREEN(等比撑满并缩放)、SURFACE_FILL(拉伸铺满)、SURFACE_16_9、SURFACE_4_3、SURFACE_ORIGINAL(原始尺寸)。
方法
所有方法都是异步的,结果统一通过 onResult 事件回传,同时支持入参的 success / fail 回调:
// 事件形式
function onResult(action: string, code: number, msg: string, data: UTSJSONObject) {}
// 回调形式
playerRef.value?.getPlayerData({
success: (res) => { console.log(res.data) },
fail: (err) => { console.error(err.code, err.message) }
})
code == 0 表示成功,其余为失败。
| 方法 | 参数 | 说明 | 成功时 data |
|---|---|---|---|
| setConfig | { url, sourceType?, options?, mediaOptions?, decoderEnabled?, decoderForce?, time?, scaleType?, isAutoPlay?, useSurfaceView?, fullScreenIsLandscape?, imageDir?, videoDir? } |
应用配置(带 url 且 isAutoPlay 不为 false 时自动播放) |
— |
| play | 同上 | 播放(重新创建 LibVLC 实例) | — |
| playUrl | url: string |
只用地址播放(不依赖对象桥接) | — |
| pause | — | 暂停 | — |
| resume | — | 继续播放 | — |
| stop | — | 停止播放 | — |
| setVolume | volume: number |
音量 0-100 | — |
| setTime | time: number |
跳转到指定位置(毫秒,超出时长自动截断) | — |
| setRate | rate: number |
播放倍速,如 0.5 / 1 / 2 | — |
| setVideoScale | scaleType: string |
设置画面比例 | — |
| getPlayerData | — | 获取播放属性 | { url, scaleType, isPlaying, vlcVersion, volume, length, time, width, height } |
| isPlaying | — | 是否正在播放 | { isPlaying } |
| takeSnapShot | — | 截图 | { path } |
| startRecording | — | 开始录制(写入 videoDir) | — |
| stopRecording | — | 结束录制 | { path } |
| changeScreenDirection | — | 全屏/退出全屏切换 | — |
| checkMediaValid | url: string |
检测播放源是否可用(最大等待 3 秒) | { isValid } |
| checkPermissions | { permissions?: string[] } |
检查运行时权限,不传时按 targetSdkVersion 自动选择 | { granted, deniedPermissions } |
| requestPermissions | { permissions?: string[] } |
申请运行时权限(弹系统对话框;结果回调由框架托管),不传时按 targetSdkVersion 自动选择 | { granted, deniedPermissions, doNotAskAgain } |
| release | — | 释放播放器资源(组件仍可继续 play) | — |
checkMediaValid 播放源无效时 code = -103;其余失败 code = -1,具体原因见 msg。
事件
| 事件 | 参数 | 说明 |
|---|---|---|
| load | — | 原生视图就绪 |
| onPlayStatus | { status, length, time } |
播放器状态回调,status 取值:Opening、Buffering、Playing、Paused、Stopped、EndReached、EncounteredError、TimeChanged、LengthChanged、PositionChanged、SeekableChanged、PausableChanged、MediaChanged、Vout、ESAdded、ESDeleted、ESSelected、RecordChanged |
| onError | { code, msg } |
播放器内部错误 |
| onResult | (action, code, msg, data) |
方法调用结果 |
onPlayStatus 频率(必读)
TimeChanged / PositionChanged 触发频率很高(每秒多次),用它们更新进度即可,不要在里面写日志或做重计算。
function onPlayStatus(data: UTSJSONObject) {
const status = data['status'] as string
if (status == 'TimeChanged' || status == 'PositionChanged') return
console.log('播放状态', status)
}

收藏人数:
购买源码授权版(
试用
使用 HBuilder 导入示例项目
赞赏(0)
下载 62
赞赏 0
下载 12729937
赞赏 1959
赞赏
京公网安备:11010802035340号