这篇档介绍如何将 TUIRoomKit 集成到现有的 React 项目中,同时介绍如何对 TUIRoomKit 的样式、布局及功能进行自定义修改。
二、开通服务
请参考 开通服务 领取 TUIRoomKit 体验版或开通 TUIRoomKit 正式版,并在 应用管理 页面获取以下信息:
·SDKAppID: 应用标识,腾讯云基于 SDKAppID 完成计费统计。
·SDKSecretKey: 应用密钥,用于初始化配置文件的密钥信息。
三、环境准备
·Node.js: ≥ 18.19.1 (推荐使用 LTS 版本)。
·React: ≥ 18.2.0。
·现代浏览器:支持 WebRTC APIs 的现代浏览器。
·设备:摄像头、麦克风、扬声器。
五、步骤1:安装项目依赖
在你的业务项目中安装以下依赖。
npmpnpmyarnnpm install @tencentcloud/roomkit-web-react tuikit-atomicx-react @tencentcloud/uikit-base-component-react @tencentcloud/universal-apipnpm install @tencentcloud/roomkit-web-react tuikit-atomicx-react @tencentcloud/uikit-base-component-react @tencentcloud/universal-apiyarn add @tencentcloud/roomkit-web-react tuikit-atomicx-react @tencentcloud/uikit-base-component-react @tencentcloud/universal-api
六、步骤2:引用 TUIRoomKit 组件
import { UIKitProvider } from '@tencentcloud/uikit-base-component-react';import { ConferenceMainView } from '@tencentcloud/roomkit-web-react';export default function App() { return ( <UIKitProvider theme="light" language="zh-CN"> <ConferenceMainView /> </UIKitProvider> );}
七、步骤3:登录
登录是使用 TUIRoomKit 一切功能的基础。通常建议在你的业务系统完成鉴权(用户登录你的 Web 页面)后,立即调用 conference.login 方法登录 TUIRoomKit。调用 conference.login 完成鉴权后,建议同步调用 conference.setSelfInfo 来设置当前用户的展示昵称和头像,这些信息将在随后的参会者视频区域和成员列表中展示。
注意:在配置代码中,请务必填入生成的 UserSig。在正式的生产环境中,建议在你的服务端生成 UserSig,在需要 UserSig 时由你的客户端向业务服务器发起请求获取动态 UserSig 来进行鉴权。详见 正式运行阶段如何计算 UserSig。
import { useEffect } from 'react';import { conference } from '@tencentcloud/roomkit-web-react';// 注意:以下参数请替换为你真实的业务数据和控制台获取的 SDKAppIDconst SDKAppID = 0;const userId = 'your_user_id';const userSig = 'your_dynamic_user_sig';const userName = '用户展示昵称';function LoginComponent() { useEffect(() => { const init = async () => { try { // 1. 执行 SDK 登录 await conference.login({ sdkAppId: SDKAppID, userId, userSig, }); // 2. (可选)设置个人信息 await conference.setSelfInfo({ userName, avatarUrl: 'https://your-avatar-url.com/image.png', }); } catch (error) { console.error('TUIRoomKit 登录失败:', error); } }; init(); }, []); return null;}
八、接入问题:登录与进房分属不同路由页面如何监听登录成功的状态?
当登录页面与进房页面是两个独立路由时,进房页面加载时 conference.login 登录逻辑可能尚未执行。推荐通过 useEffect 监听 loginUserInfo?.userId,该字段非空即视为 TUIRoomKit 登录成功。
import { useEffect } from 'react';import { useLoginState } from 'tuikit-atomicx-react/room';import { conference } from '@tencentcloud/roomkit-web-react';function RoomPage() { const { loginUserInfo } = useLoginState(); useEffect(() => { if (loginUserInfo?.userId) { conference.createAndJoinRoom({ roomId: '123456' }); } }, [loginUserInfo?.userId]); return null;}
九、步骤4:创建会议
创建会议所需要的房间号(roomId)是会议的核心标识,由你的业务系统自行生成与维护(需保证全局唯一)。请根据你的实际业务场景,选择适合的创建房间的方式:
十、场景一:客户端发起快速会议
适用场景:用户在客户端点击"快速会议",需要立即创建房间并加入(如临时沟通、IM 聊天内发起会议)。
实现方式:由客户端生成或向业务后台申请一个唯一的房间号,随后由发起人调用 conference.createAndJoinRoom 创建并直接进入该房间。
import { conference } from '@tencentcloud/roomkit-web-react';const startQuickMeeting = async () => { // 1. 客户端生成一个唯一的 roomId const myRoomId = `room_${Date.now()}`; // 2. 建房并直接加入 await conference.createAndJoinRoom({ roomId: myRoomId, options: { roomName: '我的快速会议', }, });};
十一、场景二:客户端预约会议
适用场景:适用于需要在未来特定时间召开的会议(如团队周会、线上培训等)。用户可在客户端提前设定会议标题、时间及受邀参会成员。
实现方式:由客户端生成或向业务后台申请一个唯一的房间号,并配合会议时间等参数调用 scheduleRoom 接口提交预定。预定成功后,会议信息将同步至参与者的会议列表中。更多客户端预订会议能力请参考 无 UI 集成 > 预订房间。
import { useRoomState } from 'tuikit-atomicx-react/room';function ScheduleDemo() { const { scheduleRoom } = useRoomState(); const createSchedule = async () => { try { // roomId 限制:字符串类型,必传参数,建议由业务后台生成保证 roomId 唯一性。 const roomId = '123456'; // 注意:时间戳单位必须为 **秒** (Date.getTime() 获取的是毫秒,需除以 1000) const startTime = Math.floor(new Date().getTime() / 1000) + 3600; // 1小时后开始 const duration = 1800; // 30分钟 const options = { roomName: '产品需求评审会', scheduleStartTime: startTime, // 单位:秒 scheduleEndTime: startTime + duration, // 单位:秒 scheduleAttendees: ['userA', 'userB'], // 邀请参会成员ID列表 password: '123', // 可选:设置入会密码 }; await scheduleRoom({ roomId, options }); } catch (error) { console.error('预定失败', error); } }; return <button onClick={createSchedule}>预约会议</button>;}
十二、场景三:服务端创建会议
适用场景:政务、医疗、大型企业 OA 等强管控场景。
实现方式:会议的创建动作完全由你的业务服务端发起,调用腾讯云的 服务端 REST API 创建房间。
POST /v4/room_engine_http_srv/create_room{ "roomId": "your-room-id", "roomName": "会议名称", "startTime": 1710000000, "endTime": 1710003600, "invitees": ["userId1", "userId2"]}
十三、步骤5:加入会议
参会成员加入房间时,请根据业务情况选择适合的加入房间的方式。
十四、场景一:房间已存在,已知 roomId 直接加入
适用场景:房间已经被发起人或服务端明确创建,参会人收到了发起人分享的房间号或者会议邀请链接。
实现方式:参会人输入房间号或客户端通过邀请链接解析出 roomId 后,仅需调用 conference.joinRoom 即可加入房间。
import { conference } from '@tencentcloud/roomkit-web-react';const joinExistingMeeting = async (sharedRoomId: string) => { await conference.joinRoom({ roomId: sharedRoomId, });};
十五、场景二:从房间列表加入会议
适用场景:适用于已通过"客户端预约"或"服务端创建"的会议。用户可进入"会议列表"页面,查看自己预定或受邀参与的会议,并快速点击加入。
实现方式:通过 useRoomState 提供的 getScheduledRoomList 接口拉取当前用户的预约会议列表,并将其渲染至界面。当用户点击对应会议时,获取该项预约记录对应的 roomId 并调用 conference.joinRoom 即可完成进房操作。
import { useState, useEffect } from 'react';import { conference } from '@tencentcloud/roomkit-web-react';import { useRoomState, useLoginState } from 'tuikit-atomicx-react/room';interface RoomInfo { roomId: string; roomName?: string;}export default function ScheduledRoomList() { const { getScheduledRoomList } = useRoomState(); const { loginUserInfo } = useLoginState(); const [roomList, setRoomList] = useState<RoomInfo[]>([]); // 1. 监听登录状态,确保鉴权就绪后再拉取会议列表 useEffect(() => { if (!loginUserInfo?.userId) return; getScheduledRoomList({ cursor: '' }) .then(({ scheduledRoomList }) => setRoomList(scheduledRoomList || [])) .catch((error) => console.error('获取预约会议列表失败:', error)); }, [loginUserInfo?.userId]); // 2. 点击加入房间 const handleJoinRoom = async (roomId: string) => { try { await conference.joinRoom({ roomId }); } catch (error) { console.error(`加入会议失败 (${roomId}):`, error); } }; return ( <div> <h3>我的预约会议</h3> {roomList.length > 0 ? ( <ul style={{ padding: 0, listStyle: 'none' }}> {roomList.map((room) => ( <li key={room.roomId} style={{ display: 'flex', justifyContent: 'space-between', padding: '10px', borderBottom: '1px solid #eee' }}> <div style={{ display: 'flex', flexDirection: 'column', fontSize: '14px', color: '#666' }}> <b style={{ fontSize: '16px', color: '#333' }}>{room.roomName || '未命名会议'}</b> <span>房间号: {room.roomId}</span> </div> <button onClick={() => handleJoinRoom(room.roomId)} style={{ background: '#006eff', color: '#fff', border: 'none', padding: '6px 12px', borderRadius: '4px', cursor: 'pointer' }} > 加入会议 </button> </li> ))} </ul> ) : ( <div>暂无待参加的预约会议</div> )} </div> );}
十六、场景三:不确定房间是否已存在,需要直接进入
适用场景:双向对等发起的场景(如在线问诊、1v1 视频客服)。无法预先确定房间是否已创建。
实现方式:双方统一使用共知的业务单据号(如订单号)作为 roomId,并统一调用 conference.createAndJoinRoom 加入房间。
import { conference } from '@tencentcloud/roomkit-web-react';const enterDualMeeting = async (bizOrderId: string) => { // 双方无需判断房间是否已经创建 SDK 内部自动处理建房与进房逻辑 await conference.createAndJoinRoom({ roomId: bizOrderId, options: { roomName: `业务沟通:${bizOrderId}`, }, });};
注意:说明:
注意:conference.createAndJoinRoom 接口内部封装了"不存在则创建(成为房主),已存在则加入(成为普通参会者)"的逻辑,完美解决高并发下的状态冲突问题。
十七、步骤6:离开与解散房间
TUIRoomKit 已在界面上内置了离开和解散房间的功能,用户可直接点击界面上的「离开房间」或「解散房间」按钮完成操作。
如果你需要在客户端通过代码主动触发离开或解散,可调用以下接口。
十八、场景一:主动离开房间
参与者和房主均可调用 leaveRoom() 离开会议,调用后不影响其他成员,房间继续存在。
import { conference } from '@tencentcloud/roomkit-web-react';await conference.leaveRoom();
注意:说明:
注意:房主离开房间或关闭网页,不会自动解散房间,其他参会成员可继续正常使用 TUIRoomKit 能力,系统会在会议结束时间后 6 小时、且房间内人数为 0 时自动回收房间资源。
十九、场景二:主动解散房间
房主调用 endRoom() 后,房间内所有成员均会收到房间已解散的通知。
import { conference } from '@tencentcloud/roomkit-web-react';await conference.endRoom();
注意:endRoom() 必须由房主在成功进入房间后才能调用。非房主身份或在尚未进入房间的状态下调用会报错。
20、步骤7:监听房间状态
在真实的音视频会议场景中,房间状态可能会因为各种不可控因素发生变化(例如:房主主动解散了会议、账号在其他设备登录、或者网络异常导致进房失败)。
TUIRoomKit 内部会自动处理底层音视频资源的销毁和 UI 提示,但界面的路由跳转必须由你的业务层来接管。因此,强烈建议你在会议组件挂载时注册状态监听,并在组件卸载时及时销毁监听。
import { useEffect } from 'react';import { ConferenceMainView, conference, RoomEvent } from '@tencentcloud/roomkit-web-react';export default function MeetingRoom() { useEffect(() => { const backToHome = () => {}; const backToLogin = () => {}; conference.on(RoomEvent.ROOM_DISMISS, backToHome); conference.on(RoomEvent.ROOM_LEAVE, backToHome); conference.on(RoomEvent.ROOM_ERROR, backToHome); conference.on(RoomEvent.KICKED_OUT, backToHome); conference.on(RoomEvent.KICKED_OFFLINE, backToLogin); conference.on(RoomEvent.USER_SIG_EXPIRED, backToLogin); return () => { conference.off(RoomEvent.ROOM_DISMISS, backToHome); conference.off(RoomEvent.ROOM_LEAVE, backToHome); conference.off(RoomEvent.ROOM_ERROR, backToHome); conference.off(RoomEvent.KICKED_OUT, backToHome); conference.off(RoomEvent.KICKED_OFFLINE, backToLogin); conference.off(RoomEvent.USER_SIG_EXPIRED, backToLogin); }; }, []); return <ConferenceMainView />;}
| 事件 | 触发时机 | 推荐处理 |
| RoomEvent.ROOM_DISMISS | 房间被解散,对所有成员触发 | 返回首页或会议列表 |
| RoomEvent.ROOM_LEAVE | 用户点击 TUIRoomKit 界面上的「离开」按钮 | 返回首页或会议列表 |
| RoomEvent.ROOM_ERROR | 进房失败或房间内发生未处理的错误 | 返回首页或会议列表 |
| RoomEvent.KICKED_OUT | 被房主踢出房间 | 返回首页或会议列表 |
| RoomEvent.KICKED_OFFLINE | 同一账号在其他设备登录,当前设备被强制下线 | 跳转登录页 |
| RoomEvent.USER_SIG_EXPIRED | UserSig 已过期 | 跳转登录页 |
21、启动项目
npmpnpmyarnnpm run devpnpm run devyarn run dev
启动成功后,请在浏览器中打开调试地址(通常为 http://localhost:5173)访问应用。你将看到如下所示的会议界面:
22、下一步
在完成基础集成后,你可以根据业务需求进一步定制 UI 界面。
23、配置主题及语言
通过配置 App.tsx 中 UIKitProvider 的入参,修改主题及语言的默认值。更多自定义主题及语言请参考 UI 自定义 > 主题及语言。
| UIKitProvider 参数 | 可选值 | 默认值 |
| theme | "light" | "dark" | "light" |
| language | "zh-CN" | "en-US" | "en-US" |
import { UIKitProvider } from '@tencentcloud/uikit-base-component-react';export default function App() { return ( <UIKitProvider theme="light" language="zh-CN"> {/* 路由或页面内容 */} </UIKitProvider> );}
24、配置用户联系人列表
TUIRoomKit 内置的邀请参会和预定会议选人组件,底层默认依赖腾讯云 IM 的用户关系链(好友列表)。如果你希望在这些组件中展示你企业内部的组织架构或好友列表,请先通过服务端 REST API 将你的业务联系人同步至腾讯云 IM 系统中:
1. 使用 账号管理 > 导入多个账号 REST API 接口批量导入用户账号。
2. 使用 好友管理 > 导入好友 REST API 接口批量导入用户关系链。
25、修改房间分享链接
TUIRoomKit 默认使用当前页面地址作为房间分享链接。
如你需要修改链接地址,可调用 conference.setFeatureConfig 更新分享链接。
import { conference } from '@tencentcloud/roomkit-web-react';// 在 conference.createAndJoinRoom / conference.joinRoom 成功之后立即调用,确保 roomId 已知const roomId = '123456';conference.setFeatureConfig({ shareLink: `https://your-domain.com/room?roomId=${roomId}`,});
26、设置视频布局及挂件
TUIRoomKit 目前支持九宫格、侧边栏及顶部栏三种流布局,默认为九宫格布局,开发者可调用 conference.setFeatureConfig 修改默认视频布局。
import { RoomLayoutTemplate } from 'tuikit-atomicx-react/room';import { conference } from '@tencentcloud/roomkit-web-react';// 方案一:修改默认视频流布局为侧边栏布局conference.setFeatureConfig({ layoutTemplate: RoomLayoutTemplate.SidebarLayout });// 方案二:修改默认视频流布局为顶部栏布局conference.setFeatureConfig({ layoutTemplate: RoomLayoutTemplate.CinemaLayout });
TUIRoomKit 默认内置以下视频流挂件,如你需要自定义视频流挂件,请参考 UI 自定义 > 视频布局及挂件 。
28、创建房间的用户(房主)关闭网页或异常退出后,会议会立即结束吗?
不会。 当房主关闭浏览器或因网络异常离开页面时,并不会导致会议立即解散。会议将持续运行,其他在房成员仍可正常进行会议互动。
为节省资源,建议在会议实际结束时,通过以下任一方式主动销毁房间:
·界面操作:房主点击 TUIRoomKit 界面上的「解散房间」按钮;
·客户端 API:调用 conference.endRoom() 方法;
·服务端 API:通过 REST API 进行远程销毁。
注意:若未主动解散,系统会在会议结束时间后 6 小时,且房间内人数为 0 时自动回收资源。
29、多个设备能否使用同一个 userId 同时加入同一场会议?
不支持。 TUIRoomKit 不允许同一 userId 在多个设备上同时进入同一房间。
·互踢机制:若后到的设备使用相同 userId 尝试进房,先前已在房内的设备会被强制下线(踢出)。
·解决方案:如需实现多端(如手机、PC)同时加入会议,请确保为每个设备分配唯一的 userId。
30、在本地开发时使用正常,但部署到线上环境后无法正常采集用户的摄像头或麦克风设备?
·原因分析:浏览器出于安全和隐私保护的考虑,对音视频设备(麦克风、摄像头)的采集有着严格限制。只有在安全环境下,采集操作才会被允许。安全环境协议包括:https://、localhost、file:// 等。HTTP 协议被视为不安全,浏览器会默认禁止访问媒体设备。
·解决方案:若你在本地(localhost)测试一切正常,但部署后出现采集失败,请立即检查你的网页是否部署在 HTTP 协议上。必须使用 HTTPS 协议部署你的网页,并确保具备有效的安全证书。
·相关资源:更多关于 URL 域名及协议的限制详情,请参见 URL 域名及协议限制说明。
31、是否支持使用 iframe 集成?
支持。使用 iframe 集成 TUIRoomKit 时, 需要在 iframe 标签中配置 allow 属性以授予必要的浏览器权限(麦克风、摄像头、屏幕共享、全屏等),示例如下:
// 开启麦克风、摄像头、屏幕分享、全屏权限<iframe src="https://your-domain.com/index.html" allow="microphone; camera; display-capture; display; fullscreen;">
更多信息可参考 内嵌页面 (iframe)。
32、是否支持设置内网代理?
支持。请参考如下指引设置内网代理参数。更多内网代理信息请参考 应对防火墙受限。
// 请在进房前设置内网代理参数import TUIRoomEngine from '@tencentcloud/tuiroom-engine-js';import { useRoomEngine } from 'tuikit-atomicx-react/room';const roomEngine = useRoomEngine();TUIRoomEngine.once('ready', () => { const trtcCloud = roomEngine.instance?.getTRTCCloud(); trtcCloud.callExperimentalAPI(JSON.stringify({ api: 'setNetworkProxy', params: { websocketProxy: "wss://proxy.example.com/ws/", turnServer: [{ url: '14.3.3.3:3478', username: 'turn', credential: 'turn', }], iceTransportPolicy: 'relay', }, }));});
33、是否可以直接修改 TUIRoomKit 的底层源码?
TUIRoomKit 已经为你提供了极其丰富的 UI 自定义能力,包括 自定义主题及语言、界面微调、自定义视频布局及挂件、水印配置等,能够满足绝大部分业务的个性化视觉与交互需求。
我们非常不推荐你进行源码导出。导出源码意味着你的项目将脱离 TUIRoomKit 的常规 npm 版本升级路径。你不仅需要自行承担后续极高的代码维护成本,也将无法直接通过更新版本来享受我们后续推出的新功能和底层音视频引擎的性能优化。
·推荐方案:请优先查阅 UI 自定义类文档探索标准自定义方案。
·需求反馈:如果现有的自定义接口确实无法满足你的特定业务诉求,请不要急于修改源码。欢迎随时 联系我们 提交你的需求场景,我们将进行评估并致力于为你提供更稳定、合理的标准 API 支持。
如果你已经充分评估了上述高昂的维护风险,且业务确实存在极特殊的、必须破坏底层结构的深度定制需求,可按照以下步骤导出源码:
React1. 执行源码导出脚本,默认拷贝路径为 ./src/components/RoomKit node ./node_modules/@tencentcloud/roomkit-web-react/scripts/eject.js2. 根据脚本提示确认是否要将 TUIRoomKit 源码拷贝到 ./src/components/RoomKit 目录。如你需要自定义拷贝目录请输入 'y', 否则输入'n'。3. 源码导出后,在你指定的项目路径中会新增 TUIRoomKit 源码。此时,你需要手动将 ConferenceMainView 组件及 conference 对象的引用从 npm 包地址更改为 RoomKit 源码的相对路径地址。- import { ConferenceMainView, conference } from '@tencentcloud/roomkit-web-react';// 替换引用路径为 TUIRoomKit 源码的真实路径+ import { ConferenceMainView, conference } from './components/RoomKit/index.ts';4. 配置 ESLint 校验如果你导出 TUIRoomKit 源码后运行项目出现 ESLint 报错,你可以在 .eslintignore 文件中添加 RoomKit 文件夹忽略 ESLint 检测。// 请替换为 TUIRoomKit 源码真实路径src/components/RoomKit
34、联系我们
如果你在接入或使用过程有任何疑问或者建议,欢迎 联系我们 提交反馈。