本篇文档旨在指导开发者在标准会议无 UI 集成方案中实现视频画面渲染、布局切换、屏幕共享画面展示、移动端布局适配以及视频画面挂件定制。您可以直接使用
RoomView 组件承载标准会议的视频区域,也可以通过 layoutTemplate、participantViewUI 插槽和 stream-double-click 事件组合出符合业务场景的视频布局体验。RoomView 只负责视频流画面容器和布局编排,不包含完整会议页面、成员列表、底部工具栏或业务弹窗。会议页面通常需要将 RoomView 与房间管理、设备控制、成员管理等能力组合使用。
前提条件
用户已经通过 useLoginState 完成登录鉴权,请参考 接入概览 文档。
用户已经通过 useRoomState 进入标准会议房间,请参考 房间管理 文档。
承载
RoomView 的父容器必须具备明确的宽高,否则视频区域可能无法正常计算布局。功能介绍
RoomView 是标准会议的视频布局容器,用于渲染成员摄像头流和屏幕共享流。开发者主要通过布局入参选择画面排列方式,通过插槽定制视频挂件,通过事件响应用户对视频画面的操作。RoomView 组件接口
类型 | 名称 | 说明 |
入参 | layoutTemplate?: RoomLayoutTemplate | 视频布局模板。默认值为 RoomLayoutTemplate.GridLayout。 |
插槽 | participantViewUI | 自定义视频画面挂件,插槽参数为 { participant, streamType }。 |
事件 | stream-double-click | 用户双击视频画面时触发,事件参数为 { participant, streamType }。 |
内置布局能力总览
标准会议中,
RoomView 通过 layoutTemplate 属性控制布局。布局 | 枚举值 | 适用端 | 推荐场景 | 表现说明 |
宫格布局 | RoomLayoutTemplate.GridLayout | PC Web | 多人讨论、日常会议、视频面试 | 默认布局。最多按 3 x 3 展示当前页画面,超过 9 路时支持翻页。 |
顶部栏布局 | RoomLayoutTemplate.CinemaLayout | PC Web | 演示、培训、屏幕共享 | 主画面居中突出,其他成员在顶部栏展示。 |
侧边栏布局 | RoomLayoutTemplate.SidebarLayout | PC Web | 演讲、汇报、主讲人模式 | 主画面居中突出,其他成员在侧边栏展示。 |
移动端布局 | RoomLayoutTemplate.MobileLayout | H5 | 移动端会议页面 | 支持屏幕分享双指放大、滑动分页、主画面、悬浮画面和懒加载。 |
核心参数说明
参数 | 说明 | 常见用途 |
participant | 当前视频画面对应的成员对象,包含 userId、userName、nameCard、role、microphoneStatus、cameraStatus 等状态。 | 展示昵称、角色标识、麦克风/摄像头状态,或判断当前画面对应的操作目标。 |
streamType | 当前视频画面的流类型,用于区分摄像头流和屏幕共享流。 | 摄像头流展示成员挂件;屏幕共享流展示“正在共享屏幕”等提示,并避免展示不适合的摄像头状态 UI。 |
场景一:渲染视频区域
完成登录和进房后,如需在会议页面中展示标准会议的视频画面,可直接渲染
RoomView。这是接入视频布局能力的最小使用方式。实现思路
为视频区域准备一个有明确宽高的容器,并在其中渲染
RoomView。如果不传入 layoutTemplate,默认使用 RoomLayoutTemplate.GridLayout。PC Web 示例代码
<template><div class="room-view-wrapper"><RoomView :layout-template="RoomLayoutTemplate.GridLayout" /></div></template><script setup lang="ts">import { RoomLayoutTemplate, RoomView } from 'tuikit-atomicx-vue3/room';</script><style scoped>/* 必须为 RoomView 父容器明确设置宽高 */.room-view-wrapper { width: 100%; height: 100%; }</style>
H5 示例代码
<template><div class="room-view-wrapper"><RoomView :layout-template="RoomLayoutTemplate.MobileLayout" /></div></template><script setup lang="ts">import { RoomLayoutTemplate, RoomView } from 'tuikit-atomicx-vue3/room';</script><style scoped>/* 必须为 RoomView 父容器明确设置宽高 */.room-view-wrapper { width: 100%; height: 100%; }</style>
注意事项
RoomView 会占满父容器,请确保父容器设置了明确的 width 和 height。RoomView 不负责创建或加入房间,也不负责打开本地摄像头或麦克风。设备打开逻辑请参考设备及网络。场景二:自定义视频区域挂件
如果您需要在视频画面上展示昵称、头像、角色标识、麦克风状态、音量波动、屏幕共享标识或业务标签,可以使用
participantViewUI 插槽。
实现思路
RoomView 会在每个视频画面上透传 participant 和 streamType。业务侧可以基于成员状态渲染挂件 UI,但不需要接管视频流播放逻辑。插槽参数
参数 | 类型 | 说明 |
participant | RoomParticipant | 当前视频画面对应的成员,包含 userId、userName、nameCard、role、microphoneStatus 等状态。 |
streamType | VideoStreamType | 当前画面类型,常见值为摄像头流和屏幕共享流。 |
示例代码
会议页面示例:
<template><RoomView :layout-template="currentLayout"><template #participantViewUI="{ participant, streamType }"><ParticipantViewUI:participant="participant":stream-type="streamType"/></template></RoomView></template><script setup lang="ts">import { ref } from 'vue';import {RoomLayoutTemplate,RoomView,} from 'tuikit-atomicx-vue3/room';import ParticipantViewUI from './ParticipantViewUI.vue';const currentLayout = ref(RoomLayoutTemplate.GridLayout);</script>
ParticipantViewUI.vue 示例:<template><divclass="participant-view-ui":class="{ 'camera-off': shouldShowCameraPlaceholder }"><div v-if="shouldShowCameraPlaceholder" class="camera-placeholder">{{ displayName }}</div><div class="participant-info"><span class="user-name">{{ displayName }}</span><span v-if="isOwner && isCameraStream" class="role-tag">房主</span><span v-if="isScreenStream" class="stream-tag">{{ displayName }} 正在屏幕分享</span><span v-else class="device-tag">{{ isMicrophoneOn ? '麦克风已开' : '麦克风已关' }}</span></div></div></template><script setup lang="ts">import { computed } from 'vue';import {DeviceStatus,RoomParticipantRole,VideoStreamType,} from 'tuikit-atomicx-vue3/room';import type { RoomParticipant } from 'tuikit-atomicx-vue3/room';const props = defineProps<{participant: RoomParticipant;streamType: VideoStreamType;}>();const displayName = computed(() => props.participant.nameCard || props.participant.userName || props.participant.userId);const isOwner = computed(() => props.participant.role === RoomParticipantRole.Owner && props.streamType === VideoStreamType.Camera);const isCameraStream = computed(() => props.streamType === VideoStreamType.Camera);const isScreenStream = computed(() => props.streamType === VideoStreamType.Screen);const isMicrophoneOn = computed(() => props.participant.microphoneStatus === DeviceStatus.On);const shouldShowCameraPlaceholder = computed(() => isCameraStream.value && props.participant.cameraStatus !== DeviceStatus.On);</script><style scoped>/* 必须设置 pointer-events 属性值为 none,否则会拦截底层视频画面的双击、拖拽交互! */.participant-view-ui { position: absolute; inset: 0; pointer-events: none; }.participant-view-ui.camera-off { background: #1f2937; }.camera-placeholder { display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; color: #fff; font-size: 16px; }.participant-info { position: absolute; left: 8px; bottom: 8px; display: flex; align-items: center; gap: 6px; max-width: calc(100% - 16px); padding: 4px 8px; color: #fff; background: rgb(0 0 0 / 50%); border-radius: 12px; }.user-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }</style>
推荐做法
建议区分摄像头流和屏幕共享流。屏幕共享画面通常不需要展示麦克风图标,但可以展示“正在共享屏幕”等标识。
建议为挂件容器设置
pointer-events: none,避免遮挡视频画面的双击、拖拽或其他交互。场景三:根据会议场景切换布局
不同会议场景对视频布局的要求不同。例如,多人讨论适合宫格布局;屏幕共享、培训或主讲人场景适合顶部栏或侧边栏布局;移动端页面适合移动端布局。
实现思路
在业务层维护当前布局状态,并将其传入
RoomView 的 layoutTemplate。PC Web 可以在宫格、顶部栏、侧边栏之间切换;H5 建议固定使用 RoomLayoutTemplate.MobileLayout。示例代码
<template><RoomView :layout-template="currentLayout" /></template><script setup lang="ts">import { ref } from 'vue';import { RoomView, RoomLayoutTemplate } from 'tuikit-atomicx-vue3/room';const currentLayout = ref(RoomLayoutTemplate.GridLayout);function switchToGridLayout() {currentLayout.value = RoomLayoutTemplate.GridLayout;}function switchToSpeakerLayout() {currentLayout.value = RoomLayoutTemplate.SidebarLayout;}</script>
注意事项
PC Web 不建议使用
MobileLayout,H5 不建议使用 PC 的宫格、顶部栏或侧边栏布局。如果业务侧提供布局切换按钮,应在 UI 层根据当前平台只展示可用布局。
场景四:屏幕共享时自动切换布局
当会议中有人开始屏幕共享时,业务通常希望自动突出共享内容;当共享结束或只剩一个画面时,再恢复到宫格布局。
实现思路
通过
useRoomParticipantState 获取 participantWithScreen 和 participantList。当 participantWithScreen 从空变为有值时,将布局切换为 RoomLayoutTemplate.SidebarLayout 或 RoomLayoutTemplate.CinemaLayout;当画面数量恢复到 1 时,切回宫格布局。关键接口 / 状态
状态 | 说明 |
participantWithScreen | 当前正在屏幕共享的成员。 |
participantList | 当前房间成员列表。 |
RoomLayoutTemplate.SidebarLayout | 侧边栏主画面布局。 |
RoomLayoutTemplate.GridLayout | 宫格布局。 |
示例代码
<template><RoomView :layout-template="currentLayout" /></template><script setup>import { ref, watch } from 'vue';import {RoomLayoutTemplate,useRoomParticipantState,} from 'tuikit-atomicx-vue3/room';const currentLayout = ref(RoomLayoutTemplate.GridLayout);const { participantList, participantWithScreen } = useRoomParticipantState();watch(participantWithScreen, (newVal, oldVal) => {if (newVal && !oldVal) {currentLayout.value = RoomLayoutTemplate.SidebarLayout;}});watch(() => participantList.value.length + (participantWithScreen.value ? 1 : 0),(count) => {if (count === 1) {currentLayout.value = RoomLayoutTemplate.GridLayout;}},);</script>
RoomView 核心逻辑说明
本节用于解释
RoomView 的内部表现,帮助开发者理解“为什么画面这样排序”“为什么某些远端画面没有持续播放”“为什么小窗口画质较低”。如果您只需要完成基础接入,可以先阅读前面的场景章节。RoomView 核心逻辑
核心逻辑 | 说明 | 业务侧是否需要处理 |
视频流排序 | 根据屏幕共享、房主、本地用户、管理员、摄像头和麦克风状态生成视频流列表。 | 通常不需要。只有自定义成员列表或业务排序时才需要参考。 |
非可视区域不播放 | 视频画面支持懒加载,非可视区域中的远端视频流不会持续播放。 | 通常不需要。注意不要用自定义样式破坏布局容器的可视区域计算。 |
小窗口订阅低清流 | 视频流会根据画面尺寸和页面中的大画面数量选择合适清晰度,小窗口优先使用低清流,大画面和屏幕共享优先使用高清流。 | 通常不需要。业务侧不建议自行频繁切换远端流清晰度。 |
只负责排版和缩放 | RoomView 负责视频画面的排版、缩放和渲染参数,不负责进房、开关设备、成员会控或业务弹窗。 | 需要业务侧与房间管理、设备管理、成员管理组合。 |
视频流排序参考
优先级 | 排序因素 | 说明 |
1 | 屏幕共享流 | 有屏幕共享时,屏幕共享流会优先进入视频流列表。 |
2 | 房主 | 房主画面优先。 |
3 | 本地用户 | 本地用户画面优先。 |
4 | 管理员 | 管理员画面优先。 |
5 | 同时开启摄像头和麦克风 | 音视频活跃成员优先。 |
6 | 开启摄像头 | 有视频画面的成员优先。 |
7 | 开启麦克风 | 仅音频活跃成员次之。 |
主画面选择规则
布局 | 主画面规则 |
宫格布局 | 不区分主画面,按分页展示视频流。 |
顶部栏 / 侧边栏布局 | 优先展示用户双击锁定的画面;否则展示屏幕共享;否则展示第一个开启摄像头的成员;再否则展示本地用户。 |
移动端布局 | 优先展示屏幕共享;1-2 人场景突出远端或当前主要画面;多人场景通过分页展示。 |
说明:
顶部栏和侧边栏布局中,用户双击某个画面后,该画面会成为主画面。若该成员离开房间,或被锁定的屏幕共享结束,主画面会自动回退到默认选择规则。
异常排查指引
视频布局本身通常不直接抛出业务错误,但可能因为房间状态、容器尺寸、设备状态或布局配置不正确导致画面不符合预期。建议按以下方式排查。
常见表现 | 问题类型 | 建议处理方式 |
RoomView 没有画面 | 未进入房间或未打开摄像头 | 确保在进房接口调用成功后再渲染 RoomView 组件。 |
视频区域不可见或尺寸异常 | 父容器无尺寸 | 检查浏览器控制台元素,确认 RoomView 外层 div 的 width 和 height 是否计算为 0,建议设置为 100% 或具体的 px 值。 |
布局没有按预期切换 | 布局枚举错误 | 使用 RoomLayoutTemplate 枚举,不要手写字符串。 |
PC 端或者移动端交互不符合预期 | 平台布局不匹配 | H5 使用 RoomLayoutTemplate.MobileLayout。 |
共享内容没有成为主画面 | 屏幕共享未突出展示 | 监听 participantWithScreen,在共享开始时切换到顶部栏或侧边栏布局。 |
双击或屏幕分享双指放大不生效 | 挂件遮挡交互 | 挂件层避免拦截事件,必要时设置 pointer-events: none。 |
API 文档
常见问题
RoomView 是否会自动打开摄像头和麦克风?
不会。
RoomView 负责视频画面渲染和布局编排,打开或关闭本地摄像头、麦克风需要使用设备管理相关接口。RoomView 是否包含默认昵称、麦克风图标和角色标识?
RoomView 只提供 participantViewUI 插槽,不内置固定业务挂件。您可以根据 participant 和 streamType 自定义昵称、角色、麦克风状态和业务标签。为什么页面中看不到视频布局?
常见原因包括尚未进入房间、父容器没有明确尺寸、当前平台使用了不合适的布局,或本地及远端成员没有打开摄像头。建议先确认
currentRoom、父容器宽高和设备状态。屏幕共享时应该使用哪种布局?
PC Web 推荐使用
RoomLayoutTemplate.SidebarLayout 或 RoomLayoutTemplate.CinemaLayout,让共享内容成为主画面。H5 推荐继续使用 RoomLayoutTemplate.MobileLayout。顶部栏布局和侧边栏布局有什么区别?
两者都属于主画面布局。顶部栏布局将其他成员放在主画面上方,侧边栏布局将其他成员放在主画面侧边。选择哪一种主要取决于业务页面的空间结构和用户习惯。
宫格布局最多展示多少路画面?
PC Web 宫格布局单页最多展示 9 路画面,超过后通过翻页展示。移动端布局采用滑动分页方式展示。