更新记录

1.0.0(2026-06-01)

  • 新增 LiveKit 房间连接、断开连接 API。
  • 新增麦克风和摄像头发布 API。
  • 新增摄像头采集参数配置和运行时切换摄像头能力。
  • 新增麦克风采集参数配置。
  • 新增房间状态和本地媒体状态快照 API。
  • 新增远端轨道订阅、取消订阅 API。
  • 新增扬声器输出切换和原生日志开关 API。
  • 新增参与者列表和轨道列表快照 API。
  • 新增完整的 LiveKit 房间事件监听载荷,覆盖发言人、数据消息、连接质量、静音、元数据、名称和属性等信息。
  • 新增文本数据通道发送能力。
  • 新增内置 hans-livekit-video 原生视频组件。
  • 新增 Android 和 iOS 原生实现。
  • 新增 uni-app x App 和 uni-app App-NVue 兼容支持。

平台兼容性

uni-app(5.07)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
- - - - - -
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
- - - - - - - - - - - -

uni-app x(5.07)

Chrome Safari Android iOS 鸿蒙 微信小程序
- - - -

hans-livekit

hans-livekit 是 LiveKit 的 UTS 原生能力插件,用于在 uni-app x App 和 uni-app App-NVue 中连接 LiveKit 房间、发布音视频、读取参与者和轨道信息、接收房间事件,并内置 <hans-livekit-video /> 视频渲染组件。

使用前准备

  1. 在 LiveKit 服务端生成访问 token。
  2. App 需要配置摄像头和麦克风权限。
  3. 真机运行原生 SDK 能力时需要使用自定义基座;标准基座无法加载插件内的三方原生 SDK。
  4. 如果需要显示视频画面,直接使用本插件内置的 <hans-livekit-video /> 组件。

快速开始

import {
  CommonResult,
  ConnectRoomResult,
  GetLocalMediaStateResult,
  GetParticipantsResult,
  GetRoomStateResult,
  GetTracksResult,
  LiveKitEvent,
  LiveKitFail,
  LiveKitParticipantInfo,
  LiveKitTrackInfo,
  TrackOperationResult,
  connectRoom,
  disconnectRoom,
  getLocalMediaState,
  getParticipants,
  getRoomState,
  getTracks,
  onLiveKitEvent,
  offLiveKitEvent,
  sendData,
  setCameraEnabled,
  setLiveKitLogEnabled,
  setMicrophoneEnabled,
  setSpeakerEnabled,
  setTrackSubscribed,
  switchCamera,
} from '@/uni_modules/hans-livekit'

let roomId = ''
let localVideoTrackId = ''

const handleLiveKitEvent = (event: LiveKitEvent): void => {
  console.log('LiveKit event', event)
  if (event.kind != null && event.kind == 'video' && event.trackId != null) {
    localVideoTrackId = event.trackId!
  }
}

onLiveKitEvent(handleLiveKitEvent)

connectRoom({
  url: 'wss://your-host.livekit.cloud',
  token: '<livekit-token>',
  autoSubscribe: true,
  success: (res: ConnectRoomResult) => {
    roomId = res.roomId

    setMicrophoneEnabled({
      roomId,
      enabled: true,
      captureOptions: {
        echoCancellation: true,
        autoGainControl: true,
        noiseSuppression: true,
      },
      success: (micRes: TrackOperationResult) => {
        console.log('microphone enabled', micRes.enabled)
      },
    })

    setCameraEnabled({
      roomId,
      enabled: true,
      captureOptions: {
        position: 'front',
        fps: 30,
        resolution: 'h720',
      },
      success: (cameraRes: TrackOperationResult) => {
        localVideoTrackId = cameraRes.trackId ?? ''
        console.log('local video trackId', localVideoTrackId)
      },
    })
  },
  fail: (err: LiveKitFail) => {
    console.error(err.errCode, err.errMsg)
  },
})

getRoomState({
  roomId,
  success: (res: GetRoomStateResult) => {
    console.log('room state', res.connectionState, res.participantCount)
  },
})

getLocalMediaState({
  roomId,
  success: (res: GetLocalMediaStateResult) => {
    console.log('local media', res.microphoneEnabled, res.cameraEnabled)
  },
})

switchCamera({
  roomId,
  success: (res: TrackOperationResult) => {
    localVideoTrackId = res.trackId ?? localVideoTrackId
  },
})

getParticipants({
  roomId,
  success: (res: GetParticipantsResult) => {
    const local = res.participants.find((item: LiveKitParticipantInfo): boolean => item.local)
    console.log('local participant', local?.identity)
  },
})

getTracks({
  roomId,
  success: (res: GetTracksResult) => {
    const videoTracks = res.tracks.filter((track: LiveKitTrackInfo): boolean => {
      return track.kind == 'video'
    })
    console.log(videoTracks)
  },
})

setTrackSubscribed({
  roomId,
  publicationId: '<remote-publication-id>',
  subscribed: true,
  success: (res: TrackOperationResult) => {
    console.log('subscribed', res.publicationId)
  },
})

sendData({
  roomId,
  payload: 'hello',
  topic: 'chat',
  reliable: true,
  destinationIdentities: ['user-a'],
  success: (res: CommonResult) => {
    console.log('data sent', res.ok)
  },
})

setSpeakerEnabled({
  roomId,
  enabled: true,
})

setLiveKitLogEnabled({
  enabled: false,
  level: 'info',
})

disconnectRoom({
  roomId,
  success: (res: CommonResult) => {
    console.log('disconnect', res.ok)
  },
  complete: (_res: any) => {
    roomId = ''
    localVideoTrackId = ''
    offLiveKitEvent(handleLiveKitEvent)
  },
})

API 和类型导入

在 uni-app x 的 <script setup lang="uts"> 和 uni-app App-NVue 的 <script> 中,建议和 playground 一样显式导入 API 返回类型。这样 success 回调、事件处理和页面状态都能获得明确类型。

import {
  CommonResult,
  ConnectRoomResult,
  GetLocalMediaStateResult,
  GetParticipantsResult,
  GetRoomStateResult,
  GetTracksResult,
  LiveKitEvent,
  LiveKitEventCallback,
  LiveKitFail,
  LiveKitParticipantInfo,
  LiveKitSpeakerInfo,
  LiveKitTrackInfo,
  LiveKitVideoObjectFit,
  SetLiveKitLogEnabledResult,
  TrackOperationResult,
  connectRoom,
  disconnectRoom,
  getLocalMediaState,
  getParticipants,
  getRoomState,
  getTracks,
  offLiveKitEvent,
  onLiveKitEvent,
  sendData,
  setCameraEnabled,
  setLiveKitLogEnabled,
  setMicrophoneEnabled,
  setSpeakerEnabled,
  setTrackSubscribed,
  switchCamera,
} from '@/uni_modules/hans-livekit'

页面状态类型示例

uniappx-livekit-playground/pages/index/index.uvue 使用下面这种方式保存测试页面状态。业务页面可以按需裁剪,但推荐保留 roomId、本地/远端 trackIdpublicationId 和房间快照字段。

type LiveKitPlaygroundTestData = {
  statusText: string
  roomId: string
  url: string
  token: string
  micEnabled: boolean
  cameraEnabled: boolean
  speakerEnabled: boolean
  logEnabled: boolean
  selectedVideoTrackId: string
  dataPayload: string
  dataTopic: string
  destinationIdentity: string
  firstRemotePublicationId: string
  remoteVideoTrackId: string
  localVideoTrackId: string
  roomName: string
  identity: string
  tokenServerUrl: string
  participantsText: string
  tracksText: string
}

const data = reactive<LiveKitPlaygroundTestData>({
  statusText: 'Idle',
  roomId: '',
  url: 'ws://192.168.123.56:7880',
  token: '',
  micEnabled: false,
  cameraEnabled: false,
  speakerEnabled: false,
  logEnabled: true,
  selectedVideoTrackId: '',
  dataPayload: 'hello',
  dataTopic: 'chat',
  destinationIdentity: '',
  firstRemotePublicationId: '',
  remoteVideoTrackId: '',
  localVideoTrackId: '',
  roomName: 'my-room',
  identity: '',
  tokenServerUrl: 'http://192.168.123.56:3001',
  participantsText: '[]',
  tracksText: '[]',
})

常用回调建议显式声明返回类型:

const eventCallback: LiveKitEventCallback = (event: LiveKitEvent): void => {
  if (event.type == 'dataReceived') {
    console.log(event.topic ?? '', event.payload ?? '')
  }
}

connectRoom({
  url,
  token,
  autoSubscribe: true,
  success: (res: ConnectRoomResult): void => {
    roomId = res.roomId
  },
  fail: (err: LiveKitFail): void => {
    console.log(err.errCode, err.errMsg)
  },
})

setCameraEnabled({
  roomId,
  enabled: true,
  captureOptions: { position: 'front', fps: 30, resolution: 'h720' },
  success: (res: TrackOperationResult): void => {
    localVideoTrackId = res.trackId ?? ''
  },
})

核心类型速查

以下类型由 @/uni_modules/hans-livekit 导出,可直接在 .uvue / .nvue 页面中使用。

export type LiveKitErrorCode =
  9010001 | 9010002 | 9010003 | 9010004 | 9010005 |
  9010006 | 9010007 | 9010008 | 9010009 | 9010010

export interface LiveKitFail extends IUniError {
  errCode: LiveKitErrorCode
}

export type CommonResult = {
  roomId: string
  ok: boolean
}

export type ConnectRoomResult = {
  roomId: string
  name: string
  identity: string
  connectionState: string
}

export type TrackOperationResult = {
  roomId: string
  enabled: boolean
  trackId?: string | null
  publicationId?: string | null
  kind: string
  source: string
  appliedOptions?: string[] | null
  unsupportedOptions?: string[] | null
}

export type LiveKitParticipantInfo = {
  participantId: string
  identity: string
  name: string
  metadata: string
  attributes?: string | null
  local: boolean
  connectionQuality: string
}

export type LiveKitTrackInfo = {
  trackId: string
  publicationId: string
  participantId: string
  kind: string
  source: string
  name: string
  muted: boolean
  subscribed: boolean
  local: boolean
}

export type LiveKitSpeakerInfo = {
  participantId: string
  identity: string
  name?: string | null
  isSpeaking: boolean
  audioLevel: number
}

export type LiveKitEventType =
  'connected' |
  'reconnecting' |
  'reconnected' |
  'disconnected' |
  'failedToConnect' |
  'participantConnected' |
  'participantDisconnected' |
  'trackPublished' |
  'trackUnpublished' |
  'trackSubscribed' |
  'trackUnsubscribed' |
  'trackMuted' |
  'trackUnmuted' |
  'connectionQualityChanged' |
  'dataReceived' |
  'speakersChanged' |
  'participantMetadataChanged' |
  'participantNameChanged' |
  'participantAttributesChanged'

export type LiveKitEvent = {
  type: LiveKitEventType | string
  roomId: string
  participantId?: string | null
  identity?: string | null
  name?: string | null
  metadata?: string | null
  attributes?: string | null
  trackId?: string | null
  publicationId?: string | null
  kind?: string | null
  source?: string | null
  muted?: boolean | null
  subscribed?: boolean | null
  connectionState?: string | null
  connectionQuality?: string | null
  payload?: string | null
  topic?: string | null
  reliable?: boolean | null
  speakers?: LiveKitSpeakerInfo[] | null
  message?: string | null
  timestamp: number
}

export type LiveKitCameraCaptureOptions = {
  position?: string | null
  fps?: number | null
  resolution?: string | null
  width?: number | null
  height?: number | null
}

export type LiveKitMicrophoneCaptureOptions = {
  noiseSuppression?: boolean | null
  echoCancellation?: boolean | null
  autoGainControl?: boolean | null
  highpassFilter?: boolean | null
}

export type GetRoomStateResult = {
  roomId: string
  name: string
  identity: string
  connectionState: string
  participantCount: number
}

export type GetLocalMediaStateResult = {
  roomId: string
  microphoneEnabled: boolean
  cameraEnabled: boolean
  cameraPosition: string
  microphoneTrackId?: string | null
  cameraTrackId?: string | null
}

export type GetParticipantsResult = {
  roomId: string
  participants: LiveKitParticipantInfo[]
}

export type GetTracksResult = {
  roomId: string
  tracks: LiveKitTrackInfo[]
}

export type SetLiveKitLogEnabledResult = {
  enabled: boolean
  level: string
}

export type LiveKitVideoObjectFit = 'contain' | 'cover' | 'fill'
export type LiveKitEventCallback = (event: LiveKitEvent) => void

export type ConnectRoomOptions = {
  url: string
  token: string
  roomName?: string | null
  autoSubscribe?: boolean | null
  success?: (res: ConnectRoomResult) => void
  fail?: (err: LiveKitFail) => void
  complete?: (res: any) => void
}

export type DisconnectRoomOptions = {
  roomId: string
  success?: (res: CommonResult) => void
  fail?: (err: LiveKitFail) => void
  complete?: (res: any) => void
}

export type SetMicrophoneEnabledOptions = {
  roomId: string
  enabled: boolean
  captureOptions?: LiveKitMicrophoneCaptureOptions | null
  success?: (res: TrackOperationResult) => void
  fail?: (err: LiveKitFail) => void
  complete?: (res: any) => void
}

export type SetCameraEnabledOptions = {
  roomId: string
  enabled: boolean
  cameraPosition?: string | null
  captureOptions?: LiveKitCameraCaptureOptions | null
  success?: (res: TrackOperationResult) => void
  fail?: (err: LiveKitFail) => void
  complete?: (res: any) => void
}

export type SwitchCameraOptions = {
  roomId: string
  position?: string | null
  success?: (res: TrackOperationResult) => void
  fail?: (err: LiveKitFail) => void
  complete?: (res: any) => void
}

export type GetRoomStateOptions = {
  roomId: string
  success?: (res: GetRoomStateResult) => void
  fail?: (err: LiveKitFail) => void
  complete?: (res: any) => void
}

export type GetLocalMediaStateOptions = {
  roomId: string
  success?: (res: GetLocalMediaStateResult) => void
  fail?: (err: LiveKitFail) => void
  complete?: (res: any) => void
}

export type GetParticipantsOptions = {
  roomId: string
  success?: (res: GetParticipantsResult) => void
  fail?: (err: LiveKitFail) => void
  complete?: (res: any) => void
}

export type GetTracksOptions = {
  roomId: string
  success?: (res: GetTracksResult) => void
  fail?: (err: LiveKitFail) => void
  complete?: (res: any) => void
}

export type SetTrackSubscribedOptions = {
  roomId: string
  publicationId: string
  subscribed: boolean
  success?: (res: TrackOperationResult) => void
  fail?: (err: LiveKitFail) => void
  complete?: (res: any) => void
}

export type SendDataOptions = {
  roomId: string
  payload: string
  topic?: string | null
  reliable?: boolean | null
  destinationIdentities?: string[] | null
  destinationParticipantIds?: string[] | null
  success?: (res: CommonResult) => void
  fail?: (err: LiveKitFail) => void
  complete?: (res: any) => void
}

export type SetSpeakerEnabledOptions = {
  roomId: string
  enabled: boolean
  success?: (res: CommonResult) => void
  fail?: (err: LiveKitFail) => void
  complete?: (res: any) => void
}

export type SetLiveKitLogEnabledOptions = {
  enabled: boolean
  level?: string | null
  success?: (res: SetLiveKitLogEnabledResult) => void
  fail?: (err: LiveKitFail) => void
  complete?: (res: any) => void
}

API

connectRoom(options)

连接 LiveKit 房间。

参数 类型 必填 说明
url string LiveKit WebSocket 地址
token string LiveKit access token
autoSubscribe boolean 是否自动订阅远端轨道,默认 true
success function 成功回调
fail function 失败回调
complete function 完成回调

success 返回:

{
  roomId: string
  name: string
  identity: string
  connectionState: string
}

disconnectRoom(options)

断开房间连接。

参数 类型 必填 说明
roomId string connectRoom 返回的房间 ID
success function 成功回调
fail function 失败回调
complete function 完成回调

setMicrophoneEnabled(options)

开启或关闭本地麦克风。

参数 类型 必填 说明
roomId string 房间 ID
enabled boolean 是否开启
captureOptions LiveKitMicrophoneCaptureOptions 麦克风采集参数
success function 成功回调
fail function 失败回调
complete function 完成回调

captureOptions 字段:

字段 类型 说明
noiseSuppression boolean 降噪
echoCancellation boolean 回声消除
autoGainControl boolean 自动增益
highpassFilter boolean 高通滤波

返回值里的 appliedOptions 表示已应用字段,unsupportedOptions 表示当前平台未应用字段。

平台差异:

平台 行为
Android 当前使用 LiveKit Android 默认麦克风开启/关闭能力,noiseSuppressionechoCancellationautoGainControlhighpassFilter 会进入 unsupportedOptions
iOS 通过 LiveKit AudioCaptureOptions 应用 noiseSuppressionechoCancellationautoGainControlhighpassFilter

setCameraEnabled(options)

开启或关闭本地摄像头。

参数 类型 必填 说明
roomId string 房间 ID
enabled boolean 是否开启
captureOptions LiveKitCameraCaptureOptions 摄像头采集参数
cameraPosition string 兼容旧字段,推荐使用 captureOptions.position
success function 成功回调
fail function 失败回调
complete function 完成回调

captureOptions 字段:

字段 类型 说明
position string frontback
fps number 常用 152430
resolution string h360h540h720h1080
width number 自定义宽度,需要和 height 一起传
height number 自定义高度,需要和 width 一起传

success 返回中的 trackId 可传给 <hans-livekit-video /> 渲染本地视频。

平台差异:

平台 行为
Android 支持 positionfpsresolutionwidthheight 需要同时传入才会应用
iOS 支持 positionfpsresolutionwidthheight 需要同时传入才会应用;会映射到 LiveKit CameraCaptureOptions

switchCamera(options)

运行中切换摄像头。摄像头未开启时会返回轨道不存在错误。

参数 类型 必填 说明
roomId string 房间 ID
position string frontback;不传时切到另一侧
success function 成功回调,返回 TrackOperationResult
fail function 失败回调
complete function 完成回调

getRoomState(options)

获取当前房间状态快照。

参数 类型 必填 说明
roomId string 房间 ID
success function 成功回调,返回 GetRoomStateResult
fail function 失败回调
complete function 完成回调

返回字段:roomIdnameidentityconnectionStateparticipantCount

getLocalMediaState(options)

获取本地麦克风、摄像头和当前本地轨道状态。

参数 类型 必填 说明
roomId string 房间 ID
success function 成功回调,返回 GetLocalMediaStateResult
fail function 失败回调
complete function 完成回调

返回字段:microphoneEnabledcameraEnabledcameraPositionmicrophoneTrackIdcameraTrackId

视频组件

<hans-livekit-video /> 内置在本插件中,不需要额外安装组件插件。

<template>
  <hans-livekit-video
    style="width: 320px; height: 240px;"
    :room-id="roomId"
    :track-id="videoTrackId"
    object-fit="cover"
    :mirror="mirror"
    @ready="handleVideoReady"
    @first-frame="handleVideoFirstFrame"
    @error="handleVideoError"
  />
</template>

<script setup lang="uts">
const roomId = ref('')
const videoTrackId = ref('')
const mirror = ref(true)

function handleVideoReady(_event: UniNativeViewEvent): void {
  console.log('video ready')
}

function handleVideoFirstFrame(_event: UniNativeViewEvent): void {
  console.log('video first frame')
}

function handleVideoError(event: UniNativeViewEvent): void {
  console.error('video error', event.detail)
}
</script>
属性 类型 默认值 说明
room-id / roomId string '' connectRoom 返回的房间 ID
track-id / trackId string '' setCameraEnabledgetTracks 或轨道事件返回的视频 trackId
object-fit / objectFit string contain containcoverfill
mirror boolean false 是否镜像显示
view-background-color / viewBackgroundColor string #000000 原生视图背景色
placeholder string No video track 无视频轨道时的占位文本
事件 说明
ready 原生视频视图已创建或已绑定轨道
first-frame Android 端首帧渲染完成;iOS 端绑定成功后会先触发 ready
error 视频视图绑定失败

getParticipants(options)

获取当前房间参与者快照。

参数 类型 必填 说明
roomId string 房间 ID
success function 成功回调
fail function 失败回调
complete function 完成回调

getTracks(options)

获取当前房间轨道快照。

参数 类型 必填 说明
roomId string 房间 ID
success function 成功回调
fail function 失败回调
complete function 完成回调

setTrackSubscribed(options)

手动订阅或取消订阅远端轨道。连接房间时如果 autoSubscribefalse,可先通过 getTracks 或轨道事件拿到 publicationId,再调用这个 API。

参数 类型 必填 说明
roomId string 房间 ID
publicationId string 远端轨道发布 ID
subscribed boolean 是否订阅
success function 成功回调,返回 TrackOperationResult
fail function 失败回调
complete function 完成回调

sendData(options)

发送文本 data channel 消息。

参数 类型 必填 说明
roomId string 房间 ID
payload string 文本内容
topic string 主题
reliable boolean 是否可靠传输
destinationIdentities string[] 指定接收者 identity
destinationParticipantIds string[] 兼容旧字段,推荐使用 destinationIdentities
success function 成功回调
fail function 失败回调
complete function 完成回调
sendData({
  roomId,
  payload: 'hello',
  topic: 'chat',
  reliable: true,
  destinationIdentities: ['user-a'],
  success: (res: CommonResult) => {
    console.log(res.ok)
  },
})

destinationIdentities 传 LiveKit participant identity,不是 participant SID;destinationParticipantIds 仅作为旧字段兼容保留。

setSpeakerEnabled(options)

切换系统扬声器外放。

参数 类型 必填 说明
roomId string 房间 ID
enabled boolean 是否外放
success function 成功回调
fail function 失败回调
complete function 完成回调

setLiveKitLogEnabled(options)

开启或关闭插件原生日志。

参数 类型 必填 说明
enabled boolean 是否输出日志
level string 日志级别标记,默认 info
success function 成功回调
fail function 失败回调
complete function 完成回调

onLiveKitEvent(callback)

监听 LiveKit 房间事件。

事件类型:

type 说明
connected / reconnecting / reconnected / disconnected / failedToConnect 连接状态变化
participantConnected / participantDisconnected 参与者加入或离开
trackPublished / trackUnpublished 轨道发布或取消发布
trackSubscribed / trackUnsubscribed 轨道订阅或取消订阅
trackMuted / trackUnmuted 轨道静音状态变化
connectionQualityChanged 连接质量变化
dataReceived 收到 data channel 文本消息
speakersChanged 活跃说话人变化
participantMetadataChanged / participantNameChanged / participantAttributesChanged 参与者资料变化

事件对象字段:

字段 类型 说明
type string 事件类型
roomId string 房间 ID
participantId string | null 参与者 ID
identity string | null 参与者 identity
name string | null 参与者名称
metadata string | null 参与者 metadata
attributes string | null 参与者 attributes 的 JSON 字符串
trackId string | null 轨道 ID
publicationId string | null 发布 ID
kind string | null audiovideo
source string | null 轨道来源
muted boolean | null 是否静音
subscribed boolean | null 是否已订阅
connectionState string | null 连接状态
connectionQuality string | null 连接质量
payload string | null dataReceived 文本内容
topic string | null dataReceived 主题
reliable boolean | null data channel 是否可靠传输
speakers LiveKitSpeakerInfo[] | null 活跃说话人列表
message string | null 附加消息
timestamp number 时间戳

offLiveKitEvent(callback?)

移除事件监听。不传 callback 时移除所有监听。

常见错误码

errCode 说明
9010001 参数错误
9010002 当前平台不支持
9010003 权限不足
9010004 房间不存在
9010005 轨道不存在
9010006 原生 SDK 错误
9010007 连接失败
9010010 功能未实现

注意事项

  • 插件不包含 token 生成逻辑,token 应由你的业务服务端生成。
  • 标准基座只能用于基础编译检查;实际连接 LiveKit 和调用原生 SDK 需要自定义基座。
  • 内联视频渲染请使用内置 <hans-livekit-video />,并传入本插件返回的 roomIdtrackId

隐私、权限声明

1. 本插件需要申请的系统权限列表:

Android: INTERNET, CAMERA, RECORD_AUDIO, MODIFY_AUDIO_SETTINGS, BLUETOOTH_CONNECT. iOS: Camera, Microphone, Bluetooth usage descriptions. Includes the hans-livekit-video native video component.

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

暂无用户评论。