| name | video-sdk/web |
| description | Expert guidance for building browser-based video sessions with the Zoom Video SDK for Web (@zoom/videosdk v2.4.0) in React, Vue, Angular, Svelte, or vanilla TypeScript. Use this skill whenever the user is implementing or debugging any in-browser real-time communication feature — joining/leaving a session, capturing or rendering audio/video, gallery or active-speaker views, virtual backgrounds, screen sharing with annotation, in-session chat or command channel, recording, subsessions, live streaming, PSTN/SIP dial-out, PTZ cameras, quality stats, WebAssembly/SharedArrayBuffer setup, CSP/COOP/COEP headers, JWT session tokens, or resolving SDK error codes. Trigger even when the user doesn't explicitly say "Zoom" — signals include `@zoom/videosdk`, `ZoomVideo.createClient`, `client.getMediaStream`, `stream.startVideo`, `attachVideo`, "video conferencing", "video call app", "video SDK", "render remote video", or debugging black/green video tiles, audio that won't start, or `OperationBlockedByBrowserPolicy` errors. Prefer this skill over generic WebRTC advice whenever `@zoom/videosdk` is in play. |
| user-invocable | false |
| triggers | ["video sdk web","custom video web","attachvideo","web videosdk","zoom videosdk web","@zoom/videosdk","video web session","peer-video-state-change","video rendering"] |
Zoom Video SDK Web (v2.4.0)
Expert guidance for building video sessions with Zoom Video SDK for Web.
This skill is for custom video sessions, not embedded Zoom meetings.
If the user wants a custom UI for a real Zoom meeting, route to ../../meeting-sdk/web/component-view/SKILL.md.
Use ../../probe-sdk/SKILL.md as an optional browser/device/network readiness gate before client.join(...).
Quick Start
Installation
bun install @zoom/videosdk --save
npm install @zoom/videosdk --save
Basic Session Setup
import ZoomVideo from "@zoom/videosdk";
const client = ZoomVideo.createClient();
await client.init("en-US", "Global", { patchJsMedia: true });
await client.join(sessionName, jwtToken, userName, sessionPassword);
const stream = client.getMediaStream();
Core API Reference
ZoomVideo (Static Methods)
| Method | Description |
|---|
createClient() | Create VideoClient instance (singleton) |
checkSystemRequirements() | Check browser compatibility → { audio, video, screen } |
checkFeatureRequirements() | Get supported/unsupported features list |
getDevices(skipPermissionCheck?) | Enumerate media devices |
createLocalAudioTrack(deviceId?) | Create local audio track for preview |
createLocalVideoTrack(deviceId?) | Create local video track for preview |
destroyClient() | Destroy client instance |
preloadDependentAssets(path?) | Preload WebAssembly/Worker assets |
VideoClient Methods
Session Management
await client.init(language, dependentAssets, options?);
await client.join(topic, token, userName, password?, idleTimeoutMins?);
await client.leave(end?);
User Management
client.getCurrentUserInfo(): Participant;
client.getAllUser(): Participant[];
client.getUser(userId): Participant | undefined;
client.getSessionHost(): Participant | undefined;
client.makeHost(userId);
client.makeManager(userId);
client.revokeManager(userId);
client.removeUser(userId);
client.changeName(name, userId?);
Feature Clients
client.getMediaStream();
client.getChatClient();
client.getCommandClient();
client.getRecordingClient();
client.getSubsessionClient();
client.getLiveTranscriptionClient();
client.getLiveStreamClient();
client.getWhiteboardClient();
MediaStream (Audio/Video Control)
Audio
const stream = client.getMediaStream();
await stream.startAudio({
mute?: boolean,
speakerOnly?: boolean,
backgroundNoiseSuppression?: boolean,
microphoneId?: string,
speakerId?: string,
});
await stream.muteAudio();
await stream.unmuteAudio();
stream.stopAudio();
stream.getMicList(): MediaDevice[];
stream.getSpeakerList(): MediaDevice[];
await stream.switchMicrophone(deviceId);
await stream.switchSpeaker(deviceId);
Video
await stream.startVideo();
await stream.startVideo({
cameraId?: string,
hd?: boolean,
fullHd?: boolean,
mirrored?: boolean,
virtualBackground?: { imageUrl: string | 'blur' | undefined, cropped?: boolean },
});
const videoElement = await stream.attachVideo(userId, VideoQuality.Video_720P);
container.appendChild(videoElement);
await stream.stopVideo();
stream.detachVideo(userId);
stream.getCameraList(): MediaDevice[];
await stream.switchCamera(deviceId);
Screen Share
await stream.startShareScreen({
broadcastToSubsession: boolean,
optimizedForSharedVideo: boolean,
secondaryCameraId: string,
});
await stream.stopShareScreen();
await stream.startShareView(canvas, userId);
stream.stopShareView();
Events
client.on("connection-change", (payload) => {
});
client.on("user-added", (participants: Participant[]) => {});
client.on("user-updated", (participants: Participant[]) => {});
client.on("user-removed", (participants: Participant[]) => {});
client.on("current-audio-change", (payload) => {
});
client.on("active-speaker", (payload) => {
});
client.on("video-active-change", (payload) => {
});
client.on("peer-video-state-change", (payload) => {
});
client.on("active-share-change", (payload) => {
});
client.on("peer-share-state-change", (payload) => {
});
client.on("chat-on-message", (payload) => {
});
client.on("device-change", () => {
});
Framework-Specific Implementation Guides
For complete implementation examples with full project setup, hooks/composables/services, and components:
Quick Setup Requirements
All frameworks MUST configure:
- COOP/COEP Headers (for SharedArrayBuffer support):
server: {
headers: {
'Cross-Origin-Opener-Policy': 'same-origin',
'Cross-Origin-Embedder-Policy': 'require-corp',
},
}
- TypeScript Custom Elements (for video rendering):
declare namespace JSX {
interface IntrinsicElements {
"video-player-container": React.DetailedHTMLProps<
React.HTMLAttributes<HTMLElement>,
HTMLElement
>;
}
}
Core Implementation Pattern
All implementations should follow this pattern:
- Client Management - Singleton client with init/join/leave lifecycle
- Media Stream - Audio/video/screen share controls with state sync
- Participants - User list with video state change listeners
- Video Rendering - Use
video-player-container + attachVideo()
- Event Handling - Connection, audio, video, chat events
- Error Handling - Map SDK error codes to user messages
JWT Token Requirements
Generate JWT on your server using HMAC SHA256. Never expose SDK secret in client code.
Required Claims
{
app_key: 'YOUR_SDK_KEY',
tpc: 'session-name',
role_type: 1,
version: 1,
iat: Math.floor(Date.now() / 1000) - 30,
exp: iat + 7200,
}
Optional Claims
| Claim | Description |
|---|
user_key | Unique user identifier (max 36 chars) |
session_key | Session identifier for cloud recording (max 36 chars) |
geo_regions | Data center regions: AU,BR,CA,DE,HK,IN,JP,CN,MX,NL,SG,US |
cloud_recording_option | 0 = combined video, 1 = separate files per user |
cloud_recording_election | 1 to record user's self-view |
cloud_recording_transcript_option | 0 = none, 1 = transcript, 2 = transcript + summary |
video_webrtc_mode | 0 = disable, 1 = enable WebRTC video |
audio_webrtc_mode | 1 = enable WebRTC audio (Web only) |
telemetry_tracking_id | For Web SDK telemetry tracking |
Node.js(jsrsasign) Quick Start JWT Generator Service:
git clone https://github.com/zoom/videosdk-auth-endpoint-sample.git
cd videosdk-auth-endpoint-sample
bun install
npm install
mv .env.example .env
bun run start
npm run start
jsrsasign Example Code:
import { KJUR } from "jsrsasign";
const iat = Math.floor(Date.now() / 1000) - 30;
const exp = iat + 60 * 60 * 2;
const payload = {
app_key: process.env.ZOOM_SDK_KEY,
tpc: "session-name",
role_type: 1,
version: 1,
video_webrtc_mode: 1,
audio_webrtc_mode: 1,
iat,
exp,
};
const token = KJUR.jws.JWS.sign(
"HS256",
JSON.stringify({ alg: "HS256", typ: "JWT" }),
JSON.stringify(payload),
process.env.ZOOM_SDK_SECRET
);
Init Options
interface InitOptions {
webEndpoint?: string;
enforceMultipleVideos?: boolean | { disableRenderLimits?: boolean };
enforceVirtualBackground?: boolean;
stayAwake?: boolean;
leaveOnPageUnload?: boolean;
patchJsMedia?: boolean;
alternativeNameForVideoPlayer?: string;
}
Video Quality Enum
enum VideoQuality {
Video_90P = 0,
Video_180P = 1,
Video_360P = 2,
Video_720P = 3,
Video_1080P = 4,
}
Best Practices
- Always check browser support before initializing
- Generate JWT on server - never expose SDK secret in client
- Handle connection events for robust session management
- Request user gesture before starting audio (browser requirement)
- Use
patchJsMedia: true for latest WebAssembly fixes
- Set
leaveOnPageUnload: true for clean disconnection
- Implement error handling for all async operations
- Clean up event listeners on session end
Common Issues
| Issue | Solution |
|---|
| Audio doesn't start | Requires user gesture (click/tap) |
| Video not rendering | Use video-player-container custom element and append attachVideo() result |
| JWT invalid | Verify tpc matches session name |
| SharedArrayBuffer error | MUST add COOP/COEP headers in vite.config.ts |
OPERATION_TIMEOUT on startVideo | Check camera permissions and ensure COOP/COEP headers are set |
INVALID_PARAMETERS on attachVideo | Don't pass container as 3rd param - append the returned element instead |
| Self-video not showing | Pass currentUserVideoOn prop to VideoGrid (participant.bVideoOn may lag) |
| Participants not updating | Listen for video-active-change and peer-video-state-change events |
| "Waiting for participants" stuck | Pass isJoined to useParticipants hook and listen for connection-change |
Detailed Guides
Core Concepts (read these first — they apply to every feature)
Feature References
- references/sessions.md - Session lifecycle, user roles, JWT token, connection events
- references/audio.md - Audio controls, devices, muting, dial-out, noise suppression
- references/video.md - Video capture, rendering, virtual background, PTZ cameras
- references/screen-share.md - Screen sharing, annotation, tab audio, share privileges
- references/features.md - Preview, recording, subsessions, live stream, command channel, transcription, PSTN, SIP, quality stats
- references/advanced.md - Chat, custom processors, whiteboard
- references/browser-support.md - Browser compatibility, SharedArrayBuffer, CSP headers
- references/error-codes.md - Complete error code reference
- troubleshooting/common-issues.md - Troubleshooting guide: symptoms → causes → fixes for the most common Video SDK bugs
Type Definitions Location
All TypeScript definitions are in @zoom/videosdk/dist/types:
index.d.ts - Main exports
zoomvideo.d.ts - ZoomVideo namespace
videoclient.d.ts - VideoClient methods and events
media.d.ts - MediaStream, audio/video options
common.d.ts - Shared types (Participant, enums)
chat.d.ts - Chat client
recording.d.ts - Recording client
subsession.d.ts - Breakout rooms
Resources Homepage
Official Docs URLs
# Main Documentation
https://developers.zoom.us/docs/video-sdk/web/get-started/
https://developers.zoom.us/docs/video-sdk/web/sessions/
https://developers.zoom.us/docs/video-sdk/web/event-handling/
# Audio & Video
https://developers.zoom.us/docs/video-sdk/web/video/
https://developers.zoom.us/docs/video-sdk/web/audio/
https://developers.zoom.us/docs/video-sdk/web/preview/
# Screen Sharing
https://developers.zoom.us/docs/video-sdk/web/share/
https://developers.zoom.us/docs/video-sdk/web/share-annotation/
https://developers.zoom.us/docs/video-sdk/web/share-browser-options/
# Advanced Features
https://developers.zoom.us/docs/video-sdk/web/recording/
https://developers.zoom.us/docs/video-sdk/web/subsessions/
https://developers.zoom.us/docs/video-sdk/web/live-stream/
https://developers.zoom.us/docs/video-sdk/web/command-channel/
https://developers.zoom.us/docs/video-sdk/web/transcription-translation/
https://developers.zoom.us/docs/video-sdk/web/chat/
# Phone Integration
https://developers.zoom.us/docs/video-sdk/web/pstn/
https://developers.zoom.us/docs/video-sdk/web/sip/
# Quality & Compatibility
https://developers.zoom.us/docs/video-sdk/web/quality/
https://developers.zoom.us/docs/video-sdk/web/browser-support/
https://developers.zoom.us/docs/video-sdk/web/sharedarraybuffer/
https://developers.zoom.us/docs/video-sdk/web/error-codes/
# Other
https://developers.zoom.us/docs/video-sdk/web/virtual-background/
https://developers.zoom.us/docs/video-sdk/web/frameworks/
Repo-Local Appendices
The documents below provide deeper examples, compatibility shims, and operational debugging.
Operational Docs
- RUNBOOK.md - 5-minute preflight checks before deep debugging
Compatibility References
Complementary Examples