Web SDK
TgoRTC Web (JavaScript/React) SDK,基于 LiveKit 的实时音视频通信 SDK。
安装
npm install tgortc-js-sdk
# 或
yarn add tgortc-js-sdk
# 或
pnpm add tgortc-js-sdk
依赖要求
npm install react react-dom
常用功能介绍
// 房间管理
// 加入,离开房间等
TgoRTC.instance.roomManager
// 参与者管理
// 获取本地参与者,远程参与者,要求成员等
TgoRTC.instance.participantManager
// 音频管理
// 可获取可用设备列表 切换输出输入设备等
TgoRTC.instance.audioManager
快速开始
1. 初始化 SDK
import { TgoRTC } from 'tgortc-js-sdk';
// 初始化配置
TgoRTC.instance.init({
debug: true, // 启用调试日志
mirror: false, // 启用视频镜像
});
2. 创建房间信息并加入
import { RoomInfo, RTCType } from 'tgortc-js-sdk';
// 创建房间信息
const roomInfo = new RoomInfo(
'roomName', // 房间名称
'token', // 连接 Token
'url', // 连接地址
'loginUID', // 当前用户 ID
'creatorUID' // 房间创建者 ID
);
// 可选:配置房间设置
roomInfo.maxParticipants = 9; // 房间最大人数
roomInfo.rtcType = RTCType.Video;
roomInfo.timeout = 30; // 参与者加入超时(秒)
// 加入房间
await TgoRTC.instance.roomManager.joinRoom(roomInfo, {
micEnabled: true, // 默认是否开启麦克风
cameraEnabled: true, // 默认是否打开摄像头
screenShareEnabled: false, // 默认是否屏幕共享
});
3. 监听连接状态
import { ConnectStatus } from 'tgortc-js-sdk';
const handleConnectStatus = (
roomName: string,
status: ConnectStatus,
reason: string
) => {
switch (status) {
case ConnectStatus.Connecting:
console.log('正在连接房间...');
break;
case ConnectStatus.Connected:
console.log('已连接到房间');
break;
case ConnectStatus.Disconnected:
console.log('已断开连接');
break;
case ConnectStatus.Reconnecting:
console.log('正在重连...');
break;
case ConnectStatus.Reconnected:
console.log('已重新连接到房间');
break;
}
};
// 添加监听器
TgoRTC.instance.roomManager.addConnectListener(handleConnectStatus);
// 移除监听器
TgoRTC.instance.roomManager.removeConnectListener(handleConnectStatus);
4. 获取参与者
// 获取本地参与者
const localParticipant = TgoRTC.instance.participantManager.getLocalParticipant();
// 获取所有远程参与者
const remoteParticipants = TgoRTC.instance.participantManager.getRemoteParticipants();
// 获取所有参与者(本地 + 远程)
const allParticipants = TgoRTC.instance.participantManager.getAllParticipants();
// 监听新参与者加入
TgoRTC.instance.participantManager.addNewParticipantListener((participant) => {
console.log('新参与者加入:', participant.uid);
});
5. 媒体控制和事件
媒体控制仅适用于本地参与者。
const participant = TgoRTC.instance.participantManager.getLocalParticipant();
if (participant) {
// ========== 媒体控制 ==========
// 切换麦克风(仅本地参与者生效)
await participant.setMicrophoneEnabled(true);
// 切换摄像头(仅本地参与者生效)
await participant.setCameraEnabled(true);
// 切换屏幕共享(仅本地参与者生效)
await participant.setScreenShareEnabled(true);
// 切换前后摄像头(仅本地参与者生效)
await participant.switchCamera();
// 切换扬声器(仅本地参与者生效)
await participant.toggleSpeakerphone();
// 指定扬声器开关状态(仅本地参与者生效)
await participant.setSpeakerphoneOn(true);
// 检查媒体状态
const micEnabled = participant.getMicrophoneEnabled();
const cameraEnabled = participant.getCameraEnabled();
const screenShareEnabled = participant.getScreenShareEnabled();
const speakerEnabled = participant.getSpeakerEnabled();
const cameraPosition = participant.getCameraPosition();
// ========== 事件监听 ==========
const onMicChange = (enabled: boolean) => {
console.log('麦克风:', enabled ? '开启' : '关闭');
};
const onCameraChange = (enabled: boolean) => {
console.log('摄像头:', enabled ? '开启' : '关闭');
};
const onSpeakerChange = (enabled: boolean) => {
console.log('扬声器:', enabled ? '开启' : '关闭');
};
const onScreenShareChange = (enabled: boolean) => {
console.log('屏幕共享:', enabled ? '开启' : '关闭');
};
const onSpeakingChange = (isSpeaking: boolean, audioLevel: number) => {
console.log('正在说话:', isSpeaking, '音量:', audioLevel);
};
const onConnQualityChange = (quality) => {
console.log('连接质量:', quality);
};
const onJoined = () => {
console.log('参与者已加入');
};
const onLeave = () => {
console.log('参与者已离开');
};
const onTrackPublished = () => {
console.log('轨道已发布');
};
const onTrackUnpublished = () => {
console.log('轨道已取消发布');
};
const onVideoInfoChange = (info) => {
console.log('视频信息:', info.width, 'x', info.height, info.frameRate, 'fps');
};
// 麦克风状态变化
participant.addMicrophoneStatusListener(onMicChange);
// 摄像头状态变化
participant.addCameraStatusListener(onCameraChange);
// 扬声器状态变化
participant.addSpeakerStatusListener(onSpeakerChange);
// 屏幕共享状态变化
participant.addScreenShareStatusListener(onScreenShareChange);
// 说话状态变化
participant.addSpeakingListener(onSpeakingChange);
// 连接质量变化
participant.addConnQualityListener(onConnQualityChange);
// 参与者加入房间
participant.addJoinedListener(onJoined);
// 参与者离开房间
participant.addLeaveListener(onLeave);
// 轨道发布 / 取消发布
participant.addTrackPublishedListener(onTrackPublished);
participant.addTrackUnpublishedListener(onTrackUnpublished);
// 视频信息变化(分辨率、码率等)
participant.addVideoInfoListener(onVideoInfoChange);
// ========== 移除监听器 ==========
// 页面销毁时务必移除监听器,避免内存泄漏
participant.removeMicrophoneStatusListener(onMicChange);
participant.removeCameraStatusListener(onCameraChange);
participant.removeSpeakerStatusListener(onSpeakerChange);
participant.removeScreenShareStatusListener(onScreenShareChange);
participant.removeSpeakingListener(onSpeakingChange);
participant.removeConnQualityListener(onConnQualityChange);
participant.removeJoinedListener(onJoined);
participant.removeLeaveListener(onLeave);
participant.removeTrackPublishedListener(onTrackPublished);
participant.removeTrackUnpublishedListener(onTrackUnpublished);
participant.removeVideoInfoListener(onVideoInfoChange);
}
6. 渲染视频轨道(React 组件)
import { useRef, useState, useEffect } from 'react';
import {
TgoTrackRenderer,
TgoTrackRendererHandle,
TgoParticipant,
TgoRTC
} from 'tgortc-js-sdk';
import { Track } from 'livekit-client';
function VideoView() {
const rendererRef = useRef<TgoTrackRendererHandle>(null);
const [participant, setParticipant] = useState<TgoParticipant | null>(null);
useEffect(() => {
const local = TgoRTC.instance.participantManager.getLocalParticipant();
setParticipant(local);
}, []);
return (
<TgoTrackRenderer
ref={rendererRef}
participant={participant}
source={Track.Source.Camera}
fit="cover"
mirror={true}
placeholder={<div>等待视频...</div>}
onTrackChange={(hasTrack) => {
console.log('轨道可用:', hasTrack);
}}
/>
);
}
7. 音频设备管理
// 获取音频设备
const inputDevices = await TgoRTC.instance.audioManager.getAudioInputDevices();
const outputDevices = await TgoRTC.instance.audioManager.getAudioOutputDevices();
const videoDevices = await TgoRTC.instance.audioManager.getDevices('videoinput');
// 监听设备变化
TgoRTC.instance.audioManager.addDeviceChangeListener((devices) => {
console.log('设备变化:', devices);
});
// 切换输入 / 输出设备
await TgoRTC.instance.audioManager.switchAudioInputDevice(inputDevices[0].deviceId);
await TgoRTC.instance.audioManager.switchAudioOutputDevice(outputDevices[0].deviceId);
// 切换扬声器
await TgoRTC.instance.audioManager.toggleSpeakerphone();
// 指定扬声器开关状态
await TgoRTC.instance.audioManager.setSpeakerphoneOn(true);
8. 离开房间
await TgoRTC.instance.roomManager.leaveRoom();
API 参考
TgoRTC
SDK 主入口(单例模式)。
| 属性 | 类型 | 说明 |
|---|---|---|
instance | TgoRTC | 单例实例 |
options | Options | SDK 配置 |
roomManager | TgoRoomManager | 房间管理 |
participantManager | TgoParticipantManager | 参与者管理 |
audioManager | TgoAudioManager | 音频设备管理 |
TgoRoomManager
| 方法 | 说明 |
|---|---|
joinRoom(roomInfo, options?) | 加入房间 |
leaveRoom() | 离开当前房间 |
addConnectListener(listener) | 添加连接状态监听器 |
removeConnectListener(listener) | 移除连接状态监听器 |
TgoParticipantManager
| 方法 | 说明 |
|---|---|
getLocalParticipant() | 获取本地参与者 |
getRemoteParticipants() | 获取远程参与者 |
getAllParticipants() | 获取所有参与者 |
inviteParticipant(uids) | 邀请参与者 |
removePendingParticipants(roomName, uids) | 移除未接通的待加入参与者 |
addNewParticipantListener(listener) | 监听新参与者 |
removeNewParticipantListener(listener) | 移除新参与者监听 |
TgoParticipant
媒体控制方法
| 方法 | 说明 |
|---|---|
setMicrophoneEnabled(enabled) | 启用/禁用麦克风 |
setCameraEnabled(enabled) | 启用/禁用摄像头 |
setScreenShareEnabled(enabled) | 启用/禁用屏幕共享 |
switchCamera() | 切换前后摄像头 |
toggleSpeakerphone() | 切换扬声器 |
setSpeakerphoneOn(on) | 设置扬声器开关 |
状态获取方法
| 方法 | 说明 |
|---|---|
getMicrophoneEnabled() | 获取麦克风状态 |
getCameraEnabled() | 获取摄像头状态 |
getScreenShareEnabled() | 获取屏幕共享状态 |
getSpeakerEnabled() | 获取扬声器状态 |
getCameraPosition() | 获取当前摄像头方向 |
getVideoTrack(source?) | 获取视频轨道 |
getAudioLevel() | 获取音频电平 (0-1) |
getIsSpeaking() | 获取是否正在说话 |
事件监听方法
| 方法 | 说明 |
|---|---|
addMicrophoneStatusListener(listener) | 监听麦克风状态 |
addCameraStatusListener(listener) | 监听摄像头状态 |
addSpeakerStatusListener(listener) | 监听扬声器状态 |
addScreenShareStatusListener(listener) | 监听屏幕共享状态 |
addSpeakingListener(listener) | 监听说话状态 |
addCameraPositionListener(listener) | 监听摄像头方向变化 |
addConnQualityListener(listener) | 监听连接质量 |
addJoinedListener(listener) | 监听参与者加入 |
addLeaveListener(listener) | 监听参与者离开 |
addTrackPublishedListener(listener) | 监听轨道发布 |
addTrackUnpublishedListener(listener) | 监听轨道取消发布 |
addVideoInfoListener(listener) | 监听视频信息变化 |
remove...Listener(listener) | 移除对应监听器 |
属性
| 属性 | 类型 | 说明 |
|---|---|---|
uid | string | 参与者 ID |
isLocal | boolean | 是否为本地参与者 |
hasJoined | boolean | 是否已加入房间 |
isJoined | boolean | 是否已加入房间 |
currentVideoInfo | VideoInfo | 当前视频信息 |
TgoTrackRenderer(React 组件)
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
participant | TgoParticipant | null | - | 要渲染的参与者 |
source | Track.Source | Camera | 轨道来源类型 |
fit | 'cover' | 'contain' | 'fill' | 'cover' | 视频填充模式 |
mirror | boolean | SDK 设置 | 是否镜像 |
className | string | - | 自定义类名 |
style | React.CSSProperties | - | 自定义样式 |
placeholder | ReactNode | - | 无视频时的占位符 |
onTrackChange | (hasTrack: boolean) => void | - | 轨道变化回调 |
| Ref 方法 | 说明 |
|---|---|
refresh() | 手动刷新视频轨道 |
setParticipant(participant) | 更新参与者 |
枚举类型
ConnectStatus
enum ConnectStatus {
Connecting = 'connecting', // 连接中
Connected = 'connected', // 已连接
Reconnecting = 'reconnecting', // 重连中
Reconnected = 'reconnected', // 已重连
Disconnected = 'disconnected', // 已断开
}
说明:
ConnectStatus 枚举完整包含以上 5 个状态。
按当前 JS SDK 实现,TgoRoomManager.addConnectListener(...) 目前实际会回调
Connected、Disconnected、Reconnecting、Reconnected 这 4 种状态;
Connecting 虽然在枚举中定义了,但当前 TgoRoomManager 源码里还没有主动派发这个状态。
RTCType
enum RTCType {
Audio = 'audio', // 仅音频
Video = 'video', // 音视频
}
TgoConnectionQuality
enum TgoConnectionQuality {
Unknown = 'unknown', // 未知
Excellent = 'excellent', // 优秀
Good = 'good', // 良好
Poor = 'poor', // 较差
Lost = 'lost', // 丢失
}
TgoCameraPosition
enum TgoCameraPosition {
Front = 'front', // 前置摄像头
Back = 'back', // 后置摄像头
}
RoomInfo 类
房间信息类,用于配置房间连接。
class RoomInfo {
roomName: string; // 房间名称
token: string; // LiveKit Token
url: string; // LiveKit 服务器地址
loginUID: string; // 当前用户 ID
creatorUID: string; // 房间创建者 ID
maxParticipants: number; // 最大参与者数(默认 2)
rtcType: RTCType; // 通话类型(默认 Audio)
isP2P: boolean; // 是否点对点(默认 true)
uidList: string[]; // 参与者列表
timeout: number; // 超时时间(默认 30 秒)
// 方法
getP2PToUID(): string; // 获取 P2P 目标用户
isCreator(): boolean; // 是否为创建者
}
配置选项
interface Options {
mirror: boolean; // 视频镜像(默认 false)
debug: boolean; // 调试模式(默认 true)
}
TgoAudioManager
| 方法 | 说明 |
|---|---|
getAudioInputDevices() | 获取麦克风设备列表 |
getAudioOutputDevices() | 获取音频输出设备列表 |
getDevices(kind) | 获取指定类型设备列表 |
switchAudioInputDevice(deviceId, setAsDefault?) | 切换麦克风设备 |
switchAudioOutputDevice(deviceId, setAsDefault?) | 切换音频输出设备 |
toggleSpeakerphone() | 切换扬声器状态 |
setSpeakerphoneOn(on) | 设置扬声器状态 |
addDeviceChangeListener(listener) | 监听设备变化 |
removeDeviceChangeListener(listener) | 移除设备变化监听 |
属性
| 属性 | 类型 | 说明 |
|---|---|---|
isSpeakerOn | boolean | 当前扬声器状态 |
currentAudioInputDeviceId | string | null | 当前输入设备 ID |
currentAudioOutputDeviceId | string | null | 当前输出设备 ID |
最佳实践
使用 useRef 保存参与者引用
在 React 中,使用 useRef 保存 participant 引用,避免在事件监听器中使用过时的闭包:
import { useRef, useEffect, useCallback } from 'react';
import { TgoRTC, TgoParticipant } from 'tgortc-js-sdk';
function CallPage({ roomInfo }) {
const localParticipantRef = useRef<TgoParticipant | null>(null);
const cleanupRef = useRef<(() => void) | null>(null);
useEffect(() => {
const joinRoom = async () => {
await TgoRTC.instance.roomManager.joinRoom(roomInfo, {
micEnabled: true,
cameraEnabled: true,
});
// 保存参与者引用
const participant = TgoRTC.instance.participantManager.getLocalParticipant();
localParticipantRef.current = participant;
// 添加监听器并保存清理函数
if (participant) {
const onMicChange = (enabled: boolean) => console.log('Mic:', enabled);
const onCameraChange = (enabled: boolean) => console.log('Camera:', enabled);
participant.addMicrophoneStatusListener(onMicChange);
participant.addCameraStatusListener(onCameraChange);
cleanupRef.current = () => {
participant.removeMicrophoneStatusListener(onMicChange);
participant.removeCameraStatusListener(onCameraChange);
};
}
};
joinRoom();
return () => {
// 清理监听器
cleanupRef.current?.();
// 离开房间
TgoRTC.instance.roomManager.leaveRoom();
};
}, [roomInfo]);
const handleMicToggle = useCallback(async () => {
const participant = localParticipantRef.current;
if (participant) {
const current = participant.getMicrophoneEnabled();
await participant.setMicrophoneEnabled(!current);
}
}, []);
return <button onClick={handleMicToggle}>切换麦克风</button>;
}
监听远程参与者
使用 addNewParticipantListener 监听新参与者加入,并为其添加事件监听:
const participantManager = TgoRTC.instance.participantManager;
// 监听新参与者加入
participantManager.addNewParticipantListener((participant) => {
console.log('新参与者:', participant.uid);
// 监听远程参与者事件
participant.addJoinedListener(() => {
console.log(`${participant.uid} 已加入`);
});
participant.addLeaveListener(() => {
console.log(`${participant.uid} 已离开`);
});
participant.addCameraStatusListener((enabled) => {
console.log(`${participant.uid} 摄像头:`, enabled);
});
});
处理未接通参与者
当前 JS SDK 没有 participant.addTimeoutListener(...) 这类参与者级超时事件。
如果业务侧已经知道某些被邀请用户未接通,可以通过 TgoParticipantManager.removePendingParticipants(...)
把这些尚未加入房间的参与者从当前列表中移除:
const roomName = roomInfo.roomName;
const missedUids = ['user_b', 'user_c'];
TgoRTC.instance.participantManager.removePendingParticipants(
roomName,
missedUids
);