一组 UI Kit 插件,通过提供额外的交互式组件和控件来扩展 RealtimeKit 预构建 UI Kit 的功能,从而增强会议体验。
This page is not available for the iOS, Android, Flutter, React Nativeplatform.
UI Kit 插件库提供了以下类别的组件:
主持人控制允许会议主持人管理参与者权限:
- Camera Host Control - 控制参与者摄像头权限
- Mic Host Control - 控制参与者麦克风权限
- Chat Host Control - 控制参与者聊天权限
面向参与者的互动参与功能:
- Hand Raise - 允许参与者举手示意他们想要发言
- Reactions Manager - 在会议期间显示 Emoji 表情回应
自定义参与者图块界面:
- Participant Tile Menu - 向参与者图块添加自定义菜单选项
向参与者选项卡添加自定义操作:
- Participant Menu Item - 向参与者操作添加自定义菜单项
- Participants Tab Action - 向参与者选项卡添加自定义操作按钮
- Participants Tab Toggle - 向参与者选项卡添加自定义开关控制
为参与者视频应用视觉效果:
- Video Background - 为视频流应用模糊或虚拟背景
自定义会议控制栏:
- Custom Control Bar Button - 向控制栏添加自定义按钮
npm i @cloudflare/realtimekit-ui-addonsyarn add @cloudflare/realtimekit-ui-addonspnpm add @cloudflare/realtimekit-ui-addonsbun add @cloudflare/realtimekit-ui-addonsnpm i @cloudflare/realtimekit-ui-addonsyarn add @cloudflare/realtimekit-ui-addonspnpm add @cloudflare/realtimekit-ui-addonsbun add @cloudflare/realtimekit-ui-addonsnpm i @cloudflare/realtimekit-ui-addonsyarn add @cloudflare/realtimekit-ui-addonspnpm add @cloudflare/realtimekit-ui-addonsbun add @cloudflare/realtimekit-ui-addonsimport { useState, useEffect } from "react";
import {
RealtimeKitProvider,
useRealtimeKitClient,
} from "@cloudflare/realtimekit-react";
import { RtkMeeting } from "@cloudflare/realtimekit-react-ui";
import { registerAddons, defaultConfig } from "@cloudflare/realtimekit-ui";
// 导入插件
import CameraHostControl from "@cloudflare/realtimekit-ui-addons/camera-host-control";
import MicHostControl from "@cloudflare/realtimekit-ui-addons/mic-host-control";
import ChatHostControl from "@cloudflare/realtimekit-ui-addons/chat-host-control";
import HandRaise from "@cloudflare/realtimekit-ui-addons/hand-raise";
import ReactionsManagerAddon from "@cloudflare/realtimekit-ui-addons/reactions-manager";
import ParticipantTileMenu from "@cloudflare/realtimekit-ui-addons/participant-tile-menu";
import ParticipantMenuItem from "@cloudflare/realtimekit-ui-addons/participant-menu-item";
import ParticipantsTabAction from "@cloudflare/realtimekit-ui-addons/participants-tab-action";
import ParticipantsTabToggle from "@cloudflare/realtimekit-ui-addons/participants-tab-toggle";
import RealtimeKitVideoBackground from "@cloudflare/realtimekit-ui-addons/video-background";
import CustomControlbarButton from "@cloudflare/realtimekit-ui-addons/custom-controlbar-button";
function App() {
const [meeting, initMeeting] = useRealtimeKitClient();
const [authToken, setAuthToken] = useState("<participant_auth_token>");
const [config, setConfig] = useState(defaultConfig);
useEffect(() => {
if (authToken) {
initMeeting({
authToken: authToken,
});
}
}, [authToken]);
useEffect(() => {
const initializeAddons = async () => {
if (!meeting) return;
// 初始化插件
const cameraHostControl = await CameraHostControl.init({
meeting,
hostPresets: ["webinar_presenter"],
targetPresets: ["webinar_viewer"],
addActionInParticipantMenu: true,
});
const micHostControl = await MicHostControl.init({
meeting,
hostPresets: ["webinar_presenter"],
targetPresets: ["webinar_viewer"],
addActionInParticipantMenu: true,
});
const chatHostControl = await ChatHostControl.init({
meeting,
hostPresets: ["webinar_presenter"],
targetPresets: ["webinar_viewer"],
addActionInParticipantMenu: true,
});
const handRaise = await HandRaise.init({
meeting,
canRaiseHand: true,
canManageRaisedHand: true,
handRaiseIcon:
'<svg fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M4 12.02c0 1.06.2 2.1.6 3.08l.6 1.42c.22.55.64 1.01 1.17 1.29.27.14.56.21.86.21h2.55c.77 0 1.49-.41 1.87-1.08.5-.87 1.02-1.7 1.72-2.43l1.32-1.39c.44-.46.97-.84 1.49-1.23l.59-.45a.6.6 0 0 0 .23-.47c0-.75-.54-1.57-1.22-1.79a3.34 3.34 0 0 0-2.78.29V4.5a1.5 1.5 0 0 0-2.05-1.4 1.5 1.5 0 0 0-2.9 0A1.5 1.5 0 0 0 6 4.5v.09A1.5 1.5 0 0 0 4 6v6.02ZM8 4.5v4a.5.5 0 0 0 1 0v-5a.5.5 0 0 1 1 0v5a.5.5 0 0 0 1 0v-4a.5.5 0 0 1 1 0v6a.5.5 0 0 0 .85.37h.01c.22-.22.44-.44.72-.58.7-.35 2.22-.57 2.4.5l-.53.4c-.52.4-1.04.78-1.48 1.24l-1.33 1.38c-.75.79-1.31 1.7-1.85 2.63-.21.36-.6.58-1.01.58H7.23a.87.87 0 0 1-.4-.1 1.55 1.55 0 0 1-.71-.78l-.59-1.42a7.09 7.09 0 0 1-.53-2.7V6a.5.5 0 0 1 1 0v3.5a.5.5 0 0 0 1 0v-5a.5.5 0 0 1 1 0Z" fill="#ff0000"></path></svg>',
});
const CUSTOM_REACTIONS = [
{ emoji: "🔥", label: "fire" },
{ emoji: "😢", label: "sad" },
{ emoji: "👍", label: "thumbs up" },
{ emoji: "👎", label: "thumbs down" },
{ emoji: "❤️", label: "heart" },
{ emoji: "😂", label: "laugh" },
{ emoji: "👏", label: "clap" },
{ emoji: "🎉", label: "celebrate" },
];
const reactionsAddon = await ReactionsManagerAddon.init({
meeting,
reactions: CUSTOM_REACTIONS,
canSendReactions: true,
});
const participantTileMenu = new ParticipantTileMenu(
[
{
label: "Custom Toggle",
onClick: (participantId) => {
console.log("Clicked on custom toggle for ", participantId);
},
},
],
"top-right",
);
const rightTickSVG =
"<svg xmlns='http://www.w3.org/2000/svg' width='24' height='24'><path d='M4 12l6 6 10-14' fill='none' stroke='currentColor' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/></svg>";
const participantMenuItem = new ParticipantMenuItem({
label: "Custom Menu Item",
icon: rightTickSVG,
styles: "rtk-icon { color: green !important; }",
onClick: () => {
alert("Participant Menu Item clicked");
},
});
const participantsTabAction = new ParticipantsTabAction({
onClick: () => {
alert("Clicked!");
},
label: "Click me",
position: "start",
});
const participantsTabToggle = new ParticipantsTabToggle({
onEnabled: () => {
alert("toggled true!");
},
onDisabled: () => {
alert("toggled false!");
},
label: "Click me",
initialValue: () => true,
position: "start",
});
const videoBackground = await RealtimeKitVideoBackground.init({
modes: ["blur", "virtual", "random"],
blurStrength: 30,
meeting,
images: [
"https://images.unsplash.com/photo-1487088678257-3a541e6e3922?q=80&w=2874&auto=format&fit=crop&ixlib=rb-4.0.3",
"https://images.unsplash.com/photo-1496715976403-7e36dc43f17b?q=80&w=2848&auto=format&fit=crop&ixlib=rb-4.0.3",
"https://images.unsplash.com/photo-1600431521340-491eca880813?q=80&w=2938&auto=format&fit=crop&ixlib=rb-4.0.3",
],
randomCount: 10,
onVideoBackgroundUpdate: ({ backgroundMode, backgroundURL }) => {
console.log("videoBackgroundUpdated => ", {
backgroundMode,
backgroundURL,
});
},
});
const customControlBarButton = new CustomControlbarButton({
position: "left",
icon: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"><path d="M12 17.75a1.25 1.25 0 1 1 0 2.5a1.25 1.25 0 0 1 0-2.5zM12 14c0-2.5 4-2.5 4-6a4 4 0 1 0-8 0" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /></svg>',
label: "Click Me!",
onClick: () => alert("Custom Control Bar Button Clicked"),
});
// 注册插件
const newConfig = registerAddons(
[
cameraHostControl,
micHostControl,
chatHostControl,
handRaise,
reactionsAddon,
participantTileMenu,
participantMenuItem,
participantsTabAction,
participantsTabToggle,
videoBackground,
customControlBarButton,
],
meeting,
);
setConfig(newConfig);
};
initializeAddons();
}, [meeting]);
return (
<RealtimeKitProvider value={meeting}>
<RtkMeeting showSetupScreen={true} meeting={meeting} config={config} />
</RealtimeKitProvider>
);
}将 UI Kit 库添加到您的 HTML 中:
<script type="module">
import { defineCustomElements } from "https://cdn.jsdelivr.net/npm/@cloudflare/realtimekit-ui@latest/loader/index.es2017.js";
defineCustomElements();
</script>在 HTML 文件中放置 rtk-meeting 组件:
<body>
<rtk-meeting></rtk-meeting>
</body>在脚本中初始化会议并配置插件:
<script type="module">
import RealtimeKitClient from "https://cdn.jsdelivr.net/npm/@cloudflare/realtimekit@latest/dist/index.es.js";
import { registerAddons } from "https://cdn.jsdelivr.net/npm/@cloudflare/realtimekit-ui@latest/dist/index.es.js";
// 导入插件
import CameraHostControl from "https://cdn.jsdelivr.net/npm/@cloudflare/realtimekit-ui-addons@latest/camera-host-control/index.js";
import MicHostControl from "https://cdn.jsdelivr.net/npm/@cloudflare/realtimekit-ui-addons@latest/mic-host-control/index.js";
import ChatHostControl from "https://cdn.jsdelivr.net/npm/@cloudflare/realtimekit-ui-addons@latest/chat-host-control/index.js";
import HandRaise from "https://cdn.jsdelivr.net/npm/@cloudflare/realtimekit-ui-addons@latest/hand-raise/index.js";
import ReactionsManagerAddon from "https://cdn.jsdelivr.net/npm/@cloudflare/realtimekit-ui-addons@latest/reactions-manager/index.js";
import ParticipantTileMenu from "https://cdn.jsdelivr.net/npm/@cloudflare/realtimekit-ui-addons@latest/participant-tile-menu/index.js";
import ParticipantMenuItem from "https://cdn.jsdelivr.net/npm/@cloudflare/realtimekit-ui-addons@latest/participant-menu-item/index.js";
import ParticipantsTabAction from "https://cdn.jsdelivr.net/npm/@cloudflare/realtimekit-ui-addons@latest/participants-tab-action/index.js";
import ParticipantsTabToggle from "https://cdn.jsdelivr.net/npm/@cloudflare/realtimekit-ui-addons@latest/participants-tab-toggle/index.js";
import RealtimeKitVideoBackground from "https://cdn.jsdelivr.net/npm/@cloudflare/realtimekit-ui-addons@latest/video-background/index.js";
import CustomControlbarButton from "https://cdn.jsdelivr.net/npm/@cloudflare/realtimekit-ui-addons@latest/custom-controlbar-button/index.js";
// 初始化会议
const meeting = await RealtimeKitClient.init({
authToken: "<participant_auth_token>",
});
// 初始化插件
// 主持人控制
const cameraHostControl = await CameraHostControl.init({
meeting,
hostPresets: ["webinar_presenter"],
targetPresets: ["webinar_viewer"],
addActionInParticipantMenu: true,
});
const micHostControl = await MicHostControl.init({
meeting,
hostPresets: ["webinar_presenter"],
targetPresets: ["webinar_viewer"],
addActionInParticipantMenu: true,
});
const chatHostControl = await ChatHostControl.init({
meeting,
hostPresets: ["webinar_presenter"],
targetPresets: ["webinar_viewer"],
addActionInParticipantMenu: true,
});
// 表情回应
const handRaise = await HandRaise.init({
meeting,
canRaiseHand: true,
canManageRaisedHand: true,
handRaiseIcon:
'<svg fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M4 12.02c0 1.06.2 2.1.6 3.08l.6 1.42c.22.55.64 1.01 1.17 1.29.27.14.56.21.86.21h2.55c.77 0 1.49-.41 1.87-1.08.5-.87 1.02-1.7 1.72-2.43l1.32-1.39c.44-.46.97-.84 1.49-1.23l.59-.45a.6.6 0 0 0 .23-.47c0-.75-.54-1.57-1.22-1.79a3.34 3.34 0 0 0-2.78.29V4.5a1.5 1.5 0 0 0-2.05-1.4 1.5 1.5 0 0 0-2.9 0A1.5 1.5 0 0 0 6 4.5v.09A1.5 1.5 0 0 0 4 6v6.02ZM8 4.5v4a.5.5 0 0 0 1 0v-5a.5.5 0 0 1 1 0v5a.5.5 0 0 0 1 0v-4a.5.5 0 0 1 1 0v6a.5.5 0 0 0 .85.37h.01c.22-.22.44-.44.72-.58.7-.35 2.22-.57 2.4.5l-.53.4c-.52.4-1.04.78-1.48 1.24l-1.33 1.38c-.75.79-1.31 1.7-1.85 2.63-.21.36-.6.58-1.01.58H7.23a.87.87 0 0 1-.4-.1 1.55 1.55 0 0 1-.71-.78l-.59-1.42a7.09 7.09 0 0 1-.53-2.7V6a.5.5 0 0 1 1 0v3.5a.5.5 0 0 0 1 0v-5a.5.5 0 0 1 1 0Z" fill="#ff0000"></path></svg>',
});
const CUSTOM_REACTIONS = [
{ emoji: "🔥", label: "fire" },
{ emoji: "😢", label: "sad" },
{ emoji: "👍", label: "thumbs up" },
{ emoji: "👎", label: "thumbs down" },
{ emoji: "❤️", label: "heart" },
{ emoji: "😂", label: "laugh" },
{ emoji: "👏", label: "clap" },
{ emoji: "🎉", label: "celebrate" },
];
const reactionsAddon = await ReactionsManagerAddon.init({
meeting,
reactions: CUSTOM_REACTIONS,
canSendReactions: true,
});
// 参与者图块
const participantTileMenu = new ParticipantTileMenu(
[
{
label: "Custom Toggle",
onClick: (participantId) => {
console.log("Clicked on custom toggle for ", participantId);
},
},
],
"top-right",
);
// 参与者选项卡操作
const rightTickSVG =
"<svg xmlns='http://www.w3.org/2000/svg' width='24' height='24'><path d='M4 12l6 6 10-14' fill='none' stroke='currentColor' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/></svg>";
const participantMenuItem = new ParticipantMenuItem({
label: "Custom Menu Item",
icon: rightTickSVG,
styles: "rtk-icon { color: green !important; }",
onClick: () => {
alert("Participant Menu Item clicked");
},
});
const participantsTabAction = new ParticipantsTabAction({
onClick: () => {
alert("Clicked!");
},
label: "Click me",
position: "start",
});
const participantsTabToggle = new ParticipantsTabToggle({
onEnabled: () => {
alert("toggled true!");
},
onDisabled: () => {
alert("toggled false!");
},
label: "Click me",
initialValue: () => true,
position: "start",
});
// 视频背景(效果)
const videoBackground = await RealtimeKitVideoBackground.init({
modes: ["blur", "virtual", "random"],
blurStrength: 30, // 0 - 100 范围的不透明度
meeting,
images: [
"https://images.unsplash.com/photo-1487088678257-3a541e6e3922?q=80&w=2874&auto=format&fit=crop&ixlib=rb-4.0.3",
"https://images.unsplash.com/photo-1496715976403-7e36dc43f17b?q=80&w=2848&auto=format&fit=crop&ixlib=rb-4.0.3",
"https://images.unsplash.com/photo-1600431521340-491eca880813?q=80&w=2938&auto=format&fit=crop&ixlib=rb-4.0.3",
],
randomCount: 10,
onVideoBackgroundUpdate: ({ backgroundMode, backgroundURL }) => {
console.log("videoBackgroundUpdated => ", {
backgroundMode,
backgroundURL,
});
},
});
// 控制栏
const customControlBarButton = new CustomControlbarButton({
position: "left",
icon: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"><path d="M12 17.75a1.25 1.25 0 1 1 0 2.5a1.25 1.25 0 0 1 0-2.5zM12 14c0-2.5 4-2.5 4-6a4 4 0 1 0-8 0" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /></svg>',
label: "Click Me!",
onClick: () => alert("Custom Control Bar Button Clicked"),
});
// 注册插件
const newConfig = registerAddons(
[
cameraHostControl,
micHostControl,
chatHostControl,
handRaise,
reactionsAddon,
participantTileMenu,
participantMenuItem,
participantsTabAction,
participantsTabToggle,
videoBackground,
customControlBarButton,
],
meeting,
);
// 将配置应用到会议组件
document.querySelector("rtk-meeting").showSetupScreen = true;
document.querySelector("rtk-meeting").meeting = meeting;
document.querySelector("rtk-meeting").config = newConfig;
</script>在组件模板中,添加会议组件:
<rtk-meeting [meeting]="meeting" [config]="config"></rtk-meeting>在组件 TypeScript 文件中:
import { Component, OnInit } from "@angular/core";
import RealtimeKitClient from "@cloudflare/realtimekit";
import { registerAddons, defaultConfig } from "@cloudflare/realtimekit-ui";
// 导入插件
import CameraHostControl from "@cloudflare/realtimekit-ui-addons/camera-host-control";
import MicHostControl from "@cloudflare/realtimekit-ui-addons/mic-host-control";
import ChatHostControl from "@cloudflare/realtimekit-ui-addons/chat-host-control";
import HandRaise from "@cloudflare/realtimekit-ui-addons/hand-raise";
import ReactionsManagerAddon from "@cloudflare/realtimekit-ui-addons/reactions-manager";
import ParticipantTileMenu from "@cloudflare/realtimekit-ui-addons/participant-tile-menu";
import ParticipantMenuItem from "@cloudflare/realtimekit-ui-addons/participant-menu-item";
import ParticipantsTabAction from "@cloudflare/realtimekit-ui-addons/participants-tab-action";
import ParticipantsTabToggle from "@cloudflare/realtimekit-ui-addons/participants-tab-toggle";
import RealtimeKitVideoBackground from "@cloudflare/realtimekit-ui-addons/video-background";
import CustomControlbarButton from "@cloudflare/realtimekit-ui-addons/custom-controlbar-button";
@Component({
selector: "app-meeting",
templateUrl: "./meeting.component.html",
})
export class MeetingComponent implements OnInit {
meeting: any;
config: any = defaultConfig;
async ngOnInit() {
// 初始化会议
this.meeting = await RealtimeKitClient.init({
authToken: "<participant_auth_token>",
});
// 初始化插件
const cameraHostControl = await CameraHostControl.init({
meeting: this.meeting,
hostPresets: ["webinar_presenter"],
targetPresets: ["webinar_viewer"],
addActionInParticipantMenu: true,
});
const micHostControl = await MicHostControl.init({
meeting: this.meeting,
hostPresets: ["webinar_presenter"],
targetPresets: ["webinar_viewer"],
addActionInParticipantMenu: true,
});
const chatHostControl = await ChatHostControl.init({
meeting: this.meeting,
hostPresets: ["webinar_presenter"],
targetPresets: ["webinar_viewer"],
addActionInParticipantMenu: true,
});
const handRaise = await HandRaise.init({
meeting: this.meeting,
canRaiseHand: true,
canManageRaisedHand: true,
handRaiseIcon:
'<svg fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M4 12.02c0 1.06.2 2.1.6 3.08l.6 1.42c.22.55.64 1.01 1.17 1.29.27.14.56.21.86.21h2.55c.77 0 1.49-.41 1.87-1.08.5-.87 1.02-1.7 1.72-2.43l1.32-1.39c.44-.46.97-.84 1.49-1.23l.59-.45a.6.6 0 0 0 .23-.47c0-.75-.54-1.57-1.22-1.79a3.34 3.34 0 0 0-2.78.29V4.5a1.5 1.5 0 0 0-2.05-1.4 1.5 1.5 0 0 0-2.9 0A1.5 1.5 0 0 0 6 4.5v.09A1.5 1.5 0 0 0 4 6v6.02ZM8 4.5v4a.5.5 0 0 0 1 0v-5a.5.5 0 0 1 1 0v5a.5.5 0 0 0 1 0v-4a.5.5 0 0 1 1 0v6a.5.5 0 0 0 .85.37h.01c.22-.22.44-.44.72-.58.7-.35 2.22-.57 2.4.5l-.53.4c-.52.4-1.04.78-1.48 1.24l-1.33 1.38c-.75.79-1.31 1.7-1.85 2.63-.21.36-.6.58-1.01.58H7.23a.87.87 0 0 1-.4-.1 1.55 1.55 0 0 1-.71-.78l-.59-1.42a7.09 7.09 0 0 1-.53-2.7V6a.5.5 0 0 1 1 0v3.5a.5.5 0 0 0 1 0v-5a.5.5 0 0 1 1 0Z" fill="#ff0000"></path></svg>',
});
const CUSTOM_REACTIONS = [
{ emoji: "🔥", label: "fire" },
{ emoji: "😢", label: "sad" },
{ emoji: "👍", label: "thumbs up" },
{ emoji: "👎", label: "thumbs down" },
{ emoji: "❤️", label: "heart" },
{ emoji: "😂", label: "laugh" },
{ emoji: "👏", label: "clap" },
{ emoji: "🎉", label: "celebrate" },
];
const reactionsAddon = await ReactionsManagerAddon.init({
meeting: this.meeting,
reactions: CUSTOM_REACTIONS,
canSendReactions: true,
});
const participantTileMenu = new ParticipantTileMenu(
[
{
label: "Custom Toggle",
onClick: (participantId: string) => {
console.log("Clicked on custom toggle for ", participantId);
},
},
],
"top-right",
);
const rightTickSVG =
"<svg xmlns='http://www.w3.org/2000/svg' width='24' height='24'><path d='M4 12l6 6 10-14' fill='none' stroke='currentColor' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/></svg>";
const participantMenuItem = new ParticipantMenuItem({
label: "Custom Menu Item",
icon: rightTickSVG,
styles: "rtk-icon { color: green !important; }",
onClick: () => {
alert("Participant Menu Item clicked");
},
});
const participantsTabAction = new ParticipantsTabAction({
onClick: () => {
alert("Clicked!");
},
label: "Click me",
position: "start",
});
const participantsTabToggle = new ParticipantsTabToggle({
onEnabled: () => {
alert("toggled true!");
},
onDisabled: () => {
alert("toggled false!");
},
label: "Click me",
initialValue: () => true,
position: "start",
});
const videoBackground = await RealtimeKitVideoBackground.init({
modes: ["blur", "virtual", "random"],
blurStrength: 30,
meeting: this.meeting,
images: [
"https://images.unsplash.com/photo-1487088678257-3a541e6e3922?q=80&w=2874&auto=format&fit=crop&ixlib=rb-4.0.3",
"https://images.unsplash.com/photo-1496715976403-7e36dc43f17b?q=80&w=2848&auto=format&fit=crop&ixlib=rb-4.0.3",
"https://images.unsplash.com/photo-1600431521340-491eca880813?q=80&w=2938&auto=format&fit=crop&ixlib=rb-4.0.3",
],
randomCount: 10,
onVideoBackgroundUpdate: ({ backgroundMode, backgroundURL }: any) => {
console.log("videoBackgroundUpdated => ", {
backgroundMode,
backgroundURL,
});
},
});
const customControlBarButton = new CustomControlbarButton({
position: "left",
icon: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"><path d="M12 17.75a1.25 1.25 0 1 1 0 2.5a1.25 1.25 0 0 1 0-2.5zM12 14c0-2.5 4-2.5 4-6a4 4 0 1 0-8 0" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /></svg>',
label: "Click Me!",
onClick: () => alert("Custom Control Bar Button Clicked"),
});
// 注册插件
this.config = registerAddons(
[
cameraHostControl,
micHostControl,
chatHostControl,
handRaise,
reactionsAddon,
participantTileMenu,
participantMenuItem,
participantsTabAction,
participantsTabToggle,
videoBackground,
customControlBarButton,
],
this.meeting,
);
}
}某些插件支持在会议期间进行动态更改的编程式控制。
您可以通过编程方式应用、替换或移除视频背景:
// 应用虚拟背景
await videoBackground.applyVirtualBackground(
"https://images.unsplash.com/photo-1600431521340-491eca880813?q=80&w=2938&auto=format&fit=crop&ixlib=rb-4.0.3",
);
// 应用模糊背景
await videoBackground.applyBlurBackground();
// 移除背景(返回普通视频)
await videoBackground.removeBackground();某些插件支持在会议期间进行动态更改的编程式控制。
您可以通过编程方式应用、替换或移除视频背景:
// 应用虚拟背景
await videoBackground.applyVirtualBackground(
"https://images.unsplash.com/photo-1600431521340-491eca880813?q=80&w=2938&auto=format&fit=crop&ixlib=rb-4.0.3",
);
// 应用模糊背景
await videoBackground.applyBlurBackground();
// 移除背景(返回普通视频)
await videoBackground.removeBackground();某些插件支持在会议期间进行动态更改的编程式控制。
您可以通过编程方式应用、替换或移除视频背景:
// 应用虚拟背景
await videoBackground.applyVirtualBackground(
"https://images.unsplash.com/photo-1600431521340-491eca880813?q=80&w=2938&auto=format&fit=crop&ixlib=rb-4.0.3",
);
// 应用模糊背景
await videoBackground.applyBlurBackground();
// 移除背景(返回普通视频)
await videoBackground.removeBackground();