更新记录
1.0.4(2026-10-21)
- 首次发布 wd-livekit-native 插件。
- 支持 Android App 端(nvue 页面)接入 LiveKit,基于官方原生 SDK(非 WebView、非 JS SDK)。
- 提供基础音视频控制:
connect/disconnect/setMicrophoneEnabled/setCameraEnabled/switchCamera/setSpeakerphoneOn。 - 提供原生渲染组件
livekit-video-view(viewRole="local" | "remote"):轨道自动绑定画面,无需手动管理 track。 - 内置小窗拖动、点击交换全屏/小窗交互,由原生层实现。
- 支持弱网自动重连(
onReconnecting/onReconnected)与对端网络质量回调(onNetworkQuality)。 - iOS 端 Swift 实现已提供,但未经编译验证,暂不建议用于生产。
平台兼容性
uni-app(4.76)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|
| - | - | - | - | - | - | - | - | - |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| - | - | - | - | - | - | - | - | - | - | - | - |
wd-livekit-native
基于 LiveKit 官方原生 SDK(Android: io.livekit:livekit-android,iOS: LiveKitClient)封装的 1v1 实时音视频通话 UTS 插件。非 WebView 方案、非 JS SDK 方案,画面由原生 WebRTC 渲染器(TextureViewRenderer)直出。
接入方只需要关心「连房间」和「挂断」两件事:
- 画面全自动绑定:本地/远端轨道由插件原生层自动分发到渲染组件,无任何手动绑 track 的 API
- 小窗交互内置:小窗拖动、点击交换全屏/小窗,均在原生层实现,页面不用写手势
- 弱网自动重连:瞬断由 SDK 自动恢复,业务层只需在回调里切换提示
平台支持
| 平台 | 支持 | 说明 |
|---|---|---|
| Android App(nvue 页面) | ✅ 已实测 | minSdkVersion 21 |
| iOS App | ⚠️ 代码已提供 | Swift 实现未经编译验证;onNetworkQuality / onReconnecting / onReconnected 回调暂未桥接 |
| H5 / 小程序 | ❌ |
渲染组件
livekit-video-view仅可在 nvue 页面 使用。
快速上手(3 步)
参考资料:https://www.yuque.com/bian-trriw/ruwq76/yn7s3669i9d6ktnc
1. nvue 页面放两个渲染组件
<template>
<view>
<!-- 远端全屏 -->
<livekit-video-view viewRole="remote" class="vc-remote"></livekit-video-view>
<!-- 本地小窗(mirror 镜像) -->
<livekit-video-view viewRole="local" :mirror="true" class="vc-local"></livekit-video-view>
</view>
</template>
/* 样式示例:远端全屏铺满,小窗位置见下文「必须遵守的写法」第 4 条 */
.vc-remote { position: absolute; top: 0; left: 0; right: 0; bottom: 0; }
.vc-local { position: absolute; }
connect 成功后本地画面自动进小窗,对方画面到达后自动进全屏,不需要也不能手动绑 track。
2. 拿 token 连房间
token 由你的后端调 LiveKit Server API 签发(见下文「后端要求」)。
import { connect } from '@/uni_modules/wd-livekit-native'
const res = await uni.request({ url: 'https://your-server/api/video/token?roomId=xxx' })
const { token, url } = res.data.data
connect(url, token, {
onConnected: () => {}, // 接通
onTrackSubscribed: (sid, identity, kind) => {}, // kind='VIDEO' 即对方画面到达
onDisconnected: (reason) => {}, // 'participant-left' 对方挂断
onError: (msg) => {},
onNetworkQuality: (level) => {}, // 对端网络质量,见 RoomEvents
onReconnecting: () => {}, // 瞬断自动重连中
onReconnected: () => {} // 重连成功
})
3. 操作与挂断
import { disconnect, setMicrophoneEnabled, switchCamera, setSpeakerphoneOn } from '@/uni_modules/wd-livekit-native'
setMicrophoneEnabled(false) // 静音
switchCamera() // 翻转前后摄像头
setSpeakerphoneOn(false) // 切听筒(true=扬声器外放,连接后默认扬声器)
disconnect() // 挂断。页面 onUnload 里必须调,否则摄像头不释放
API 一览
| API | 说明 |
|---|---|
connect(url, token, events) |
连房间,成功后自动开摄像头/麦克风/扬声器 |
disconnect() |
断开并释放资源,退出页面必须调 |
setMicrophoneEnabled(bool) |
麦克风开关 |
setCameraEnabled(bool) |
摄像头开关 |
switchCamera() |
前后摄切换 |
setSpeakerphoneOn(bool) |
扬声器/听筒切换 |
swapVideoViews() |
手动交换全屏/小窗画面(一般不用,点小窗原生层已自动交换) |
getDebugState() |
调试用状态快照字符串 |
RoomEvents 回调(全部可选)
| 回调 | 参数 | 说明 |
|---|---|---|
onConnected |
- | 房间接通 |
onTrackSubscribed |
sid, identity, kind |
对方轨道到达,kind = 'AUDIO' | 'VIDEO' |
onTrackUnsubscribed |
sid |
对方轨道移除 |
onDisconnected |
reason |
'participant-left' 对方离开 | 'disconnected' 房间断开,仅在彻底失败时触发 |
onError |
message |
出错(连接失败等) |
onNetworkQuality |
level |
对端网络质量:excellent / good / poor / lost / unknown |
onReconnecting |
- | 瞬断自动重连中(SDK 自动恢复,无需重拨) |
onReconnected |
- | 重连成功 |
渲染组件 livekit-video-view
| 属性 | 类型 | 默认 | 说明 |
|---|---|---|---|
viewRole |
String | 'remote' |
'remote' 远端画面(全屏)| 'local' 本地预览(小窗) |
mirror |
Boolean | false |
本地画面是否镜像 |
必须遵守的写法(违反会黑屏/失效)
- 两个组件放在 page 根节点直接子级,不要包在
absolute + overflow:hidden容器里 - 组件不要写 background-color 样式
- 组件常驻挂载,别用 v-if 控制显隐(未接通用占位 view 盖住即可)
- 小窗用内联 style 定位时,值要乘
screenWidth / 750(UTS 组件 px 与 weex px 不一致),参考:
// onLoad 里算补偿系数
const sys = uni.getSystemInfoSync()
this.compRatio = (sys.screenWidth || 750) / 750
// 内联样式里使用
this.style = `top:${Math.round(top * this.compRatio)}px;left:${Math.round(left * this.compRatio)}px;width:${Math.round(192 * this.compRatio)}px;height:${Math.round(300 * this.compRatio)}px;`
- 别给组件包 @click/@touch —— 收不到事件,小窗拖动/交换已在原生层实现
- Android 需预申请运行时权限
CAMERA/RECORD_AUDIO(建议连同MODIFY_AUDIO_SETTINGS),拒绝时原生 SDK 会给出明确错误 - 修改插件源码后需重新云打包自定义基座才能生效
后端要求
需要自己部署 LiveKit Server,并提供一个签发 token 的接口:
GET /api/video/token?roomId=xxx
返回:{ "url": "wss://your-livekit-server", "token": "eyJ..." }
同一房间的双方拿各自 token 进房即可互通。呼叫/接听/挂断等信令(STOMP WebSocket、IM 通道等)由业务层自行实现,本插件不参与信令。
完整示例里,哪些代码和插件有关?
下面用一个完整通话页(含呼叫流程)说明边界——插件相关的只有 4 块,其余都是业务代码:
| 代码块 | 归属 | 作用 |
|---|---|---|
两个 <livekit-video-view> 组件及其样式 |
插件 | 渲染本地/远端画面 |
connect(url, token, {...}) |
插件 | 进房间 |
setMicrophoneEnabled / switchCamera / setSpeakerphoneOn |
插件 | 通话操作 |
disconnect()(放在 onUnload / 清理函数里) |
插件 | 挂断并释放摄像头/麦克风 |
| STOMP/WebSocket 信令(invite / accept / reject / hangup) | 业务 | 决定「谁和谁、何时、进哪个房间」 |
| 获取 token 的后端接口 | 业务 | 后端签发 LiveKit 凭证 |
| 状态文案、计时、网络质量 UI、图标字体、占位头像等 | 业务 | 界面展示 |
也就是说:不实现呼叫信令也能用本插件——写个测试按钮直接调 connect() 就能进房间看到画面。信令只是决定通话的时机和对象。
完整工程示例(信令 + UI + 插件接入):参考
pages/myPage/videoCall.nvue(本项目内)。

收藏人数:
购买源码授权版(
试用
赞赏(0)
下载 0
赞赏 0
下载 12700756
赞赏 1956
赞赏
京公网安备:11010802035340号