Claude
Skills
Sign in
Back

video-sdk/web

Included with Lifetime
$97 forever

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.

Image & Video

What this skill does


# 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](../../meeting-sdk/web/component-view/SKILL.md).
Use [../../probe-sdk/SKILL.md](../../probe-sdk/SKILL.md) as an optional browser/device/network readiness gate before `client.join(...)`.

## Quick Start

### Installation

```bash
bun install @zoom/videosdk --save
# or
npm install @zoom/videosdk --save
```

### Basic Session Setup

```typescript
import ZoomVideo from "@zoom/videosdk";

// 1. Create client
const client = ZoomVideo.createClient();

// 2. Initialize SDK
await client.init("en-US", "Global", { patchJsMedia: true });

// 3. Join session (requires JWT token from your server)
await client.join(sessionName, jwtToken, userName, sessionPassword);

// 4. Get media stream for audio/video control
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

```typescript
// Initialize before joining
await client.init(language, dependentAssets, options?);

// Join session
await client.join(topic, token, userName, password?, idleTimeoutMins?);

// Leave or end session
await client.leave(end?); // end=true ends for all (host only)
```

#### User Management

```typescript
client.getCurrentUserInfo(): Participant;
client.getAllUser(): Participant[];
client.getUser(userId): Participant | undefined;
client.getSessionHost(): Participant | undefined;

// Host/Manager actions
client.makeHost(userId);      // Transfer host
client.makeManager(userId);   // Promote to manager
client.revokeManager(userId); // Revoke manager
client.removeUser(userId);    // Remove participant
client.changeName(name, userId?);
```

#### Feature Clients

```typescript
client.getMediaStream(); // Audio/Video/Screen share
client.getChatClient(); // In-session chat
client.getCommandClient(); // Custom signaling
client.getRecordingClient(); // Cloud recording
client.getSubsessionClient(); // Breakout rooms
client.getLiveTranscriptionClient(); // Captions
client.getLiveStreamClient(); // RTMP streaming
client.getWhiteboardClient(); // Whiteboard
```

### MediaStream (Audio/Video Control)

#### Audio

```typescript
const stream = client.getMediaStream();

// Start audio (requires user gesture)
await stream.startAudio({
  mute?: boolean,
  speakerOnly?: boolean,
  backgroundNoiseSuppression?: boolean,
  microphoneId?: string,
  speakerId?: string,
});

// Control
await stream.muteAudio();
await stream.unmuteAudio();
stream.stopAudio();

// Device management
stream.getMicList(): MediaDevice[];
stream.getSpeakerList(): MediaDevice[];
await stream.switchMicrophone(deviceId);
await stream.switchSpeaker(deviceId);
```

#### Video

```typescript
// Start video (simple call, no options needed)
await stream.startVideo();

// Or with options
await stream.startVideo({
  cameraId?: string,
  hd?: boolean,           // 720p
  fullHd?: boolean,       // 1080p
  mirrored?: boolean,
  virtualBackground?: { imageUrl: string | 'blur' | undefined, cropped?: boolean },
});

// CRITICAL: Attach video to DOM
// 1. Container MUST be a <video-player-container> custom element
// 2. attachVideo returns an element - append it to the container
// 3. Do NOT pass container as third parameter
const videoElement = await stream.attachVideo(userId, VideoQuality.Video_720P);
container.appendChild(videoElement);

// Stop video
await stream.stopVideo();

// Detach video (cleanup)
stream.detachVideo(userId);

// Device management
stream.getCameraList(): MediaDevice[];
await stream.switchCamera(deviceId);
```

#### Screen Share

```typescript
// Start sharing
await stream.startShareScreen({
  broadcastToSubsession: boolean,
  optimizedForSharedVideo: boolean,
  secondaryCameraId: string, // Share secondary camera
});

// Stop sharing
await stream.stopShareScreen();

// View others' share
await stream.startShareView(canvas, userId);
stream.stopShareView();
```

### Events

```typescript
// Connection
client.on("connection-change", (payload) => {
  // payload.state: 'Connected' | 'Reconnecting' | 'Closed' | 'Fail'
});

// Users
client.on("user-added", (participants: Participant[]) => {});
client.on("user-updated", (participants: Participant[]) => {});
client.on("user-removed", (participants: Participant[]) => {});

// Audio
client.on("current-audio-change", (payload) => {
  // payload.action: 'join' | 'leave' | 'muted' | 'unmuted'
});
client.on("active-speaker", (payload) => {
  // payload.activeSpeaker: { oderId: number, oderId?: number }[]
});

// Video
client.on("video-active-change", (payload) => {
  // payload.userId, payload.state: 'Active' | 'Inactive'
});
client.on("peer-video-state-change", (payload) => {
  // payload.userId, payload.action: 'Start' | 'Stop'
});

// Screen Share
client.on("active-share-change", (payload) => {
  // payload.userId, payload.state: 'Active' | 'Inactive'
});
client.on("peer-share-state-change", (payload) => {
  // payload.userId, payload.action: 'Start' | 'Stop'
});

// Chat
client.on("chat-on-message", (payload) => {
  // payload.message, payload.sender, payload.timestamp
});

// Device
client.on("device-change", () => {
  // Re-enumerate devices
});
```

## Framework-Specific Implementation Guides

For complete implementation examples with full project setup, hooks/composables/services, and components:

- **[references/react.md](references/react.md)** - React 19 + Vite 7 + TypeScript + shadcn/ui implementation
- **[references/vue.md](references/vue.md)** - Vue 3 + Vite 7 + TypeScript + shadcn-vue implementation
- **[references/angular.md](references/angular.md)** - Angular 21 + Standalone Components + Signals implementation
- **[references/svelte.md](references/svelte.md)** - Svelte 5 + Runes + Vite 7 + TypeScript implementation

### Quick Setup Requirements

**All frameworks MUST configure:**

1. **COOP/COEP Headers** (for SharedArrayBuffer support):

```typescript
// vite.config.ts
server: {
  headers: {
    'Cross-Origin-Opener-Policy': 'same-origin',
    'Cross-Origin-Embedder-Policy': 'require-corp',
  },
}
```

2. **TypeScript Custom Elements** (for video rendering):

```typescript
// src/types/zoom-elements.d.ts
declare namespace JSX {
  interface IntrinsicElements {
    "video-player-container": React.DetailedHTMLProps<
      React.HTMLAttributes<HTMLElement>,
      HTMLElement
    >;
  }
}
```

### Core Implementation Pattern

All implementations should follow this pattern:

1. **Client Management** - Singleton client with init/join/leave lifecycle
2. **Media Stream** - Audio/video/screen share controls with state sync
3. **Participants** - User list with video state change listeners
4. **Video Rendering** - Use `video-player-container` + `attachVideo()`
5. **Event Handling** - Connection, audio, video, chat events
6. **Error Handling** - Map SDK
Files: 31
Size: 451.3 KB
Complexity: 77/100
Category: Image & Video

Related in Image & Video