uni-app x live-player 组件完全指南:实时音视频拉流播放与 LivePlayerContext 控制
2026/9/19 20:39:32 网站建设 项目流程

uni-app x live-player 组件完全指南:实时音视频拉流播放与 LivePlayerContext 控制

【免费下载链接】uni-appA cross-platform framework using Vue.js项目地址: https://gitcode.com/gh_mirrors/un/uni-app

导读live-player是 uni-app x(uni-app 下一代跨平台框架)在 Android / iOS / 微信小程序等平台上提供的实时音视频拉流(播放)组件,与 DCloud 与七牛云合作的「uni直播」服务配套使用。本文将以 docs/component/live-player.md 为主线,完整覆盖该组件的全部属性、枚举值、事件对象、状态码与错误码,并结合 docs/api/create-live-player-context.md 与仓库内示例 src/pages/component/live-player/live-player.uvue 的源码实现,给出可直接复制运行的完整实战代码,帮助读者在 uni-app x 中快速接入 rtmp / hls 直播流并实现播放控制、全屏切换、静音等能力。

live-player 组件定位与使用前提

live-player组件是 uni直播服务(DCloud 与七牛云合作推出的直播服务,依托云边一体化架构和海量节点资源构建流媒体服务)中的拉流(播放)组件,用于在应用中实时播放音视频直播流。

需要注意两点使用前提:

  1. App 端申请绑定:在 Android / iOS 平台使用该组件,需要申请绑定包名 / Bundle ID(AppID),详情可咨询 DCloud 官方渠道。
  2. Web / HarmonyOS 暂不支持:根据组件兼容性表,live-player在 Web 端与 HarmonyOS 端均为不支持状态(兼容性表格中标记为x),微信小程序自4.41版本起支持,Android / iOS 自4.81版本起支持。

在仓库示例工程的页面注册文件 src/pages.json 中,可以看到该示例页面正是通过条件编译限定平台范围注册的:

// #ifdef APP-ANDROID || APP-IOS || MP-WEIXIN { "path": "pages/component/live-player/live-player", "group": "0,5,4", "style": { "navigationBarTitleText": "live-player | 实时音视频播放" } }, // #endif

这一注册方式与文档兼容性表完全一致:组件只在 App(Android / iOS)与微信小程序平台可用。

平台兼容性总览

| Web | 微信小程序 | Android | iOS | HarmonyOS | | :- | :- | :- | :- | :- | | x | 4.41 | 4.81 | 4.81 | x |

表格中的数字代表对应平台最低支持版本号,x表示不支持。

组件属性详解

live-player组件的核心属性如下表所示,其中兼容性列沿用文档原始标注(x表示不支持):

| 名称 | 类型 | 默认值 | 兼容性 | 描述 | | :- | :- | :- | :-: | :- | | src | string(string.VideoURIString) | | Web: x; 微信小程序: 4.41; Android: 4.81; iOS: 4.81 | 音视频地址。微信小程序支持 flv, rtmp 格式,app平台支持 rtmp, hls 协议 | | mode | string | | Web: x; 微信小程序: 4.41; Android: x; iOS: x | live(直播),RTC(实时通话) | | autoplay | boolean | false | Web: x; 微信小程序: 4.41; Android: 4.81; iOS: 4.81 | 自动播放 | | muted | boolean | false | Web: x; 微信小程序: 4.41; Android: 4.81; iOS: 4.81 | 是否静音 | | orientation | string | "vertical" | Web: x; 微信小程序: 4.41; Android: 4.81; iOS: 4.81 | 画面方向,可选值有 vertical,horizontal | | object-fit | string | "contain" | Web: x; 微信小程序: 4.41; Android: 4.81; iOS: 4.81 | 填充模式,可选值有 contain,fillCrop | | background-mute | boolean | false | Web: x; 微信小程序: 4.41; Android: 4.81; iOS: 4.81 | 进入后台时是否静音 | | min-cache | string | | Web: x; 微信小程序: 4.41; Android: x; iOS: x | 最小缓冲区,单位s | | max-cache | string | | Web: x; 微信小程序: 4.41; Android: x; iOS: x | 最大缓冲区,单位s | | sound-mode | string | | Web: x; 微信小程序: 4.41; Android: x; iOS: x; HarmonyOS: x | 声音输出方式 | | auto-pause-if-navigate | boolean | | Web: x; 微信小程序: 4.41; Android: x; iOS: x; HarmonyOS: x | 当跳转到本小程序的其他页面时,是否自动暂停本页面的实时音视频播放 | | auto-pause-if-open-native | boolean | | Web: x; 微信小程序: 4.41; Android: x; iOS: x; HarmonyOS: x | 当跳转到其它微信原生页面时,是否自动暂停本页面的实时音视频播放 | | picture-in-picture-mode | string/Array | | Web: x; 微信小程序: 4.41; Android: x; iOS: x; HarmonyOS: x | 设置小窗模式: push, pop,空字符串或通过数组形式设置多种模式(如: ["push", "pop"]) | | picture-in-picture-init-position | string | | Web: x; 微信小程序: 4.41; Android: x; iOS: x; HarmonyOS: x | 小窗模式下小窗的初始显示位置,格式为 (alignment, y),其中 alignment 表示小窗吸附屏幕左侧还是右侧,可选值为 left、right,y 代表小窗最顶部所在的屏幕高度百分比 | | enable-auto-rotation | boolean | | Web: x; 微信小程序: 4.41; Android: x; iOS: x; HarmonyOS: x | 是否开启手机横屏时自动全屏,当系统设置开启自动旋转时生效 | | referrer-policy | string | | Web: x; 微信小程序: 4.41; Android: x; iOS: x; HarmonyOS: x | 格式固定为https://servicewechat.com/{appid}/{version}/page-frame.html,其中 {appid} 为小程序的 appid,{version} 为小程序的版本号,版本号为 0 表示为开发版、体验版以及审核版本,版本号为 devtools 表示为开发者工具,其余为正式版本 | | enable-casting | boolean | | Web: x; 微信小程序: 4.41; Android: x; iOS: x; HarmonyOS: x | 是否支持投屏。开启后,可以通过 LivePlayerContext 上相关方法进行操作 | | duration | number | 0 | | | | initial-time | number | 0 | | | | loop | boolean | false | | | | codec | string | "auto" | | | | show-play-btn | boolean | true | | | | show-mute-btn | boolean | true | | | | show-fullscreen-btn | boolean | true | | | | show-progress | boolean | false | | | | enable-progress-gesture | boolean | true | | | | poster | string | "" | | | | controls | boolean | true | | | | show-center-play-btn | boolean | true | | | | show-loading | boolean | true | | |

属性使用要点

  • src是唯一必填的业务属性,直接决定播放哪个流地址。在仓库示例 src/pages/component/live-player/live-player.uvue 中通过:src="src"双向绑定到 ref 变量,用户可在输入框动态填入播放地址。
  • autoplaymutedbackground-mute是 App 端(Android 4.81+ / iOS 4.81+)均支持的基础播放控制属性;而min-cachemax-cachesound-modepicture-in-picture-mode等属性目前仅在微信小程序端(4.41+)生效,Android / iOS 端标注为x
  • orientationobject-fitsound-mode等枚举型属性的合法值,见下文枚举值小节。

mode 的属性描述

| 合法值 | 兼容性 | | :- | :-: | | RTC | Web: x; 微信小程序: 4.41; Android: x; iOS: x; HarmonyOS: x | | live | Web: x; 微信小程序: 4.41; Android: x; iOS: x; HarmonyOS: x |

live表示普通直播场景,RTC表示实时音视频通话场景(注意当前仅在微信小程序端支持)。

orientation 的属性描述

| 合法值 | 兼容性 | | :- | :-: | | vertical | Web: x; 微信小程序: 4.41; Android: 4.81; iOS: 4.81; HarmonyOS: x | | horizontal | Web: x; 微信小程序: 4.41; Android: 4.81; iOS: 4.81; HarmonyOS: x |

vertical为竖屏方向,horizontal为横屏方向,App 端(Android / iOS)与微信小程序均支持。

object-fit 的属性描述

| 合法值 | 兼容性 | | :- | :-: | | contain | Web: x; 微信小程序: 4.41; Android: 4.81; iOS: 4.81; HarmonyOS: x | | fillCrop | Web: x; 微信小程序: 4.41; Android: 4.81; iOS: 4.81; HarmonyOS: x |

contain表示画面完整包含在组件内(可能留黑边),fillCrop表示以填充并裁剪的方式铺满组件区域。

sound-mode 的属性描述

| 合法值 | 兼容性 | 描述 | | :- | :-: | :- | | speaker | Web: x; 微信小程序: 4.41; Android: x; iOS: x; HarmonyOS: x | 扬声器 | | ear | Web: x; 微信小程序: 4.41; Android: x; iOS: x; HarmonyOS: x | 听筒 |

picture-in-picture-mode 的属性描述

| 合法值 | 兼容性 | 描述 | | :- | :-: | :- | | [] | Web: x; 微信小程序: 4.41; Android: x; iOS: x; HarmonyOS: x | 取消小窗 | | push | Web: x; 微信小程序: 4.41; Android: x; iOS: x; HarmonyOS: x | 路由 push 时触发小窗 | | pop | Web: x; 微信小程序: 4.41; Android: x; iOS: x; HarmonyOS: x | 路由 pop 时触发小窗 |

小窗模式支持通过数组形式设置多种模式,例如["push", "pop"],即路由 push 与 pop 时均触发小窗播放;置为空数组[]可取消小窗。

referrer-policy 的属性描述

| 合法值 | 兼容性 | 描述 | | :- | :-: | :- | | origin | Web: x; 微信小程序: 4.41; Android: x; iOS: x; HarmonyOS: x | 发送完整的referrer | | no-referrer | Web: x; 微信小程序: 4.41; Android: x; iOS: x; HarmonyOS: x | 不发送 |

事件与事件对象

live-player支持以下事件:

| 事件名 | 类型 | 兼容性 | 说明 | | :- | :- | :-: | :- | | @statechange | (event: UniLivePlayerStatechangeEvent) => void | Web: x; 微信小程序: 4.41; Android: 4.81; iOS: 4.81 | 播放状态变化事件,event.detail = {code} | | @fullscreenchange | (event: UniLivePlayerFullscreenchangeEvent) => void | Web: x; 微信小程序: 4.41; Android: 4.81; iOS: 4.81 | 全屏变化事件,event.detail = {direction, fullScreen} | | @error | (event: UniLivePlayerErrorEvent) => void | Web: x; 微信小程序: x; Android: 4.81; iOS: 4.81 | 错误事件,event.detail = {errCode, errMsg} | | @netstatus | (event: UniEvent) => void | Web: x; 微信小程序: 4.41; Android: x; iOS: x | 网络状态通知,detail = {info} | | @audiovolumenotify | eventhandler | Web: x; 微信小程序: 4.41; Android: x; iOS: x; HarmonyOS: x | 播放音量大小通知,detail = {} | | @enterpictureinpicture | eventhandler | Web: x; 微信小程序: 4.41; Android: x; iOS: x; HarmonyOS: x | 播放器进入小窗 | | @leavepictureinpicture | eventhandler | Web: x; 微信小程序: 4.41; Android: x; iOS: x; HarmonyOS: x | 播放器退出小窗 | | @castinguserselect | eventhandler | Web: x; 微信小程序: 4.41; Android: x; iOS: x; HarmonyOS: x | 用户选择投屏设备时触发 detail = { state: "success"/"fail" } | | @castingstatechange | eventhandler | Web: x; 微信小程序: 4.41; Android: x; iOS: x; HarmonyOS: x | 投屏成功/失败时触发 detail = { type, state: "success"/"fail" } | | @castinginterrupt | eventhandler | Web: x; 微信小程序: 4.41; Android: x; iOS: x; HarmonyOS: x | 投屏被中断时触发 |

注意:@error事件在微信小程序端标注为x,错误处理在 App 端(Android 4.81+ / iOS 4.81+)可用。

UniLivePlayerStatechangeEvent 播放状态变化事件

属性值

| 名称 | 类型 | 必填 | | :- | :- | :- | | detail |UniLivePlayerStatechangeEventDetail| 是 | | bubbles | boolean | 是 | | cancelable | boolean | 是 | | type | string | 是 | | target | UniElement | 否 | | currentTarget | UniElement | 否 | | timeStamp | Long | 是 |

detail 的属性描述

| 名称 | 类型 | 必备 | 兼容性 | 描述 | | :- | :- | :- | :-: | :- | | code | number | 是 | Web: x; 微信小程序: x; Android: 4.81; iOS: 4.81; HarmonyOS: x | 状态码 |

code 状态码合法值

| 合法值 | 描述 | | :- | :- | | 10000 | (空) | | 10001 | 初始化 | | 10002 | 准备播放 | | 10004 | 播放中 | | 10006 | 停止渲染 | | 10007 | 播放完成 | | 10008 | 播放进度跳转中 | | 10009 | 播放停止 | | 10010 | 播放错误 | | 10011 | 播放结束 | | 10012 | (空) | | 10013 | 资源释放 |

在仓库示例 src/pages/component/live-player/live-player.uvue 中,正是依据e.detail.code维护了按钮的可用状态:当收到10004(播放中)时置playStatetrue;当收到10006(停止渲染)、10007(播放完成)、10009(播放停止)、10010(播放错误)、10011(播放结束)时置playStatefalse

const statechange = (e : UniLivePlayerStatechangeEvent) => { console.log("statechange", e); switch (e.detail.code) { case 10004: initState.value = false; playState.value = true; stopState.value = false; break; case 10009: stopState.value = true; case 10006: case 10007: case 10010: case 10011: playState.value = false; break; } };
方法

| 名称 | 类型 | 必填 | | :- | :- | :- | | stopPropagation | () => void | 是 | | preventDefault | () => void | 是 |

UniLivePlayerFullscreenchangeEvent 全屏事件

属性值

| 名称 | 类型 | 必填 | | :- | :- | :- | | detail |UniLivePlayerFullscreenchangeEventDetail| 是 | | bubbles | boolean | 是 | | cancelable | boolean | 是 | | type | string | 是 | | target | UniElement | 否 | | currentTarget | UniElement | 否 | | timeStamp | Long | 是 |

detail 的属性描述

| 名称 | 类型 | 必备 | 兼容性 | 描述 | | :- | :- | :- | :-: | :- | | direction | string | 是 | Web: x; 微信小程序: x; Android: 4.81; iOS: 4.81; HarmonyOS: x | 屏幕方向 | | fullScreen | boolean | 是 | Web: x; 微信小程序: x; Android: 4.81; iOS: 4.81; HarmonyOS: x | 是否全屏 |

方法

| 名称 | 类型 | 必填 | | :- | :- | :- | | stopPropagation | () => void | 是 | | preventDefault | () => void | 是 |

UniLivePlayerErrorEvent 错误事件

属性值

| 名称 | 类型 | 必填 | | :- | :- | :- | | detail |UniLivePlayerError| 是 | | bubbles | boolean | 是 | | cancelable | boolean | 是 | | type | string | 是 | | target | UniElement | 否 | | currentTarget | UniElement | 否 | | timeStamp | Long | 是 |

detail 的属性描述

| 名称 | 类型 | 必备 | 描述 | | :- | :- | :- | :- | | errCode | number | 是 | 错误码 | | errSubject | string | 是 | 统一错误主题(模块)名称 | | data | any | 否 | 错误信息中包含的数据 | | cause | Error | 否 | 源错误信息,可以包含多个错误,详见SourceError | | errMsg | string | 是 | 错误信息描述 |

errCode 错误码合法值

| 合法值 | 描述 | | :- | :- | | 3001 | 当前视频格式不支持,视频无法播放 | | 3002 | 视频解码失败 | | 3003 | 不支持的解码格式 | | 3004 | 重连失败,请检查网络情况 | | 3005 | 视频播放失败,请检查网络或视频资源 |

方法

| 名称 | 类型 | 必填 | | :- | :- | :- | | stopPropagation | () => void | 是 | | preventDefault | () => void | 是 |

排查提示:遇到播放失败时,优先核对src协议是否在平台支持范围内(微信小程序支持 flv / rtmp,App 支持 rtmp / hls)、网络是否可达、以及直播流源是否正常推流;错误码 3004 / 3005 均与网络或资源可达性相关。

音视频协议支持

  • 支持rtmphls协议格式。

结合src属性说明,各平台可用的协议/格式汇总如下:

| 平台 | 支持的协议 / 格式 | | :- | :- | | 微信小程序 | flv、rtmp | | App(Android / iOS) | rtmp、hls |

因此在实际项目中应根据目标平台选择拉流地址协议:例如需要覆盖 App 与微信小程序两端时,可优先准备 rtmp 流;仅面向微信小程序时亦可使用 flv 流。

LivePlayerContext 上下文对象 API

通过uni.createLivePlayerContext(livePlayerId, component?)可创建并返回 live-player 组件的上下文对象LivePlayerContext,用于以命令式方式控制播放。完整 API 文档见 docs/api/create-live-player-context.md。

createLivePlayerContext 兼容性

| Web | 微信小程序 | Android | iOS | HarmonyOS | | :- | :- | :- | :- | :- | | x | x | 4.81 | 4.81 | x |

与组件本身的差异:createLivePlayerContext在微信小程序端标注为x,仅 App 端(Android 4.81+ / iOS 4.81+)可用。

参数

| 名称 | 类型 | 必填 | 兼容性 | | :- | :- | :- | :-: | | livePlayerId | string | 是 | Web: x; 微信小程序: x; HarmonyOS: x | | component | ComponentPublicInstance | 否 | |

返回值

| 类型 | 描述 | 必备 | | :- | :- | :- | | LivePlayerContext | live-player 组件上下文对象 | 否 |

LivePlayerContext 的方法

上下文对象提供以下方法,每个方法均接受可选的LivePlayerOptions参数(包含successfailcomplete三个回调),所有方法在 Web / 微信小程序 / HarmonyOS 端均为x,仅在 Android 4.81+ / iOS 4.81+ 可用:

| 方法 | 说明 | 兼容性 | | :- | :- | :- | | play(options?: LivePlayerOptions) : void | 播放 | Web: x; 微信小程序: x; Android: 4.81; iOS: 4.81; HarmonyOS: x | | pause(options?: LivePlayerOptions) : void | 暂停 | 同上 | | stop(options?: LivePlayerOptions) : void | 停止 | 同上 | | resume(options?: LivePlayerOptions) : void | 恢复 | 同上 | | mute(options?: LivePlayerOptions): void | 静音 | 同上 | | requestFullScreen(options?: LivePlayerOptions): void | 全屏 | 同上 | | exitFullScreen(options?: LivePlayerOptions): void | 退出全屏 | 同上 |

LivePlayerOptions 的属性描述

| 名称 | 类型 | 必备 | 兼容性 | 描述 | | :- | :- | :- | :-: | :- | | success | (res: UTSJSONObject) => void | 否 | Web: x; 微信小程序: x; Android: 4.81; iOS: 4.81; HarmonyOS: x | 接口调用成功的回调函数 | | fail | (res: UTSJSONObject) => void | 否 | Web: x; 微信小程序: x; Android: 4.81; iOS: 4.81; HarmonyOS: x | 接口调用失败的回调函数 | | complete | (res: any) => void | 否 | Web: x; 微信小程序: x; Android: 4.81; iOS: 4.81; HarmonyOS: x | 接口调用结束的回调函数(调用成功、失败都会执行) |

在仓库示例 src/pages/component/live-player/live-player.uvue 中,上下文对象在页面onReady生命周期中创建并保存:

onReady(() => { context.value = uni.createLivePlayerContext("live-player", getCurrentInstance()!.proxy); });

注意livePlayerId参数需要与模板中<live-player id="live-player">id保持一致。

完整实战示例(可复制运行)

以下示例完整取自组件文档,并已在仓库 src/pages/component/live-player/live-player.uvue 中落地为 hello uni-app x 示例页面(页面注册于 src/pages.json)。该示例覆盖了属性配置(src / autoplay / muted / object-fit / background-mute / sound-mode / orientation)与上下文 API(play / pause / resume / stop / mute / requestFullScreen / exitFullScreen)的完整用法。

该 API 不支持 Web,请运行 hello uni-app x 到 App 平台体验。

<template> <view class="uni-flex-item"> <live-player id="live-player" class="live-player" :src="src" :autoplay="autoplay" :muted="muted" :object-fit="objectFit" :background-mute="backgroundMute" :sound-mode="soundMode" :orientation="orientation" @statechange="statechange" @fullscreenchange="fullscreenchange" @error="error"> </live-player> <scroll-view id="live-player-scroll-view" class="uni-padding-wrap uni-common-mt uni-flex-item"> <view class="uni-title"> <text class="uni-title-text">API示例</text> </view> <view class="uni-btn-v"> <button type="primary" @click="play" :disabled="playState">播放</button> </view> <view class="uni-btn-v"> <button type="primary" @click="pause" :disabled="!playState">暂停</button> </view> <view class="uni-btn-v"> <button type="primary" @click="resume" :disabled="initState || playState || stopState">恢复</button> </view> <view class="uni-btn-v"> <button type="primary" @click="stop" :disabled="!playState">停止</button> </view> <view class="uni-btn-v"> <button type="primary" @click="mute" :disabled="!playState">静音</button> </view> <view class="uni-btn-v"> <button type="primary" @click="requestFullScreen" :disabled="!playState">进入全屏</button> </view> <view class="uni-btn-v"> <button type="primary" @click="exitFullScreen" :disabled="!playState">退出全屏</button> </view> <view class="uni-title"> <text class="uni-title-text">属性示例</text> </view> <input class="input margin-10" type="string" placeholder="设置播放地址" @confirm="onSrcComfirm"></input> <boolean-data title="设置是否自动播放" :defaultValue="autoplay" @change="onAutoplayChange"></boolean-data> <boolean-data title="设置是否静音" :defaultValue="muted" @change="onMutedChange"></boolean-data> <boolean-data title="设置进入后台时是否静音" :defaultValue="backgroundMute" @change="onBackgroundMuteChange"></boolean-data> <enum-data title="设置填充模式" :items="objectFitItemTypes" @change="onObjectFitChange"></enum-data> <enum-data title="设置声音输出方式" :items="soundModeItemTypes" @change="onSoundModeChange"></enum-data> <enum-data title="设置画面方向" :items="orientationItemTypes" @change="onOrientationChange"></enum-data> </scroll-view> </view> </template> <script setup> import { ItemType } from '@/components/enum-data/enum-data-types'; const context = ref(null as LivePlayerContext | null); const src = ref(""); const autoplay = ref(false); const muted = ref(false); const objectFit = ref("contain"); const backgroundMute = ref(false); const soundMode = ref("speaker"); const orientation = ref("vertical"); const initState = ref(true); const playState = ref(false); const stopState = ref(false); onReady(() => { context.value = uni.createLivePlayerContext("live-player", getCurrentInstance()!.proxy); }); const statechange = (e : UniLivePlayerStatechangeEvent) => { console.log("statechange", e); switch (e.detail.code) { case 10004: initState.value = false; playState.value = true; stopState.value = false; break; case 10009: stopState.value = true; case 10006: case 10007: case 10010: case 10011: playState.value = false; break; } }; const fullscreenchange = (e : UniLivePlayerFullscreenchangeEvent) => { console.log("fullscreenchange", e); }; const error = (e : UniLivePlayerErrorEvent) => { console.log("error", e); }; const isSrcValid = () : boolean => { const length = src.value.length; if (length <= 0) { uni.showToast({ title: "请输入播放地址", icon: "none" }); } return length > 0; }; const play = () => { if (!isSrcValid()) return; context.value?.play({ success: (res) => { console.log("play", JSON.stringify(res)); }, fail: (err) => { console.log("play", JSON.stringify(err)); }, complete: (res) => { console.log("play", JSON.stringify(res)); } }); }; const pause = () => { if (!isSrcValid()) return; context.value?.pause({ success: (res) => { console.log("pause", JSON.stringify(res)); }, fail: (err) => { console.log("pause", JSON.stringify(err)); }, complete: (res) => { console.log("pause", JSON.stringify(res)); } }); }; const resume = () => { if (!isSrcValid()) return; context.value?.resume({ success: (res) => { console.log("resume", JSON.stringify(res)); }, fail: (err) => { console.log("resume", JSON.stringify(err)); }, complete: (res) => { console.log("resume", JSON.stringify(res)); } }); }; const stop = () => { if (!isSrcValid()) return; context.value?.stop({ success: (res) => { console.log("stop", JSON.stringify(res)); }, fail: (err) => { console.log("stop", JSON.stringify(err)); }, complete: (res) => { console.log("stop", JSON.stringify(res)); } }); }; const mute = () => { if (!isSrcValid()) return; context.value?.mute({ success: (res) => { console.log("mute", JSON.stringify(res)); }, fail: (err) => { console.log("mute", JSON.stringify(err)); }, complete: (res) => { console.log("mute", JSON.stringify(res)); } }); }; const requestFullScreen = () => { if (!isSrcValid()) return; context.value?.requestFullScreen({ success: (res) => { console.log("requestFullScreen", JSON.stringify(res)); }, fail: (err) => { console.log("requestFullScreen", JSON.stringify(err)); }, complete: (res) => { console.log("requestFullScreen", JSON.stringify(res)); } }); }; const exitFullScreen = () => { if (!isSrcValid()) return; context.value?.exitFullScreen({ success: (res) => { console.log("exitFullScreen", JSON.stringify(res)); }, fail: (err) => { console.log("exitFullScreen", JSON.stringify(err)); }, complete: (res) => { console.log("exitFullScreen", JSON.stringify(res)); } }); }; const objectFitItemTypes = [{ "value": 0, "name": "contain" }, { "value": 1, "name": "fillCrop" }] as ItemType[]; const objectFitItems = ["contain", "fillCrop"]; const soundModeItemTypes = [{ "value": 0, "name": "speaker" }, { "value": 1, "name": "ear" }] as ItemType[]; const soundModeItems = ["speaker", "ear"]; const orientationItemTypes = [{ "value": 0, "name": "vertical" }, { "value": 1, "name": "horizontal" }] as ItemType[]; const orientationItems = ["vertical", "horizontal"]; const onSrcComfirm = (event : UniInputConfirmEvent) => { let value = event.detail.value; if (value == '') return; src.value = value; console.log("src ->", value); }; const onAutoplayChange = (value : boolean) => { autoplay.value = value; console.log("autoplay ->", autoplay.value); }; const onMutedChange = (value : boolean) => { muted.value = value; console.log("muted ->", muted.value); }; const onBackgroundMuteChange = (value : boolean) => { backgroundMute.value = value; console.log("background-mute ->", backgroundMute.value); }; const onObjectFitChange = (value : number) => { objectFit.value = objectFitItems[value]; console.log("object-fit ->", objectFit.value); }; const onSoundModeChange = (value : number) => { soundMode.value = soundModeItems[value]; console.log("sound-mode ->", soundMode.value); }; const onOrientationChange = (value : number) => { orientation.value = orientationItems[value]; console.log("orientation ->", orientation.value); }; const getScrollViewRectForTest = () : DOMRect | null => { return uni.getElementById('live-player-scroll-view')?.getBoundingClientRect() ?? null; }; defineExpose({ getScrollViewRectForTest }); </script> <style> .live-player { width: 100%; height: 40%; } .input { height: 40px; background: #FFF; padding: 8px 13px; } </style>

示例代码要点解析

  1. 上下文获取时机:必须在组件渲染完成后(onReady生命周期)调用uni.createLivePlayerContext,并传入组件的id与组件实例,否则拿不到有效的LivePlayerContext
  2. 按钮状态与播放状态机联动initState/playState/stopState三个 ref 与statechange中的状态码(10004 播放中、10006 停止渲染、10007 播放完成、10009 播放停止、10010 播放错误、10011 播放结束)联动,保证"播放 / 暂停 / 恢复 / 停止"等按钮在正确的时机可用。
  3. 地址合法性校验isSrcValid()在每次调用上下文方法前校验src是否为空,为空时通过uni.showToast提示"请输入播放地址",避免无效调用。
  4. 枚举数据驱动 UIobjectFitItemTypessoundModeItemTypesorientationItemTypesItemType[]数组形式驱动enum-data组件渲染可选项,选择后映射为对应的字符串值写入组件属性,清晰展示了枚举型属性的动态切换方式。

使用注意事项与排查建议

  • 平台限制明确:组件在 Web / HarmonyOS 端不可用,微信小程序 4.41+、App 端 4.81+ 可用;createLivePlayerContext上下文 API 仅 App 端(4.81+)可用。开发时建议按平台做好条件编译或降级提示。
  • App 端需先申请绑定:Android / iOS 平台使用live-player需申请绑定包名 / Bundle ID(AppID),未绑定时可能导致组件无法正常工作。
  • 协议匹配平台:微信小程序使用 flv / rtmp 格式,App 平台使用 rtmp / hls 协议;请确保推流端产出的流地址协议与目标平台匹配。
  • 错误码对照:播放异常时监听@error事件,依据 errCode(3001~3005)区分格式不支持、解码失败、重连失败、网络或资源异常等场景,结合 errMsg 与cause字段定位根因。
  • 状态机驱动 UI:推荐像示例工程一样以@statechange的 code 为准维护播放状态,避免 UI 按钮状态与播放器真实状态脱节。

参见

  • createLivePlayerContext 上下文 API 文档
  • string.VideoURIString 类型说明
  • UniElement 通用元素接口
  • UniEvent 通用事件说明
  • UniError 统一错误规范
  • 仓库示例源码:src/pages/component/live-player/live-player.uvue
  • 示例页面注册:src/pages.json

【免费下载链接】uni-appA cross-platform framework using Vue.js项目地址: https://gitcode.com/gh_mirrors/un/uni-app

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询