Video SDK Web
AnthropicOfficialCreated by ZoomDistributed by Anthropic
- Skill
- Tool integration
- Software development
- MIT
- No issues found
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
The Zoom Video SDK for Web provides a library for developers to build custom video-based experiences directly within browser environments. It supports real-time communication, screen sharing, cloud recording, live streaming, chat, and live transcription. The SDK requires a specific lifecycle, including client initialization and session joining, and provides specialized clients for managing media streams, chat, and other collaborative features.
What it does
- Enables custom video and audio sessions in modern web browsers.
- Supports screen sharing and collaborative whiteboard features.
- Provides tools for cloud recording and live streaming to RTMP endpoints.
- Includes messaging capabilities via chat and command channels.
- Facilitates live transcription for real-time speech-to-text.
- Allows for virtual backgrounds and custom video frame processing.
When to use it
- When building a custom video application that requires a unique UI.
- When integrating real-time video communication into an existing web platform.
- When implementing features like breakout rooms or live transcription in a web-based session.
- When you need to control media stream rendering and participant interaction programmatically.
Advantages
- Provides a modular API for granular control over media and session features.
- Supports standard web technologies like JavaScript and TypeScript.
- Offers specialized clients for distinct features like recording and chat.
- Includes event-driven architecture for handling participant and media state changes.
Usage examples
- “How do I join a video session using the Zoom Video SDK for Web?”
- Initialize the client with your credentials, call the join method with the session topic and signature, then retrieve the media stream object to start video and audio.
- “How can I display a remote participant's video?”
- Listen for the peer-video-state-change event, and when a participant starts their video, use the attachVideo method to append their video element to your DOM.
- “What is the correct way to handle media streams?”
- Always call getMediaStream after the join method has successfully completed to ensure the stream object is available.
- “How do I implement screen sharing?”
- Use the startShareScreen method on the media stream object, passing in a canvas or video element to render the shared content.
Install
Download the skill as a ZIP:
https://mp-staging.autogineer.com/agent-skills/anthropics/video-sdk-web/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip video-sdk-web.zip -d .agents/skills
Documentation by Zoom
Zoom Video SDK - Web Development
Expert guidance for developing with the Zoom Video SDK on Web. This SDK enables custom video applications in the browser with real-time video/audio, screen sharing, cloud recording, live streaming, chat, and live transcription.
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.
Official Documentation: https://developers.zoom.us/docs/video-sdk/web/ API Reference: https://marketplacefront.zoom.us/sdk/custom/web/modules.html Sample Repository: https://github.com/zoom/videosdk-web-sample
Quick Links
New to Video SDK? Follow this path:
SDK Architecture Pattern - Universal 3-step pattern for ANY feature
Session Join Pattern - Complete working code to join a session
Video Rendering - Display video with attachVideo()
Event Handling - Required events for video/audio
Reference:
Singleton Hierarchy - 4-level SDK navigation map
API Reference - Methods, events, error codes
SKILL.md - Complete documentation navigation
../../probe-sdk/SKILL.md - Optional browser/device/network readiness diagnostics before join
Having issues?
Video not showing → Video Rendering (use attachVideo, not renderVideo)
getMediaStream() returns undefined → Call AFTER join() completes
Quick diagnostics → Common Issues
SDK Overview
The Zoom Video SDK for Web is a JavaScript library that provides:
Session Management: Join/leave video SDK sessions
Video/Audio: Start/stop camera and microphone
Screen Sharing: Share screens or browser tabs
Cloud Recording: Record sessions to Zoom cloud
Live Streaming: Stream to RTMP endpoints
Chat: In-session messaging
Command Channel: Custom command messaging
Live Transcription: Real-time speech-to-text
Subsessions: Breakout room support
Whiteboard: Collaborative whiteboard features
Virtual Background: Blur or custom image backgrounds
Prerequisites
System Requirements
Modern Browser: Chrome 80+, Firefox 75+, Safari 14+, Edge 80+
Video SDK Credentials: SDK Key and Secret from Marketplace
JWT Token: Server-side generated signature
Browser Feature Requirements
// Check browser compatibility before init
const compatibility = ZoomVideo.checkSystemRequirements();
console.log('Audio:', compatibility.audio);
console.log('Video:', compatibility.video);
console.log('Screen:', compatibility.screen);
// Check feature support
const features = ZoomVideo.checkFeatureRequirements();
console.log('Supported:', features.supportFeatures);
console.log('Unsupported:', features.unSupportFeatures);Optional Pre-Join Diagnostics (Recommended for Reliability)
Use Probe SDK as a readiness gate before client.join(...) when you need to reduce failed starts:
Run diagnostics with ../../probe-sdk/SKILL.md.
Evaluate policy (
allow,warn,block).Start Video SDK join only when policy allows.
Cross-skill flow: ../../general/use-cases/probe-sdk-preflight-readiness-gate.md
Installation
NPM (Recommended)
npm install @zoom/videosdkimport ZoomVideo from '@zoom/videosdk';CDN (Fallback Strategy Recommended)
Note: Some networks/ad blockers can block
source.zoom.us. If you see flaky loads, first try allowlisting the domain in your environment. If needed, consider a fallback (mirror/self-host) only if it's permitted for your use case and you can keep versions in sync.
# Download SDK locally
curl "https://source.zoom.us/videosdk/zoom-video-2.3.12.min.js" -o public/js/zoom-video-sdk.min.js<!-- Use local copy instead of CDN -->
<script src="js/zoom-video-sdk.min.js"></script>// CDN exports as WebVideoSDK, NOT ZoomVideo
const ZoomVideo = WebVideoSDK.default;Quick Start
import ZoomVideo from '@zoom/videosdk';
// 1. Create client (singleton - returns same instance)
const client = ZoomVideo.createClient();
// 2. Initialize SDK
await client.init('en-US', 'Global', { patchJsMedia: true });
// 3. Join session
await client.join(topic, signature, userName, password);
// 4. CRITICAL: Get stream AFTER join
const stream = client.getMediaStream();
// 5. Start media
await stream.startVideo();
await stream.startAudio();
// 6. Attach video to DOM
const videoElement = await stream.attachVideo(userId, VideoQuality.Video_360P);
document.getElementById('video-container').appendChild(videoElement);SDK Lifecycle (CRITICAL ORDER)
The SDK has a strict lifecycle. Violating it causes silent failures.
1. Create client: client = ZoomVideo.createClient()
2. Initialize: await client.init('en-US', 'Global', options)
3. Join session: await client.join(topic, signature, userName, password)
4. Get stream: stream = client.getMediaStream() ← ONLY AFTER JOIN
5. Start media: await stream.startVideo() / await stream.startAudio()Common Mistake:
// WRONG: Getting stream before joining
const stream = client.getMediaStream(); // Returns undefined!
await client.join(...);
// CORRECT: Get stream after joining
await client.join(...);
const stream = client.getMediaStream(); // Works!Critical Gotchas and Best Practices
getMediaStream() ONLY Works After join()
The #1 issue that causes video/audio to fail:
// WRONG
const stream = client.getMediaStream(); // undefined!
await client.join(...);
// CORRECT
await client.join(...);
const stream = client.getMediaStream(); // WorksUse attachVideo() NOT renderVideo()
renderVideo() is deprecated. Use attachVideo() which returns a VideoPlayer element:
import { VideoQuality } from '@zoom/videosdk';
// CORRECT: attachVideo returns element to append
const videoElement = await stream.attachVideo(userId, VideoQuality.Video_360P);
document.getElementById('video-container').appendChild(videoElement);
// WRONG: renderVideo is deprecated
await stream.renderVideo(canvas, userId, ...); // Don't use!Video Rendering is Event-Driven (CRITICAL)
You MUST listen for events to properly render participant videos:
// When another participant's video state changes
client.on('peer-video-state-change', async (payload) => {
const { action, userId } = payload;
if (action === 'Start') {
// Participant turned on video - attach it
const element = await stream.attachVideo(userId, VideoQuality.Video_360P);
container.appendChild(element);
} else if (action === 'Stop') {
// Participant turned off video - detach it
await stream.detachVideo(userId);
}
});
// When participants join/leave
client.on('user-added', (payload) => {
// New participant joined - check if their video is on
const users = client.getAllUser();
// Render videos for users with bVideoOn === true
});
client.on('user-removed', (payload) => {
// Participant left - clean up their video element
stream.detachVideo(payload[0].userId);
});Peer Video on Mid-Session Join
Existing participants' videos won't auto-render when you join mid-session.
// After joining, render existing participants' videos
const renderExistingVideos = async () => {
await new Promise(resolve => setTimeout(resolve, 500));
const users = client.getAllUser();
const currentUserId = client.getCurrentUserInfo().userId;
for (const user of users) {
if (user.bVideoOn && user.userId !== currentUserId) {
const element = await stream.attachVideo(user.userId, VideoQuality.Video_360P);
document.getElementById(`video-${user.userId}`).appendChild(element);
}
}
};CDN Race Condition with ES Modules
When using <script type="module"> with CDN, the SDK may not be loaded yet:
function waitForSDK(timeout = 10000) {
return new Promise((resolve, reject) => {
if (typeof WebVideoSDK !== 'undefined') {
resolve();
return;
}
const start = Date.now();
const check = setInterval(() => {
if (typeof WebVideoSDK !== 'undefined') {
clearInterval(check);
resolve();
} else if (Date.now() - start > timeout) {
clearInterval(check);
reject(new Error('SDK failed to load'));
}
}, 100);
});
}
await waitForSDK();
const ZoomVideo = WebVideoSDK.default;SharedArrayBuffer for HD Video
For optimal performance and HD video, configure these headers on your server:
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corpNote: As of v1.11.2, SharedArrayBuffer is elective (not strictly required).
Check HD Capability Before Enabling
const stream = client.getMediaStream();
// Check if 720p is supported
const hdSupported = stream.isSupportHDVideo();
// Get maximum video quality
const maxQuality = stream.getVideoMaxQuality();
// 0=90P, 1=180P, 2=360P, 3=720P, 4=1080P
// Start video with HD
if (hdSupported) {
await stream.startVideo({ hd: true });
}Screen Share Rendering Mode Check
const stream = client.getMediaStream();
// Check which element type to use
if (stream.isStartShareScreenWithVideoElement()) {
// Use video element
const video = document.getElementById('share-video');
await stream.startShareScreen(video as unknown as HTMLCanvasElement);
} else {
// Use canvas element
const canvas = document.getElementById('share-canvas');
await stream.startShareScreen(canvas);
}Key Features
Video Quality Enum
import { VideoQuality } from '@zoom/videosdk';
VideoQuality.Video_90P // 0
VideoQuality.Video_180P // 1
VideoQuality.Video_360P // 2 (recommended for most cases)
VideoQuality.Video_720P // 3
VideoQuality.Video_1080P // 4Virtual Backgrounds
const stream = client.getMediaStream();
// Always check support first
if (stream.isSupportVirtualBackground()) {
// Blur background
await stream.updateVirtualBackgroundImage('blur');
// Custom image background
await stream.updateVirtualBackgroundImage('https://example.com/bg.jpg');
// Remove virtual background
await stream.updateVirtualBackgroundImage(undefined);
}Video Processor (Custom Effects)
The VideoProcessor class allows you to intercept and modify video frames:
// video-processor-worker.js
class MyVideoProcessor extends VideoProcessor {
processFrame(input, output) {
const ctx = output.getContext('2d');
ctx.drawImage(input, 0, 0);
// Add overlay
ctx.fillStyle = 'white';
ctx.font = '24px Arial';
ctx.fillText('Live', 20, 40);
return true;
}
}WebRTC Mode
Enable WebRTC mode for direct peer-to-peer streaming with HD video support:
await client.init('en-US', 'Global', {
patchJsMedia: true,
webrtc: true // Enable WebRTC mode
});Feature Clients
Access specialized clients from the VideoClient:
| Client | Access Method | Purpose |
|---|---|---|
| Stream | client.getMediaStream() | Video, audio, screen share, devices |
| Chat | client.getChatClient() | Send/receive messages |
| Command | client.getCommandClient() | Custom commands (reactions, etc.) |
| Recording | client.getRecordingClient() | Cloud recording control |
| Transcription | client.getLiveTranscriptionClient() | Live captions |
| LiveStream | client.getLiveStreamClient() | RTMP streaming |
| Subsession | client.getSubsessionClient() | Breakout rooms |
| Whiteboard | client.getWhiteboardClient() | Collaborative whiteboard |
Common Tasks
Start/Stop Video
await stream.startVideo();
await stream.stopVideo();Start/Stop Audio
await stream.startAudio();
await stream.muteAudio();
await stream.unmuteAudio();
await stream.stopAudio();Switch Devices
// Get available devices
const cameras = stream.getCameraList();
const mics = stream.getMicList();
const speakers = stream.getSpeakerList();
// Switch devices
await stream.switchCamera(cameraId);
await stream.switchMicrophone(micId);
await stream.switchSpeaker(speakerId);Screen Sharing
// Start sharing
await stream.startShareScreen(canvas);
// Stop sharing
await stream.stopShareScreen();
// Receive share
client.on('active-share-change', async (payload) => {
if (payload.state === 'Active') {
await stream.startShareView(canvas, payload.userId);
} else {
await stream.stopShareView();
}
});Chat
const chatClient = client.getChatClient();
// Send to everyone
await chatClient.send('Hello, everyone!');
// Send to specific user
await chatClient.sendToUser(userId, 'Private message');
// Receive messages
client.on('chat-on-message', (payload) => {
console.log(`${payload.sender.name}: ${payload.message}`);
});Recording (Host Only)
const recordingClient = client.getRecordingClient();
await recordingClient.startCloudRecording();
await recordingClient.stopCloudRecording();
client.on('recording-change', (payload) => {
console.log('Recording status:', payload.state);
});Leave/End Session
// Leave session (others stay)
await client.leave();
// End session for ALL participants (host only)
await client.leave(true);Error Handling
Common Join Errors
| Error | Cause | Solution |
|---|---|---|
Invalid signature | JWT expired or malformed | Generate new signature |
Session does not exist | Host hasn't started yet | Show "waiting" message, retry |
Permission denied | User denied camera/mic | Request permission again |
Example Error Handler
try {
await client.join(topic, signature, userName, password);
} catch (error) {
if (error.reason?.includes('signature')) {
// Regenerate signature and retry
} else if (error.reason?.includes('Session')) {
// Show "Waiting for host..." and poll
} else if (error.reason?.includes('Permission')) {
// Guide user to enable permissions
}
console.error('Join failed:', error);
}Browser Compatibility
| Feature | Chrome | Firefox | Safari | Edge |
|---|---|---|---|---|
| Video | 80+ | 75+ | 14+ | 80+ |
| Audio | 80+ | 75+ | 14+ | 80+ |
| Screen Share | 80+ | 75+ | 15+ | 80+ |
| Virtual BG | 80+ | 90+ | - | 80+ |
Safari Notes:
Virtual background not supported
Screen sharing requires macOS 15+
CORS Errors (Telemetry)
CORS errors to log-external-gateway.zoom.us are harmless.
These are caused by COOP/COEP headers blocking telemetry requests. They don't affect SDK functionality.
Complete Documentation Library
Core Concepts
SDK Architecture Pattern - Universal 3-step pattern for ANY feature
Singleton Hierarchy - 4-level navigation guide
Complete Examples
Session Join Pattern - JWT auth + session join with full code
Video Rendering - attachVideo() patterns
Screen Share - Send and receive screen shares
Event Handling - Required events
Chat - In-session messaging
Recording - Cloud recording control
Transcription - Live captions
Framework Integrations
React Hooks - Official @zoom/videosdk-react library
Framework Integrations - Next.js, Vue/Nuxt patterns
Troubleshooting
Common Issues - Quick diagnostics & error codes
References
API Reference - Complete method signatures
Events Reference - All event types
SKILL.md - Complete navigation guide
Official Sample Repositories
| Type | Repository |
|---|---|
| Web Sample | videosdk-web-sample |
| React SDK | videosdk-react |
| Next.js | videosdk-nextjs-quickstart |
| Vue/Nuxt | videosdk-vue-nuxt-quickstart |
| Auth Endpoint | videosdk-auth-endpoint-sample |
| UI Toolkit | videosdk-zoom-ui-toolkit-react-sample |
Resources
Official Docs: https://developers.zoom.us/docs/video-sdk/web/
API Reference: https://marketplacefront.zoom.us/sdk/custom/web/modules.html
Dev Forum: https://devforum.zoom.us/
GitHub Samples: https://github.com/zoom/videosdk-web-sample
Need help? Start with SKILL.md for complete navigation.
Merged from video-sdk/web/SKILL.md
Zoom Video SDK Web - Complete Documentation Index
Quick Start Path
If you're new to the SDK, follow this order:
Read the architecture pattern → concepts/sdk-architecture-pattern.md
Universal formula: Create Client → Init → Join → Get Stream → Use
Once you understand this, you can implement any feature
Implement session join → examples/session-join-pattern.md
Complete working JWT + session join code
Listen to events → examples/event-handling.md
CRITICAL: The SDK is event-driven, you must listen for events
Implement video → examples/video-rendering.md
Use attachVideo(), NOT renderVideo()
Troubleshoot any issues → troubleshooting/common-issues.md
Quick diagnostic checklist
Error code tables
Documentation Structure
video-sdk/web/
├── SKILL.md # Main skill overview
├── SKILL.md # This file - navigation guide
│
├── concepts/ # Core architectural patterns
│ ├── sdk-architecture-pattern.md # Universal formula for ANY feature
│ └── singleton-hierarchy.md # 4-level navigation guide
│
├── examples/ # Complete working code
│ ├── session-join-pattern.md # JWT auth + session join
│ ├── video-rendering.md # attachVideo() patterns
│ ├── screen-share.md # Send and receive screen shares
│ ├── event-handling.md # Required events
│ ├── chat.md # Chat implementation
│ ├── command-channel.md # Command channel messaging
│ ├── recording.md # Cloud recording control
│ ├── transcription.md # Live transcription/captions
│ ├── react-hooks.md # Official @zoom/videosdk-react library
│ └── framework-integrations.md # Next.js, Vue/Nuxt, ZFG patterns
│
├── troubleshooting/ # Problem solving guides
│ └── common-issues.md # Quick diagnostic workflow
│
└── references/ # Reference documentation
├── web-reference.md # API hierarchy, methods, error codes
└── events-reference.md # All event typesBy Use Case
I want to build a video app
SDK Architecture Pattern - Understand the pattern
Session Join Pattern - Join sessions
Video Rendering - Display video
Event Handling - Listen for video events
I'm getting runtime errors
Common Issues - Error code tables
"getMediaStream() is undefined" → Call AFTER join() completes
I want to receive screen shares
Screen Share - startShareView() patterns
Event Handling - active-share-change event
I want to send screen shares
Screen Share - startShareScreen() patterns
Check isStartShareScreenWithVideoElement() for element type
I want to use chat
Chat - Send/receive messages
getChatClient() for ChatClient access
I want to record sessions
Recording - Cloud recording (host only)
getRecordingClient() for RecordingClient access
I want to use live transcription
Transcription - Enable live captions
getLiveTranscriptionClient() for LiveTranscriptionClient access
I want to use command channel
Command Channel - Custom signaling between participants
Must call getCommandClient() AFTER join()
I want to implement a specific feature
SDK Architecture Pattern - START HERE!
Singleton Hierarchy - Navigate to the feature
API Reference - Method signatures
I'm using React
React Hooks - Official @zoom/videosdk-react library
Provides hooks: useSession, useSessionUsers, useVideoState, useAudioState
Pre-built components: VideoPlayerComponent, ScreenSharePlayerComponent
I'm using Next.js or Vue/Nuxt
Framework Integrations - SSR considerations
Server-side JWT generation patterns
Client-side only SDK usage
Most Critical Documents
1. SDK Architecture Pattern (MASTER DOCUMENT)
concepts/sdk-architecture-pattern.md
The universal 5-step pattern:
Create client
Initialize SDK
Join session
Get stream
Use features + listen to events
2. Common Issues (MOST COMMON PROBLEMS)
troubleshooting/common-issues.md
Common issues:
getMediaStream() returns undefined
Video not displaying
renderVideo() deprecated
3. Singleton Hierarchy (NAVIGATION MAP)
concepts/singleton-hierarchy.md
4-level deep navigation showing how to reach every feature.
Key Learnings
Critical Discoveries:
getMediaStream() ONLY works after join()
The stream object is not available until session is joined
Use attachVideo() NOT renderVideo()
renderVideo() is deprecated
attachVideo() returns a VideoPlayer element to append to DOM
See: Video Rendering
The SDK is Event-Driven
You MUST listen for events to render participant videos
key events: peer-video-state-change, user-added, user-removed
See: Event Handling
Peer Videos on Mid-Session Join
Existing participants' videos won't auto-render
Must manually iterate getAllUser() and attachVideo()
See: Video Rendering
CDN vs NPM
CDN exports as
WebVideoSDK.default, notZoomVideoSome networks/ad blockers may block
source.zoom.us- allowlist or use a permitted fallback strategySee: Session Join Pattern
SharedArrayBuffer for HD
Required for 720p/1080p video
Need COOP/COEP headers on server
Check with
stream.isSupportHDVideo()
Screen Share Element Type
Check
isStartShareScreenWithVideoElement()for correct element typeSee: Screen Share
Command Channel Setup Order
Must call getCommandClient() AFTER client.join()
Register listeners AFTER join, not before
Web uses getCommandClient() not getCmdChannel()
See: Command Channel
Command Channel is Session-Scoped
Does NOT span across different sessions
Both sender and receiver must be in the same session
Quick Reference
"getMediaStream() returns undefined"
→ Call AFTER join() completes
"Video not showing"
→ Video Rendering - Use attachVideo(), check events
"renderVideo() doesn't work"
→ Video Rendering - Use attachVideo() instead
"How do I implement [feature]?"
"How do I navigate to [client]?"
"What error code means what?"
Document Version
Based on Zoom Video SDK for Web v2.3.x
Happy coding!
Remember: The SDK Architecture Pattern is your key to unlocking the entire SDK. Read it first!
Operations
RUNBOOK.md - 5-minute preflight and debugging checklist.
Files
- ATTRIBUTION.mdAdded by AutoGineer982 B
- LICENSELicence file added by AutoGineer1.1 KiB
- RUNBOOK.md2.5 KiB
- SKILL.md25.8 KiB
- concepts/sdk-architecture-pattern.md8.3 KiB
- concepts/singleton-hierarchy.md18.9 KiB
- examples/chat.md12.0 KiB
- examples/command-channel.md7.1 KiB
- examples/event-handling.md14.1 KiB
- examples/framework-integrations.md10.8 KiB
- examples/react-hooks.md9.8 KiB
- examples/recording.md10.4 KiB
- examples/screen-share.md12.1 KiB
- examples/session-join-pattern.md10.2 KiB
- examples/transcription.md13.9 KiB
- examples/video-rendering.md10.0 KiB
- references/events-reference.md12.8 KiB
- references/web-reference.md15.5 KiB
- references/web.md26.2 KiB
- troubleshooting/common-issues.md11.0 KiB
references/web-reference.md
Zoom Video SDK Web - API Reference
Overview
This reference provides the complete API for the Zoom Video SDK for Web. The SDK follows a hierarchical pattern:
ZoomVideo (module)
└── VideoClient (singleton)
├── Stream (media operations)
└── Feature Clients (chat, recording, etc.)Official API Reference: https://marketplacefront.zoom.us/sdk/custom/web/modules.html
Level 0: ZoomVideo Module
Static Methods
| Method | Returns | Description |
|---|---|---|
createClient() | VideoClient | Creates/returns the singleton client |
destroyClient() | Promise<void> | Destroys the client instance |
checkSystemRequirements() | MediaCompatibility | Check browser compatibility |
checkFeatureRequirements() | SupportFeatures | Check feature support |
getDevices(skip?) | Promise<MediaDeviceInfo[]> | Enumerate media devices |
preloadDependentAssets(path?) | void | Preload SDK assets |
createLocalVideoTrack(id?) | LocalVideoTrack | Create local video track for preview |
createLocalAudioTrack(id?) | LocalAudioTrack | Create local audio track for preview |
VERSION | string | SDK version |
MediaCompatibility Interface
interface MediaCompatibility {
audio: boolean; // Audio support
video: boolean; // Video support
screen: boolean; // Screen share support
}SupportFeatures Interface
interface SupportFeatures {
platform: string; // Browser/platform info
supportFeatures: string[]; // Supported features
unSupportFeatures: string[]; // Unsupported features
}Level 1: VideoClient
Session Lifecycle
| Method | Parameters | Returns | Description |
|---|---|---|---|
init | (language, dependentAssets, options?) | ExecutedResult | Initialize SDK |
join | (topic, token, userName, password?, timeout?) | ExecutedResult | Join session |
leave | (end?) | ExecutedResult | Leave/end session |
on | (event, callback) | void | Subscribe to events |
off | (event, callback) | void | Unsubscribe from events |
InitOptions Interface
interface InitOptions {
patchJsMedia?: boolean; // Patch JS media (recommended: true)
webrtc?: boolean; // Enable WebRTC mode for HD
enforceMultipleVideos?: boolean; // Force multi-video mode
stayAwake?: boolean; // Prevent screen sleep
}Participant Methods
| Method | Returns | Description |
|---|---|---|
getAllUser() | Participant[] | Get all participants |
getCurrentUserInfo() | Participant | Get current user |
getUser(userId) | Participant | undefined | Get user by ID |
getSessionHost() | Participant | undefined | Get session host |
getSessionInfo() | SessionInfo | Get session info |
isHost() | boolean | Is current user host |
isManager() | boolean | Is current user manager |
isOriginalHost() | boolean | Is current user original host |
Host Controls
| Method | Parameters | Returns | Description |
|---|---|---|---|
makeHost | (userId) | ExecutedResult | Make user host |
makeManager | (userId) | ExecutedResult | Make user manager |
revokeManager | (userId) | ExecutedResult | Remove manager |
removeUser | (userId) | ExecutedResult | Remove user from session |
changeName | (name, userId?) | ExecutedResult | Change display name |
reclaimHost | () | ExecutedResult | Reclaim host (original host only) |
Feature Client Getters
| Method | Returns | Description |
|---|---|---|
getMediaStream() | Stream | Get media stream (AFTER join!) |
getChatClient() | ChatClient | Get chat client |
getCommandClient() | CommandChannel | Get command channel |
getRecordingClient() | RecordingClient | Get recording client |
getLiveTranscriptionClient() | LiveTranscriptionClient | Get transcription client |
getLiveStreamClient() | LiveStreamClient | Get live stream client |
getSubsessionClient() | SubsessionClient | Get subsession client |
getWhiteboardClient() | WhiteboardClient | Get whiteboard client |
getBroadcastStreamingClient() | BroadcastStreamingClient | Get broadcast client |
getRealTimeMediaStreamsClient() | RealTimeMediaStreamsClient | Get RTMS client |
getLoggerClient(options?) | LoggerClient | Get logger client |
Participant Interface
interface Participant {
userId: number; // Unique user ID
displayName: string; // Display name
bVideoOn: boolean; // Is video on
muted: boolean; // Is audio muted
audio: '' | 'computer' | 'phone'; // Audio type
sharerOn: boolean; // Is sharing screen
bShareAudioOn: boolean; // Is sharing audio
isHost: boolean; // Is host
}Level 2: Stream (Media Operations)
Video Methods
| Method | Parameters | Returns | Description |
|---|---|---|---|
startVideo | (options?) | ExecutedResult | Start camera |
stopVideo | () | ExecutedResult | Stop camera |
attachVideo | (userId, quality, element?) | Promise<VideoPlayer> | Attach video to DOM |
detachVideo | (userId, element?) | Promise<VideoPlayer | VideoPlayer[]> | Detach video |
switchCamera | (cameraId) | ExecutedResult | Switch camera |
getCameraList | () | MediaDevice[] | Get cameras |
getActiveCamera | () | string | Get active camera ID |
mirrorVideo | (enable) | ExecutedResult | Mirror video |
spotlightVideo | (userId) | ExecutedResult | Spotlight user |
screenshotVideo | (userId?) | Promise<Blob> | Screenshot video |
Video Capability Methods
| Method | Returns | Description |
|---|---|---|
isSupportHDVideo() | boolean | Is HD video supported |
getVideoMaxQuality() | VideoQuality | Get max video quality |
getMaxRenderableVideos() | number | Max renderable videos |
isSupportMultipleVideos() | boolean | Multiple videos support |
isSupportVirtualBackground() | boolean | Virtual BG support |
isCapturingVideo() | boolean | Is capturing video |
VideoQuality Enum
enum VideoQuality {
Video_90P = 0,
Video_180P = 1,
Video_360P = 2,
Video_720P = 3,
Video_1080P = 4
}Virtual Background Methods
| Method | Parameters | Returns | Description |
|---|---|---|---|
updateVirtualBackgroundImage | (image) | ExecutedResult | Set virtual background |
previewVirtualBackground | (canvas, image) | ExecutedResult | Preview virtual BG |
stopPreviewVirtualBackground | () | ExecutedResult | Stop preview |
getVirtualbackgroundStatus | () | VirtualBackgroundStatus | Get VB status |
Virtual Background Options:
'blur': Blur background'https://example.com/image.jpg': Custom image URLundefined: Remove virtual background
Audio Methods
| Method | Parameters | Returns | Description |
|---|---|---|---|
startAudio | (options?) | ExecutedResult | Start audio |
stopAudio | () | ExecutedResult | Stop audio |
muteAudio | (userId?) | ExecutedResult | Mute audio |
unmuteAudio | (userId?) | ExecutedResult | Unmute audio |
muteAllAudio | () | ExecutedResult | Mute all (host) |
unmuteAllAudio | () | ExecutedResult | Unmute all (host) |
switchMicrophone | (micId) | ExecutedResult | Switch microphone |
switchSpeaker | (speakerId) | ExecutedResult | Switch speaker |
getMicList | () | MediaDevice[] | Get microphones |
getSpeakerList | () | MediaDevice[] | Get speakers |
getActiveMicrophone | () | string | Get active mic ID |
getActiveSpeaker | () | string | Get active speaker ID |
isAudioMuted | (userId?) | boolean | Is audio muted |
Screen Share Methods
| Method | Parameters | Returns | Description |
|---|---|---|---|
startShareScreen | (canvas, options?) | ExecutedResult | Start sharing |
stopShareScreen | () | ExecutedResult | Stop sharing |
startShareView | (canvas, userId) | ExecutedResult | View share |
stopShareView | () | ExecutedResult | Stop viewing |
attachShareView | (userId, element?) | Promise<VideoPlayer> | Attach share view |
detachShareView | (userId, element?) | Promise<VideoPlayer> | Detach share view |
pauseShareScreen | () | ExecutedResult | Pause share |
resumeShareScreen | () | ExecutedResult | Resume share |
getActiveShareUserId | () | number | Get sharer user ID |
getShareStatus | () | ShareStatus | Get share status |
getShareUserList | () | Participant[] | Get sharers |
lockShare | (isLocked) | ExecutedResult | Lock share (host) |
setSharePrivilege | (privilege) | ExecutedResult | Set share privilege |
isStartShareScreenWithVideoElement | () | boolean | Use video or canvas |
ScreenShareOption Interface
interface ScreenShareOption {
requestReadReceipt?: boolean; // Request read receipt
secondaryAudio?: boolean; // Share with audio
optimizedForVideo?: boolean; // Optimize for video
}ShareStatus Enum
enum ShareStatus {
Sharing = 'Sharing',
Paused = 'Paused',
End = 'End'
}Processor Methods
| Method | Parameters | Returns | Description |
|---|---|---|---|
createProcessor | (params) | Promise<Processor> | Create processor |
addProcessor | (processor) | Promise<""> | Add processor |
removeProcessor | (processor) | Promise<""> | Remove processor |
isSupportVideoProcessor | () | boolean | Video processor support |
isSupportAudioProcessor | () | boolean | Audio processor support |
isSupportShareProcessor | () | boolean | Share processor support |
Level 2: Feature Clients
ChatClient
| Method | Parameters | Returns | Description |
|---|---|---|---|
send | (message) | ExecutedResult | Send to all |
sendToUser | (userId, message) | ExecutedResult | Send to user |
sendFile | (file, receiverId) | ExecutedResult | Send file |
downloadFile | (fileUrl, options) | ExecutedResult | Download file |
CommandChannel
| Method | Parameters | Returns | Description |
|---|---|---|---|
send | (text) | ExecutedResult | Send to all |
sendToUser | (userId, text) | ExecutedResult | Send to user |
RecordingClient
| Method | Returns | Description |
|---|---|---|
startCloudRecording() | ExecutedResult | Start recording (host) |
stopCloudRecording() | ExecutedResult | Stop recording |
pauseCloudRecording() | ExecutedResult | Pause recording |
resumeCloudRecording() | ExecutedResult | Resume recording |
LiveTranscriptionClient
| Method | Parameters | Returns | Description |
|---|---|---|---|
startLiveTranscription | () | ExecutedResult | Start transcription |
stopLiveTranscription | () | ExecutedResult | Stop transcription |
enableReceivingCaption | (enable) | ExecutedResult | Enable/disable captions |
setSpokenLanguage | (language) | ExecutedResult | Set spoken language |
LiveStreamClient
| Method | Parameters | Returns | Description |
|---|---|---|---|
startLiveStream | (url, key) | ExecutedResult | Start streaming |
stopLiveStream | () | ExecutedResult | Stop streaming |
SubsessionClient
| Method | Parameters | Returns | Description |
|---|---|---|---|
createSubsessions | (names) | ExecutedResult | Create subsessions |
openSubsessions | (rooms) | ExecutedResult | Open subsessions |
closeAllSubsessions | () | ExecutedResult | Close all |
broadcast | (message) | ExecutedResult | Broadcast message |
getSubsessionList | () | Subsession[] | Get subsessions |
Events Reference
Session Events
| Event | Payload | Description |
|---|---|---|
connection-change | ConnectionChangePayload | Connection state changed |
user-added | ParticipantPropertiesPayload[] | Participant joined |
user-removed | ParticipantPropertiesPayload[] | Participant left |
user-updated | ParticipantPropertiesPayload[] | Participant updated |
Video Events
| Event | Payload | Description |
|---|---|---|
peer-video-state-change | {action: 'Start'|'Stop', userId} | Peer video on/off |
video-active-change | {state: VideoActiveState, userId} | Video stream changed |
video-capturing-change | {state: VideoCapturingState} | Capture state changed |
video-dimension-change | {width, height, type} | Video dimensions changed |
Audio Events
| Event | Payload | Description |
|---|---|---|
current-audio-change | {action, source?, type?} | Audio state changed |
active-speaker | ActiveSpeaker[] | Active speakers |
host-ask-unmute-audio | {reason} | Host asks unmute |
auto-play-audio-failed | (none) | Auto-play blocked |
Screen Share Events
| Event | Payload | Description |
|---|---|---|
active-share-change | {state: 'Active'|'Inactive', userId} | Share active state |
peer-share-state-change | {action: 'Start'|'Stop', userId} | Peer share changed |
passively-stop-share | PassiveStopShareReason | Share stopped passively |
share-content-dimension-change | {width, height, type} | Share size changed |
Chat Events
| Event | Payload | Description |
|---|---|---|
chat-on-message | ChatMessage | Message received |
chat-privilege-change | {chatPrivilege} | Privilege changed |
Command Channel Events
| Event | Payload | Description |
|---|---|---|
command-channel-message | {senderId, senderName, text, timestamp} | Command received |
command-channel-status | ConnectionState | Channel status |
Recording Events
| Event | Payload | Description |
|---|---|---|
recording-change | {state: RecordingStatus} | Recording state changed |
individual-recording-change | {state, userId?} | Individual recording |
Transcription Events
| Event | Payload | Description |
|---|---|---|
caption-message | LiveTranscriptionMessage | Caption received |
caption-status | {autoCaption, lang?, ...} | Caption status |
caption-enable | boolean | Caption enabled/disabled |
Media Events
| Event | Payload | Description |
|---|---|---|
device-change | (none) | Device added/removed |
device-permission-change | {name, state} | Permission changed |
network-quality-change | {level, type, userId} | Network quality |
Error Types
type ErrorTypes =
| 'INVALID_OPERATION' // Duplicated operation
| 'INTERNAL_ERROR' // Service unavailable
| 'OPERATION_TIMEOUT' // Timed out
| 'INSUFFICIENT_PRIVILEGES' // Need host/manager
| 'IMPROPER_MEETING_STATE' // Not in meeting
| 'INVALID_PARAMETERS' // Wrong params
| 'OPERATION_LOCKED'; // Property lockedRelated Documentation
Singleton Hierarchy - Navigation guide
SDK Architecture Pattern - Universal pattern
SKILL.md - Main skill overview
Requirements and compatibility
Written for: Claude Code, Claude apps
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Needs: Claude Code frontmatter, Needs network access, Needs Node.js
Security
No issues found by our static scan· No issues found
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Created by
- Zoom
- Publisher
- Anthropic (Official)
- Distributed by
- Anthropic
- Source
- anthropics/knowledge-work-plugins · partner-built/zoom-plugin/skills/video-sdk/web · commit e050c2e
- Licence
- MIT License (redistribution allowed)
- LICENSE (added by AutoGineer from partner-built/zoom-plugin/LICENSE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by Zoom or Anthropic.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download video-sdk-web.zip