即时通信 IM 屏幕分享

这篇档指导你如何使用 Atomicx 实现屏幕分享能力,并根据屏幕分享状态处理房间内交互。

相关产品
即时通信 IM 产品页,含版本规格、价格与购买入口。

一、前提条件

·用户已经通过 useLoginState 完成登录鉴权,请参考 接入概览。

·用户已经通过 useRoomState 进入房间,请参考 房间管理。

·若在 iframe 中集成,需在标签中声明权限。

<iframe allow="display-capture; fullscreen;"></iframe>

二、步骤1:开始屏幕分享

使用 startScreenShare 方法开始屏幕分享。在 Web 环境下,你将看到浏览器的屏幕选择器,可以选择分享整个屏幕、应用窗口或浏览器标签页。

Vue3Reactimport { useDeviceState } from 'tuikit-atomicx-vue3/room';const { startScreenShare } = useDeviceState();// 尝试开始屏幕分享,并尝试分享系统音频const handleStartShare = async () => { try { await startScreenShare({ screenAudio: true }); } catch (error) { // 处理用户拒绝或浏览器不支持等错误 console.error('开始屏幕分享失败:', error); }};import { useDeviceState } from 'tuikit-atomicx-react/room';const { startScreenShare } = useDeviceState();// 尝试开始屏幕分享,并尝试分享系统音频const handleStartShare = async () => { try { await startScreenShare({ screenAudio: true }); } catch (error) { // 处理用户拒绝或浏览器不支持等错误 console.error('开始屏幕分享失败:', error); }};

三、步骤2:分享系统音频

通过设置 screenAudio: true 参数,可以在屏幕分享时同时分享系统音频。这在分享视频、演示、音乐等包含音频内容时非常有用。

Vue3Reactimport { useDeviceState } from 'tuikit-atomicx-vue3/room';const { startScreenShare } = useDeviceState();// 开始屏幕分享并分享系统音频const handleStartScreenShareWithAudio = async () => { try { await startScreenShare({ screenAudio: true }); console.log('屏幕分享(含音频)已开始'); } catch (error) { console.error('开始屏幕分享失败:', error); }};import { useDeviceState } from 'tuikit-atomicx-react/room';const { startScreenShare } = useDeviceState();// 开始屏幕分享并分享系统音频const handleStartScreenShareWithAudio = async () => { try { await startScreenShare({ screenAudio: true }); console.log('屏幕分享(含音频)已开始'); } catch (error) { console.error('开始屏幕分享失败:', error); }};

浏览器兼容性说明:

浏览器 系统音频分享支持 备注
Chrome 74+ 支持 需要在选择器中勾选分享音频
Edge 79+ 支持 基于 Chromium,体验同 Chrome
Firefox 不支持 暂不支持系统音频分享
Safari 不支持 暂不支持系统音频分享

注意:系统音频分享需要浏览器支持,且用户在屏幕选择器中勾选分享音频选项。如果浏览器不支持系统音频分享,screenAudio 参数会被忽略,但屏幕画面分享功能不受影响,可以正常使用。

四、步骤3:停止屏幕分享

用户可以通过以下几种方式停止屏幕分享:

1. 调用 stopScreenShare() 接口

Vue3Reactimport { useDeviceState, DeviceStatus } from 'tuikit-atomicx-vue3/room';const { screenStatus, stopScreenShare } = useDeviceState();// 停止屏幕分享const handleStopScreenShare = async () => { try { await stopScreenShare(); console.log('屏幕分享已停止'); } catch (error) { console.error('停止屏幕分享失败:', error); }};import { useDeviceState, DeviceStatus } from 'tuikit-atomicx-react/room';const { screenStatus, stopScreenShare } = useDeviceState();// 停止屏幕分享const handleStopScreenShare = async () => { try { await stopScreenShare(); console.log('屏幕分享已停止'); } catch (error) { console.error('停止屏幕分享失败:', error); }};

2. 点击浏览器原生的"停止分享"按钮

3. 关闭被分享的窗口或标签页

注意:说明:

注意:用户使用任意一种方式停止屏幕分享时,Atomicx 都会自动更新 screenStatus 的状态。

五、设置屏幕分享权限

你可以通过 useRoomParticipantState 提供的成员管理接口控制房间内的屏幕管理权限。

Vue3Reactimport { useRoomParticipantState, DeviceType } from 'tuikit-atomicx-vue3/room';const { disableAllDevices } = useRoomParticipantState();// 限制仅房主/管理员可以发起屏幕分享async function handleDisableAllScreen() { await disableAllDevices({ deviceType: DeviceType.Screen, disable: true, });}// 允许房间内所有用户发起屏幕分享async function handleEnableAllScreen() { await disableAllDevices({ deviceType: DeviceType.Screen, disable: false, });}import { useRoomParticipantState, DeviceType } from 'tuikit-atomicx-react/room';const { disableAllDevices } = useRoomParticipantState();// 限制仅房主/管理员可以发起屏幕分享async function handleDisableAllScreen() { await disableAllDevices({ deviceType: DeviceType.Screen, disable: true, });}// 允许房间内所有用户发起屏幕分享async function handleEnableAllScreen() { await disableAllDevices({ deviceType: DeviceType.Screen, disable: false, });}

六、自动布局切换

当检测到房间中有用户开始屏幕分享时,建议切换到侧边栏布局(RoomLayoutTemplate.SidebarLayout),将分享画面放大显示,其他参会者画面显示在侧边栏。

Vue3React<template> <div class="room-container"> <RoomView :layout-template="layoutTemplate"> <template #participantViewUI="{ participant, streamType }"> <ParticipantViewUI :participant="participant" :stream-type="streamType" /> </template> </RoomView> </div></template><script setup lang="ts">import { ref, watch } from 'vue';import { RoomView, RoomLayoutTemplate, useRoomParticipantState} from 'tuikit-atomicx-vue3/room';const layoutTemplate = ref(RoomLayoutTemplate.GridLayout);const { participantWithScreen } = useRoomParticipantState();// 监听屏幕分享状态,自动切换布局watch(participantWithScreen, (participant) => { if (participant) { // 有人分享屏幕,切换到侧边栏布局 layoutTemplate.value = RoomLayoutTemplate.SidebarLayout; } else { // 没有人分享屏幕,切换回网格布局 layoutTemplate.value = RoomLayoutTemplate.GridLayout; }});</script>import { useState, useEffect } from 'react';import { RoomView, RoomLayoutTemplate, useRoomParticipantState} from 'tuikit-atomicx-react/room';const RoomComponent = () => { const [layoutTemplate, setLayoutTemplate] = useState(RoomLayoutTemplate.GridLayout); const { participantWithScreen } = useRoomParticipantState(); // 监听屏幕分享状态,自动切换布局 useEffect(() => { if (participantWithScreen) { // 有人分享屏幕,切换到侧边栏布局 setLayoutTemplate(RoomLayoutTemplate.SidebarLayout); } else { // 没有人分享屏幕,切换回网格布局 setLayoutTemplate(RoomLayoutTemplate.GridLayout); } }, [participantWithScreen]); return ( <div className="room-container"> <RoomView layoutTemplate={layoutTemplate} participantViewUI={({ participant, streamType }) => ( <ParticipantViewUI participant={participant} streamType={streamType} /> )} /> </div> );};

七、限制仅一人屏幕分享

在房间中应该只允许一个人分享屏幕,当有人正在分享时,禁用其他人的分享按钮:

Vue3React<script setup>import { computed } from 'vue';import { useRoomParticipantState } from 'tuikit-atomicx-vue3/room';const { participantWithScreen, localParticipant } = useRoomParticipantState();const isOtherSharing = computed(() => { const sharer = participantWithScreen.value; if (!sharer) return false; return sharer.userId !== localParticipant.value?.userId;});const canStartScreenShare = computed(() => { return !isOtherSharing.value;});</script>// 在模板中使用<template> <button :disabled="!canStartScreenShare" @click="handleStartShare"> 开始屏幕分享 </button><template>import { useRoomParticipantState } from 'tuikit-atomicx-react/room';const { participantWithScreen, localParticipant } = useRoomParticipantState();const isOtherSharing = (() => { const sharer = participantWithScreen; if (!sharer) return false; return sharer.userId !== localParticipant?.userId;})();const canStartScreenShare = !isOtherSharing;// 在 JSX 中使用return ( <button disabled={!canStartScreenShare} onClick={handleStartShare}> 开始屏幕分享 </button>);

八、步骤5:处理屏幕分享错误

当屏幕分享发生错误时,根据错误信息提示用户做出相应的操作。

代码示例:

Vue3Reactimport { useDeviceState, DeviceError } from 'tuikit-atomicx-vue3/room';import { TUIToast } from '@tencentcloud/uikit-base-component-vue3';const { startScreenShare } = useDeviceState();try { await startScreenShare();} catch (error: any) { let message = ''; switch (error.name) { case 'NotReadableError': message = '系统禁止当前浏览器访问屏幕内容,请启用屏幕分享权限。'; break; case 'NotAllowedError': if (error.message.includes('Permission denied by system')) { message = '系统禁止当前浏览器访问屏幕内容,请启用屏幕分享权限。'; } else { message = '用户取消屏幕分享'; } break; default: message = '屏幕分享过程中发生未知错误,请重试。'; break; } TUIToast.warning({ message, });}import { useDeviceState, DeviceError } from 'tuikit-atomicx-react/room';import { TUIToast } from '@tencentcloud/uikit-base-component-react';const { startScreenShare } = useDeviceState();try { await startScreenShare();} catch (error: any) { let message = ''; switch (error.name) { case 'NotReadableError': message = '系统禁止当前浏览器访问屏幕内容,请启用屏幕分享权限。'; break; case 'NotAllowedError': if (error.message.includes('Permission denied by system')) { message = '系统禁止当前浏览器访问屏幕内容,请启用屏幕分享权限。'; } else { message = '用户取消屏幕分享'; } break; default: message = '屏幕分享过程中发生未知错误,请重试。'; break; } TUIToast.warning({ message, });}

九、API 文档

State/Component 功能描述 API 文档
useDeviceState 包含音视频设备状态,音视频设备列表及操作接口。 API 文档
useRoomParticipantState 包含房间内用户数据,用户管理接口。 API 文档

十、为什么系统音频分享不生效?

·平台限制:音频分享目前仅在 Chrome、Edge 等现代浏览器上支持。

·操作细节:用户必须在浏览器弹出的屏幕选择器中,手动选择分享音频。

·系统限制:部分操作系统不支持分享特定应用窗口的音频,建议优先选择整个屏幕或浏览器标签页。

十一、如何感知用户通过点击浏览器的“停止分享”按钮后结束屏幕分享?

Atomicx 会自动监听浏览器的停止分享事件,并更新 screenStatus 状态。你只需要监听 screenStatus 的变化即可:

Vue3Reactwatch(screenStatus, (newStatus, oldStatus) => { if (oldStatus === DeviceStatus.On && newStatus === DeviceStatus.Off) { console.log('用户已停止屏幕分享。'); }});import { useEffect, useRef } from 'react';import { useDeviceState, DeviceStatus } from 'tuikit-atomicx-react/room';const { screenStatus } = useDeviceState();const prevScreenStatus = useRef(screenStatus);useEffect(() => { if (prevScreenStatus.current === DeviceStatus.On && screenStatus === DeviceStatus.Off) { console.log('用户已停止屏幕分享。'); } prevScreenStatus.current = screenStatus;}, [screenStatus]);

十二、移动端浏览器是否支持屏幕分享?

仅桌面端浏览器支持屏幕分享,移动端浏览器不支持屏幕分享能力。

十三、为什么用户开启屏幕分享音频后,其他参会者看到该用户的麦克风状态显示为“开启”?

这是符合预期的系统行为,原因如下:

技术原理: microphoneStatus表示当前设备是否正在对外传输音频信号。当开启屏幕分享并勾选采集系统音频时,Atomicx SDK 会启动一条音频传输通道。由于远端接收到的是连续的音频数据流,系统无法区分音频来源是物理麦克风还是系统播放声音,因此会将音频采集状态统一标识为 DeviceStatus.On。

隐私说明:请放心,这并不代表你的麦克风已经在采集说话声音。 麦克风声音是否在推送仅和麦克风控制接口( openLocalMicrophone 和 unmuteLocalMicrophone )有关,与屏幕分享音频采集是独立的两个通道。即使屏幕分享音频正在传输,只要未调用麦克风相关接口,你的麦克风声音不会被采集和推送。

赞 (0)
上一篇 4天前
下一篇 4天前