Options
All
  • Public
  • Public/Protected
  • All
Menu

如视 Live SDK

Live.js

npm version

功能说明

Live如视开发者中心 VRTC 服务 的核心客户端 Web SDK,搭配 Live Container SDKs(iOS/Android/微信小程序)和 Live API 可以快速实现实时同屏、实时语音、IM 等功能。

名词释义

  • 帧数据(Keyframe): 指用户界面需同屏交互信息的状态数据的集合。

通常以键值对的形式表现——键为界面模块名字,值为该模块的状态信息。
比如帧数据 {"popupPanel": { hidden: true }} 表示界面交互中有个弹窗面板,我们命名为popupPanel,它有个hidden状态,true表示其正处于隐藏状态。

  • 快照(Snapshot): 指某个时刻所有 帧数据 的集合。

您可以理解 帧数据快照 的子集,通过某时刻的"快照"信息能够还原该时刻的用户界面所有状态。

  • RTC: Real-Time Communication, 在本文中则特指渲染 HTML 页面的 WebView/Browser 等容器的音视频实时通信能力。

需注意的是 Live 并不包含 RTC 功能的实现,需借助客户端原生能力的支持。更多细节详见后文 RTC 协议 部分。

快速上手

安装 SDK

可以通过 Node 包管理工具 npmyarn 安装Live

# npm
npm i @realsee/live
# yarn
yarn add @realsee/live

如何使用

简单使用样例(先不考虑实时语音能力):

import { createLive } from '@realsee/live'

const live = createLive({
url: 'wss://ws-access.realsee.com/***/?=xxx' /* 连接 WebSocket 服务的 URL */,
getTicket: async () => {
/* 获取带看"门票"的回调函数 */
},
})

在创建 live 实例时配置了两个参数:

  • url:连接 WebSocket 服务的 URL,如果在创建 live 实例阶段并不知道 URL ,您可以在合适的时机通过 live.connect({ url }) 方法进行 WebScoket 连接。
  • getTicket():是一个异步回调函数,其返回值是连接 WebScoket 服务的 **"门票"**,关于如何获取 ticket 请查阅 VR 带看 API

关于 createLive() 函数的更多参数配置请参考 LiveOptions

获取实例 live 之后,可以做很多有趣的事情。但在讲述详细用途之前,先简单介绍下 Live 中的 消息系统

消息系统

Live 核心职责是借助 WebSocket 长链双工通信能力实现多端用户的同屏连线。用户间的通信都是基于 WebSocket 消息。

Live 将消息分为帧数据广播房间信息三类。针对每一类信息提供相应的发送、接收 API,更多 API 细节请参考 Live API 文档

帧数据 是进行同屏的信息载体,由用户自行定义当前场景中哪些信息用以同屏,将这些信息组织成 {key: value} 的形式即可。

广播消息 用以房间成员之间以事件的形式指定某个用户向其发送自定义广播消息。如:主持人向观众发送问候消息。

房间信息 为内置消息体,由 WebSocket 服务主动推送,包括房间状态、当前用户及参与用户列表等。部分信息也可通过 Live 提供的更新方式进行修改。

帧数据同步

当前 UI 交互状态的同步:

Five 同屏为例

// 发送本地 帧数据 (Five State)
live.sendKeyframe('five', { panoIndex: 13 })

// 接收远程 帧数据 (Five State)
live.keyframes.on('five', (newState, prevState) => {
// 可以拿最新的 `newState` 更新本地 UI 状态
})

您也可以通过 live.snapshot 属性来获取当前所有序列帧数据的"快照"。

房间信息

Live 有会话房间的概念,当您成功连接 WebSocket 服务之后等同于您作为一个用户加入了一个房间。此房间用户除了您之外还会有其他用户,您可以通过如下方式获取或更新用户信息:

// 属性:获取本地用户信息
live.selfInfo

// 属性:获取当前房间内所有用户列表
live.userList

// 方法:更新本地用户信息
live.setSelfInfo({})

// 事件:本地用户信息发生变更
live.on('selfInfoUpdate', (userInfo) => {})

// 事件:房间用户列表信息发生变更
live.on('userListUpdate', (userList) => {})

广播消息

除了帧数据和房间信息之外,还可以用事件的形式向房间内的其他用户广播消息:

live.broadcast(data /* 广播的数据 */, ['user_id_1', 'user_id_2'] /* 收到此用户的userId */)

此时,房间内用户 Id 为 user_id_1user_id_2 的用户会收到此广播消息(其他用户无感知):

live.on('broadcast', (data /* 广播的数据 */) => {})

更多的例子请查看 Live API 文档 。

事件监听

Live 提供 WebSocket 事件live 事件RTC 事件 三类异步事件的监听。

其中, WebSocket 事件live 事件 都可以通过 live.on('/*事件名*/', /*事件回调*/) 的方式监听。

比如监听 WebSocket 状态发生变更:

live.on('ws.readyStateUpdate', (readyState: WebSocketState) => {
console.log(readyState) // readyState 即是最新的 WebScoket 状态
})

WebSocket 事件

  • ws.beforeConnect(reConnect?: number): void WebSocket 完成连接之后。

  • ws.afterConnect(reConnect?: number): void WebSocket 完成连接之前。

  • ws.readyStateUpdate(readyState: WebSocketState): void WebSocket 完成状态发生变更。

WebSocket 连接状态枚举表:

状态名称 状态描述
NOTINITIALIZED 未被初始化
CONNECTING 正在连接中
OPEN 连接成功
CLOSING 关闭中
CLOSED 关闭成功

Live 前后端服务交互是基于 WebSocket 长链接的。一次带看成功进入、退出的标识由 WebSocket 的状态 OPENCLOSED体现。 因此,所有 VRTC 相关的事件处理逻辑应保证在OPEN 事件之后进行。

live 事件

  • broadcast(evtMsg: Record<string, any>, frontRequestId: string): void 接收其他用户的广播消息。

  • builtinEvent(builtinMsg: BuiltinMsg): void 接收服务端推送的内置事件消息。

  • keyframes(keyframes: Partial<Snapshot>, frontRequestId: string): void 接收其他用户的帧数据。

  • readyKeyframeSync(lastKeyframe: Partial<Snapshot>): void 表明帧同步行为已就绪。

  • selfInfoUpdate(userInfo: UserInfo, frontRequestId: string): void 自身的信息发生变更。

  • userListUpdate(userList: UserInfo[], frontRequestId: string): void 用户列信息表发生变更。

live 实例提供了很多诸如live.connect()live.broadcast()live.sendKeyframe()等方法,这些方法都是异步反馈且可能会影响房间内的其他用户。 您可以通过监听以上事件来获知这些影响。

需要注意的是 readyKeyframeSync 事件是可进行帧同步的节点标识,收到此事件后您的帧同步行为才生效。

RTC 事件

  • error(error: Error): void 异常事件。

  • initWillStart(): void 即将初始化事件。

  • inited(): void 初始化完成事件。

  • joinWillStart(): void 即将加入语音房间事件。

  • joined(): void 成功加入语音房间事件。

  • userVolumes(userVolumes: UserVolume[]): void 房间内每个说话用户的音量。

  • weakNetwork(): void 弱网提醒事件。

live.$RTC 实例需满足 RTC 协议,其事件通过 live.$RTC.on('/*事件名*/', /*事件回调*/) 方式来监听,比如监听语音房间内正在说话的用户及其音量:

live.$RTC.on('userVolumes', (userVolumes: UserVolume[]) => {
console.log(userVolumes) // userVolumes 正在说话的用户及其音量数据。
})

异常处理

  • ws.error(error: WebSocketError): void WebSocket 连接出现异常。

WebSocket 错误状态枚举表:

错误字段 错误描述 触发场景
Close 错误类型枚举参照CloseEvent 错误原因参照CloseEvent
Error
MicroAuth 麦克风授权错误 语音功能获取麦克风授权失败
DuplicateConnect 重复连接 使用相同的 WS 链接申请连接
IllegalURL 非法的 WS 链接 传入的 WS 链接不合法
Unknown 未知错误 其他未被枚举的错误原样返回
  • error(liveMsg: LiveMsg): void 服务端推送出现异常。

与 WebSocket 通信的结构体LiveMsg格式如下:

名称 类型 描述
appId string
code string 返回码,详情参照服务端 API Code 码表
command 指令 WebSocket 通信指令类型,详情请查看Live API 文档
data Record<string, any> 本条指令对应的业务数据
frontRequestId: string 前端的请求 ID,由 WS 服务原样透传回前端
message string 返回描述
requestId string 后端请求 ID
roomCode string 带看房间号
triggerUserId string 触发指令的用户 ID

当 WebSocket 推送的数据结构体不满足 LiveMsg 或者 code 值不为 SUCCESS 时会以 error 事件的形式抛出来。

  • error(error: Error): void RTC 语音出现异常。

RTC 语音不同容器或 RTC 解决方案不同,其错误信息内容可能不完全一致。

RTC 协议

语音能力需依赖 WebView/Browser 容器,即需要容器端实现 RTC 能力。

为了方便开发者接入,如视开发者中心 VRTC 服务 为主流平台提供 容器 SDKjsbridge-x

Live 通过 jsbridge-x 与 集成了容器 SDK 的客户端应用或微信小程序应用程序桥接,实现原生能力的调用。这个 jsbridge-x 实例需作为配置参数提供给createLive()

如果是 iOS/Android App(已接入如视 VRTC 容器 SDK)

import { JSBridgeApp } from '@realsee/jsbridge-x/lib/app'
import { createLive } from '@realsee/live'
import { VRWebViewRTC } from '@realsee/live/RTC/VRWebViewRTC'

const jsBridgeInstance = new JSBridgeApp()

const rtcInstance = new VRWebViewRTC({
jsBridge,
getVoiceSign: () => {},
})

const live = createLive({
rtc: rtcInstance,
getTicket: async () => '',
})

提供 RTC 实例配置参数之后,语音的连接、断开、重连等逻辑就托管给了 Live 。您可以通过 live 实例上的 $RTC 命名空间访问语音相关的状态和事件。

// 状态:用户是否成功加入语音房间
live.$RTC.joined
// 状态:用户麦克风状态
live.$RTC.micro
// 监听用户音量变化
live.$RTC.on('userVolumes', (userVolumes) => {})

TypeScript & React 支持

Live 有完整的 TypeScript GenericsReact Hooks 支持,如果您的技术栈基于 TypeScriptReact 可以参考如下方式更优雅地使用 Live

TypeScript效果演示

步骤一:新建文件 LiveReact.ts 并创建您自己的 LiveReact 实例。

import { createLiveReact } from '@realsee/live'

/** 定义帧数据快照结构 */
interface Snapshot {
/** 以 Five 状态快照为例 */
five: {
panoIndex: number
fov: number
mode: 'Panorama' | 'Model'
latitude: number
longitude: number
}
}

/** 通过 `createLiveReact()` 函数创建实例*/

const LiveReact = createLiveReact<Snapshot>({
getTicket: async () => '' /* 必须提供 */,
})

export default LiveReact

/** 如果您不喜欢 `LiveReact.LiveProvider` 这类编程习惯,可以将需要的函数"抛"出来 */
export const LiveProvider = LiveReact.LiveProvider
export const useConnect = LiveReact.useConnect
export const useKeyframe = LiveReact.useKeyframe
// export ..

步骤二:通过 LiveProviderlive 实例集成到 ReactContext 上下文环境中。

import { LiveProvider } from './LiveReact'

ReactDOM.render(
<LiveProvider>
<RootApp />
</LiveProvider>,
containter
)

步骤三:在您的 React 函数组件中使用相关 Hooks 函数。

import { useConnect } from './LiveReact'

function ReconnectBtn() {
const connect = useConnect()

return <button onClick={() => connect()}>重新连接</button>
}

Live API 文档

欢迎查看 Live API 文档 。
该文档由 TypeDoc 生成,您可以详细查看 API 使用方式、事件 Hooks 及数据结构定义等。

相关文档链接