iiuniversitet.ruЦентр обучения нейросетямОткрыть каталог

Видеосессии в браузере через Zoom SDK

Руководство разработчика: как создать в браузере видеоприложение на JavaScript с Zoom Video SDK, демонстрацией экрана, записью, чатом и транскрипцией.

СкиллAnthropic (партнёр: Zoom)ClaudeMITНужен терминалПроверка не требуетсяСлужебный: его вызывают другие скиллы
Что делает
Руководство разработчика: как создать в браузере видеоприложение на JavaScript с Zoom Video SDK, демонстрацией экрана, записью, чатом и транскрипцией.
Когда брать
Когда нужно создать на сайте или в веб-приложении собственную видеосессию: вход, показ видео участников, звук, чат, запись.
Когда не брать
Если нужен встроенный интерфейс настоящей встречи Zoom: для этого есть Meeting SDK.
Пример запроса
Помоги создать на JavaScript страницу с видеозвонком: вход в сессию по теме, камера, микрофон и видео собеседников.
Нужно подключить
терминал

Входит в плагин zoom-plugin. В Cowork и Claude Code можно поставить плагин целиком.

Как включить

  1. Скачайте архив и распакуйте его.
  2. Положите папку video-sdk-web в ~/.claude/skills/.
  3. Откройте Claude Code и опишите задачу своими словами: Claude подхватит скилл по описанию.

Текст

---
name: video-sdk/web
description: "Zoom Video SDK для веба - интеграция на JavaScript/TypeScript для видеосессий в браузере, общения в реальном времени, демонстрации экрана, записи и живой транскрипции"
user-invocable: false
triggers:
  - "video sdk web"
  - "custom video web"
  - "attachvideo"
  - "peer-video-state-change"
  - "web videosdk"
---

Zoom Video SDK - веб-разработка

Экспертное руководство по разработке с Zoom Video SDK для веба. Этот SDK позволяет создавать собственные видеоприложения в браузере: видео и звук в реальном времени, демонстрация экрана, облачная запись, прямые трансляции, чат и живая транскрипция.

Этот скилл предназначен для собственных видеосессий, а не для встроенных встреч Zoom. Если пользователю нужен собственный интерфейс для настоящей встречи Zoom, направь его в [../../meeting-sdk/web/component-view/SKILL.md](../../meeting-sdk/web/component-view/SKILL.md).

Официальная документация: https://developers.zoom.us/docs/video-sdk/web/ Справочник API: https://marketplacefront.zoom.us/sdk/custom/web/modules.html Репозиторий с примерами: https://github.com/zoom/videosdk-web-sample

Быстрые ссылки

Впервые работаешь с Video SDK? Иди по этому пути:

  1. [Архитектурный шаблон SDK](concepts/sdk-architecture-pattern.md) - Универсальный трёхшаговый шаблон для ЛЮБОЙ функции
  2. [Шаблон входа в сессию](examples/session-join-pattern.md) - Полный рабочий код входа в сессию
  3. [Отрисовка видео](examples/video-rendering.md) - Показ видео через attachVideo()
  4. [Обработка событий](examples/event-handling.md) - Обязательные события для видео и звука

Справочные материалы:

  • [Иерархия одиночек (singleton)](concepts/singleton-hierarchy.md) - Четырёхуровневая карта навигации по SDK
  • [Справочник API](references/web-reference.md) - Методы, события, коды ошибок
  • [SKILL.md](SKILL.md) - Полная навигация по документации
  • [../../probe-sdk/SKILL.md](../../probe-sdk/SKILL.md) - Необязательная диагностика готовности браузера, устройств и сети перед входом

Что-то не работает?

  • Видео не отображается → [Отрисовка видео](examples/video-rendering.md) (используй attachVideo, а не renderVideo)
  • getMediaStream() возвращает undefined → вызывай ПОСЛЕ завершения join()
  • Быстрая диагностика → [Частые проблемы](troubleshooting/common-issues.md)

Обзор SDK

Zoom Video SDK для веба - это библиотека JavaScript, которая предоставляет:

  • Управление сессиями: вход в сессии Video SDK и выход из них
  • Видео и звук: запуск и остановка камеры и микрофона
  • Демонстрация экрана: показ экрана или вкладок браузера
  • Облачная запись: запись сессий в облако Zoom
  • Прямые трансляции: трансляция на RTMP-адреса
  • Чат: обмен сообщениями во время сессии
  • Командный канал: пересылка собственных команд
  • Живая транскрипция: распознавание речи в реальном времени
  • Подсессии: поддержка комнат для групповой работы
  • Доска: возможности совместной доски
  • Виртуальный фон: размытие или собственное изображение

Предварительные требования

Системные требования

  • Современный браузер: Chrome 80+, Firefox 75+, Safari 14+, Edge 80+
  • Учётные данные Video SDK: ключ и секрет SDK из Marketplace
  • Токен JWT: подпись, созданная на стороне сервера

Требования к возможностям браузера

// 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);

Необязательная диагностика перед входом (рекомендуется для надёжности)

Используй Probe SDK как проверку готовности перед client.join(...), когда нужно сократить число неудачных запусков:

  1. Запусти диагностику через [../../probe-sdk/SKILL.md](../../probe-sdk/SKILL.md).
  2. Оцени результат по политике (allow, warn, block).
  3. Начинай вход через Video SDK, только если политика это разрешает.

Сквозной процесс между скиллами: [../../general/use-cases/probe-sdk-preflight-readiness-gate.md](../../general/use-cases/probe-sdk-preflight-readiness-gate.md)

Установка

NPM (рекомендуется)

npm install @zoom/videosdk
import ZoomVideo from '@zoom/videosdk';

CDN (рекомендуется запасной вариант)

Примечание: в некоторых сетях и блокировщиках рекламы source.zoom.us может блокироваться. Если загрузка нестабильна, сначала попробуй добавить домен в список разрешённых в своей среде. Если нужно, рассмотри запасной вариант (зеркало или самостоятельное размещение), только если он допустим для твоего случая и ты можешь поддерживать версии в синхронизированном виде.

# 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;

Быстрый старт

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 (ВАЖЕН ПОРЯДОК)

У SDK строгий жизненный цикл. Нарушение порядка приводит к тихим сбоям.

1. Создать клиент:        client = ZoomVideo.createClient()
2. Инициализировать:      await client.init('en-US', 'Global', options)
3. Войти в сессию:        await client.join(topic, signature, userName, password)
4. Получить поток:        stream = client.getMediaStream()  ← ТОЛЬКО ПОСЛЕ ВХОДА
5. Запустить медиа:       await stream.startVideo() / await stream.startAudio()

Типичная ошибка:

// 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!

Критические подводные камни и лучшие практики

getMediaStream() работает ТОЛЬКО после join()

Проблема №1, из-за которой не работают видео и звук:

// WRONG
const stream = client.getMediaStream();  // undefined!
await client.join(...);

// CORRECT
await client.join(...);
const stream = client.getMediaStream();  // Works

Используй attachVideo(), а НЕ renderVideo()

renderVideo() устарел. Используй attachVideo(), который возвращает элемент VideoPlayer:

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!

Отрисовка видео работает на событиях (ВАЖНО)

Чтобы правильно показывать видео участников, ты ОБЯЗАН слушать события:

// 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);
});

Видео других участников при входе в середине сессии

Видео уже присутствующих участников не отображается автоматически, если ты вошёл в середине сессии.

// 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 и ES-модулями

При использовании <script type="module"> с CDN SDK может быть ещё не загружен:

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 для HD-видео

Для оптимальной производительности и HD-видео настрой на своём сервере такие заголовки:

Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp

Примечание: начиная с v1.11.2 SharedArrayBuffer необязателен (строго не требуется).

Проверяй поддержку HD перед включением

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 });
}

Проверка режима отрисовки демонстрации экрана

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);
}

Основные возможности

Перечисление качества видео

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 // 4

Виртуальные фоны

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);
}

Видеопроцессор (собственные эффекты)

Класс VideoProcessor позволяет перехватывать и изменять кадры видео:

// 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

Включи режим WebRTC для прямой потоковой передачи между участниками (peer-to-peer) с поддержкой HD-видео:

await client.init('en-US', 'Global', {
  patchJsMedia: true,
  webrtc: true  // Enable WebRTC mode
});

Клиенты возможностей

Специализированные клиенты доступны из VideoClient:

КлиентСпособ доступаНазначение
Streamclient.getMediaStream()Видео, звук, демонстрация экрана, устройства
Chatclient.getChatClient()Отправка и приём сообщений
Commandclient.getCommandClient()Собственные команды (реакции и др.)
Recordingclient.getRecordingClient()Управление облачной записью
Transcriptionclient.getLiveTranscriptionClient()Живые субтитры
LiveStreamclient.getLiveStreamClient()Трансляция по RTMP
Subsessionclient.getSubsessionClient()Комнаты для групповой работы
Whiteboardclient.getWhiteboardClient()Совместная доска

Типовые задачи

Запуск и остановка видео

await stream.startVideo();
await stream.stopVideo();

Запуск и остановка звука

await stream.startAudio();
await stream.muteAudio();
await stream.unmuteAudio();
await stream.stopAudio();

Переключение устройств

// 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);

Демонстрация экрана

// 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();
  }
});

Чат

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}`);
});

Запись (только ведущий)

const recordingClient = client.getRecordingClient();

await recordingClient.startCloudRecording();
await recordingClient.stopCloudRecording();

client.on('recording-change', (payload) => {
  console.log('Recording status:', payload.state);
});

Выход из сессии и её завершение

// Leave session (others stay)
await client.leave();

// End session for ALL participants (host only)
await client.leave(true);

Обработка ошибок

Частые ошибки входа

ОшибкаПричинаРешение
Invalid signatureJWT истёк или неправильно сформированСоздай новую подпись
Session does not existВедущий ещё не начал сессиюПокажи сообщение «ожидание» и повтори попытку
Permission deniedПользователь запретил камеру/микрофонЗапроси разрешение ещё раз

Пример обработчика ошибок

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);
}

Совместимость с браузерами

ФункцияChromeFirefoxSafariEdge
Видео80+75+14+80+
Звук80+75+14+80+
Демонстрация экрана80+75+15+80+
Виртуальный фон80+90+-80+

Примечания по Safari:

  • Виртуальный фон не поддерживается
  • Для демонстрации экрана нужна macOS 15+

Ошибки CORS (телеметрия)

**Ошибки CORS при обращении к log-external-gateway.zoom.us безвредны.**

Их вызывают заголовки COOP/COEP, блокирующие запросы телеметрии. На работу SDK они не влияют.

Полная библиотека документации

Основные понятия

  • [Архитектурный шаблон SDK](concepts/sdk-architecture-pattern.md) - Универсальный трёхшаговый шаблон для ЛЮБОЙ функции
  • [Иерархия одиночек](concepts/singleton-hierarchy.md) - Четырёхуровневый путеводитель

Полные примеры

  • [Шаблон входа в сессию](examples/session-join-pattern.md) - Аутентификация JWT и вход в сессию с полным кодом
  • [Отрисовка видео](examples/video-rendering.md) - Шаблоны attachVideo()
  • [Демонстрация экрана](examples/screen-share.md) - Отправка и приём демонстрации экрана
  • [Обработка событий](examples/event-handling.md) - Обязательные события
  • [Чат](examples/chat.md) - Обмен сообщениями во время сессии
  • [Запись](examples/recording.md) - Управление облачной записью
  • [Транскрипция](examples/transcription.md) - Живые субтитры

Интеграция с фреймворками

  • [Хуки React](examples/react-hooks.md) - Официальная библиотека @zoom/videosdk-react
  • [Интеграция с фреймворками](examples/framework-integrations.md) - Шаблоны для Next.js, Vue/Nuxt

Устранение неполадок

  • [Частые проблемы](troubleshooting/common-issues.md) - Быстрая диагностика и коды ошибок

Справочные материалы

  • [Справочник API](references/web-reference.md) - Полные сигнатуры методов
  • [Справочник событий](references/events-reference.md) - Все типы событий
  • [SKILL.md](SKILL.md) - Полный путеводитель по навигации

Официальные репозитории с примерами

ТипРепозиторий
Веб-примерvideosdk-web-sample
React SDKvideosdk-react
Next.jsvideosdk-nextjs-quickstart
Vue/Nuxtvideosdk-vue-nuxt-quickstart
Конечная точка аутентификацииvideosdk-auth-endpoint-sample
UI Toolkitvideosdk-zoom-ui-toolkit-react-sample

Ресурсы


Нужна помощь? Начни с [SKILL.md](SKILL.md): там полная навигация.

Объединено из video-sdk/web/SKILL.md

Zoom Video SDK для веба - полный указатель документации

Путь быстрого старта

Если ты впервые работаешь с SDK, иди в таком порядке:

  1. Прочитай архитектурный шаблон → [concepts/sdk-architecture-pattern.md](concepts/sdk-architecture-pattern.md)
  2. Универсальная формула: создать клиент → инициализировать → войти → получить поток → использовать
  3. Поняв её, ты сможешь реализовать любую функцию
  1. Реализуй вход в сессию → [examples/session-join-pattern.md](examples/session-join-pattern.md)
  2. Полный рабочий код с JWT и входом в сессию
  1. Слушай события → [examples/event-handling.md](examples/event-handling.md)
  2. ВАЖНО: SDK работает на событиях, их нужно слушать
  1. Реализуй видео → [examples/video-rendering.md](examples/video-rendering.md)
  2. Используй attachVideo(), а НЕ renderVideo()
  1. Разбери любые проблемы → [troubleshooting/common-issues.md](troubleshooting/common-issues.md)
  2. Контрольный список быстрой диагностики
  3. Таблицы кодов ошибок

Структура документации

video-sdk/web/
├── SKILL.md                           # Общий обзор скилла
├── SKILL.md                           # Этот файл - навигация по документации
│
├── concepts/                          # Основные архитектурные шаблоны
│   ├── sdk-architecture-pattern.md    # Универсальная формула для ЛЮБОЙ функции
│   └── singleton-hierarchy.md         # Четырёхуровневый путеводитель
│
├── examples/                          # Полные рабочие примеры кода
│   ├── session-join-pattern.md        # Аутентификация JWT и вход в сессию
│   ├── video-rendering.md             # Шаблоны attachVideo()
│   ├── screen-share.md                # Отправка и приём демонстрации экрана
│   ├── event-handling.md              # Обязательные события
│   ├── chat.md                        # Реализация чата
│   ├── command-channel.md             # Сообщения командного канала
│   ├── recording.md                   # Управление облачной записью
│   ├── transcription.md               # Живая транскрипция и субтитры
│   ├── react-hooks.md                 # Официальная библиотека @zoom/videosdk-react
│   └── framework-integrations.md      # Шаблоны для Next.js, Vue/Nuxt, ZFG
│
├── troubleshooting/                   # Руководства по решению проблем
│   └── common-issues.md               # Порядок быстрой диагностики
│
└── references/                        # Справочная документация
    ├── web-reference.md               # Иерархия API, методы, коды ошибок
    └── events-reference.md            # Все типы событий

По сценариям использования

Я хочу создать видеоприложение

  1. [Архитектурный шаблон SDK](concepts/sdk-architecture-pattern.md) - Пойми шаблон
  2. [Шаблон входа в сессию](examples/session-join-pattern.md) - Входи в сессии
  3. [Отрисовка видео](examples/video-rendering.md) - Показывай видео
  4. [Обработка событий](examples/event-handling.md) - Слушай события видео

У меня ошибки при выполнении

  1. [Частые проблемы](troubleshooting/common-issues.md) - Таблицы кодов ошибок
  2. «getMediaStream() is undefined» → вызывай ПОСЛЕ завершения join()

Я хочу принимать демонстрацию экрана

  1. [Демонстрация экрана](examples/screen-share.md) - Шаблоны startShareView()
  2. [Обработка событий](examples/event-handling.md) - Событие active-share-change

Я хочу отправлять демонстрацию экрана

  1. [Демонстрация экрана](examples/screen-share.md) - Шаблоны startShareScreen()
  2. Проверь isStartShareScreenWithVideoElement(), чтобы узнать тип элемента

Я хочу использовать чат

  1. [Чат](examples/chat.md) - Отправка и приём сообщений
  2. getChatClient() для доступа к ChatClient

Я хочу записывать сессии

  1. [Запись](examples/recording.md) - Облачная запись (только ведущий)
  2. getRecordingClient() для доступа к RecordingClient

Я хочу использовать живую транскрипцию

  1. [Транскрипция](examples/transcription.md) - Включение живых субтитров
  2. getLiveTranscriptionClient() для доступа к LiveTranscriptionClient

Я хочу использовать командный канал

  1. [Командный канал](examples/command-channel.md) - Собственные сигналы между участниками
  2. getCommandClient() нужно вызывать ПОСЛЕ join()

Я хочу реализовать конкретную функцию

  1. [Архитектурный шаблон SDK](concepts/sdk-architecture-pattern.md) - НАЧНИ ОТСЮДА!
  2. [Иерархия одиночек](concepts/singleton-hierarchy.md) - Найди путь к функции
  3. [Справочник API](references/web-reference.md) - Сигнатуры методов

Я использую React

  1. [Хуки React](examples/react-hooks.md) - Официальная библиотека @zoom/videosdk-react
  2. Предоставляет хуки: useSession, useSessionUsers, useVideoState, useAudioState
  3. Готовые компоненты: VideoPlayerComponent, ScreenSharePlayerComponent

Я использую Next.js или Vue/Nuxt

  1. [Интеграция с фреймворками](examples/framework-integrations.md) - Особенности SSR
  2. Шаблоны создания JWT на сервере
  3. Использование SDK только на стороне клиента

Самые важные документы

1. Архитектурный шаблон SDK (ГЛАВНЫЙ ДОКУМЕНТ)

[concepts/sdk-architecture-pattern.md](concepts/sdk-architecture-pattern.md)

Универсальный пятишаговый шаблон:

  1. Создать клиент
  2. Инициализировать SDK
  3. Войти в сессию
  4. Получить поток
  5. Использовать функции и слушать события

2. Частые проблемы (САМЫЕ РАСПРОСТРАНЁННЫЕ СБОИ)

[troubleshooting/common-issues.md](troubleshooting/common-issues.md)

Частые проблемы:

  • getMediaStream() возвращает undefined
  • Видео не отображается
  • renderVideo() устарел

3. Иерархия одиночек (КАРТА НАВИГАЦИИ)

[concepts/singleton-hierarchy.md](concepts/singleton-hierarchy.md)

Четырёхуровневая навигация, показывающая, как добраться до любой функции.


Главные выводы

Критические находки:

  1. getMediaStream() работает ТОЛЬКО после join()
  2. Объект потока недоступен, пока не выполнен вход в сессию
  3. См.: [Архитектурный шаблон SDK](concepts/sdk-architecture-pattern.md)
  1. Используй attachVideo(), а НЕ renderVideo()
  2. renderVideo() устарел
  3. attachVideo() возвращает элемент VideoPlayer для добавления в DOM
  4. См.: [Отрисовка видео](examples/video-rendering.md)
  1. SDK работает на событиях
  2. Ты ОБЯЗАН слушать события, чтобы показывать видео участников
  3. Ключевые события: peer-video-state-change, user-added, user-removed
  4. См.: [Обработка событий](examples/event-handling.md)
  1. Видео других участников при входе в середине сессии
  2. Видео уже присутствующих участников не отображается автоматически
  3. Нужно вручную перебрать getAllUser() и вызвать attachVideo()
  4. См.: [Отрисовка видео](examples/video-rendering.md)
  1. CDN или NPM
  2. CDN экспортирует WebVideoSDK.default, а не ZoomVideo
  3. В некоторых сетях и блокировщиках рекламы source.zoom.us может блокироваться - добавь его в список разрешённых или используй допустимый запасной вариант
  4. См.: [Шаблон входа в сессию](examples/session-join-pattern.md)
  1. SharedArrayBuffer для HD
  2. Нужен для видео 720p/1080p
  3. Требуются заголовки COOP/COEP на сервере
  4. Проверка через stream.isSupportHDVideo()
  1. Тип элемента для демонстрации экрана
  2. Проверь isStartShareScreenWithVideoElement(), чтобы узнать нужный тип элемента
  3. См.: [Демонстрация экрана](examples/screen-share.md)
  1. Порядок настройки командного канала
  2. getCommandClient() нужно вызывать ПОСЛЕ client.join()
  3. Регистрируй слушателей ПОСЛЕ входа, а не до
  4. В вебе используется getCommandClient(), а не getCmdChannel()
  5. См.: [Командный канал](examples/command-channel.md)
  1. Командный канал привязан к сессии
  2. Он НЕ работает между разными сессиями
  3. Отправитель и получатель должны быть в одной сессии

Краткий справочник

«getMediaStream() возвращает undefined»

→ Вызывай ПОСЛЕ завершения join()

«Видео не отображается»

→ [Отрисовка видео](examples/video-rendering.md) - используй attachVideo(), проверь события

«renderVideo() не работает»

→ [Отрисовка видео](examples/video-rendering.md) - используй attachVideo() вместо него

«Как реализовать [функцию]?»

→ [Архитектурный шаблон SDK](concepts/sdk-architecture-pattern.md)

«Как добраться до [клиента]?»

→ [Иерархия одиночек](concepts/singleton-hierarchy.md)

«Что означает этот код ошибки?»

→ [Частые проблемы](troubleshooting/common-issues.md)


Версия документа

Основано на Zoom Video SDK для веба v2.3.x


Приятного программирования!

Помни: [архитектурный шаблон SDK](concepts/sdk-architecture-pattern.md) - это ключ ко всему SDK. Прочитай его первым!

Операции

  • [RUNBOOK.md](RUNBOOK.md) - пятиминутная предварительная проверка и контрольный список отладки.

Перевод: iiuniversitet. Оригинал: https://github.com/anthropics/knowledge-work-plugins/tree/main/partner-built/zoom-plugin/skills/video-sdk/web, лицензия MIT. Изменения: перевод на русский язык.

Оригинал на английском
---
name: video-sdk/web
description: "Zoom Video SDK for Web - JavaScript/TypeScript integration for browser-based video sessions, real-time communication, screen sharing, recording, and live transcription"
user-invocable: false
triggers:
  - "video sdk web"
  - "custom video web"
  - "attachvideo"
  - "peer-video-state-change"
  - "web videosdk"
---

# 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](../../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:**

1. **[SDK Architecture Pattern](concepts/sdk-architecture-pattern.md)** - Universal 3-step pattern for ANY feature
2. **[Session Join Pattern](examples/session-join-pattern.md)** - Complete working code to join a session
3. **[Video Rendering](examples/video-rendering.md)** - Display video with attachVideo()
4. **[Event Handling](examples/event-handling.md)** - Required events for video/audio

**Reference:**
- **[Singleton Hierarchy](concepts/singleton-hierarchy.md)** - 4-level SDK navigation map
- **[API Reference](references/web-reference.md)** - Methods, events, error codes
- **[SKILL.md](SKILL.md)** - Complete documentation navigation
- **[../../probe-sdk/SKILL.md](../../probe-sdk/SKILL.md)** - Optional browser/device/network readiness diagnostics before join

**Having issues?**
- Video not showing → [Video Rendering](examples/video-rendering.md) (use attachVideo, not renderVideo)
- getMediaStream() returns undefined → Call AFTER join() completes
- Quick diagnostics → [Common Issues](troubleshooting/common-issues.md)

## 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](https://marketplace.zoom.us/)
- **JWT Token**: Server-side generated signature

### Browser Feature Requirements

```javascript
// 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:

1. Run diagnostics with [../../probe-sdk/SKILL.md](../../probe-sdk/SKILL.md).
2. Evaluate policy (`allow`, `warn`, `block`).
3. Start Video SDK join only when policy allows.

Cross-skill flow: [../../general/use-cases/probe-sdk-preflight-readiness-gate.md](../../general/use-cases/probe-sdk-preflight-readiness-gate.md)

## Installation

### NPM (Recommended)

```bash
npm install @zoom/videosdk
```

```javascript
import 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.

```bash
# Download SDK locally
curl "https://source.zoom.us/videosdk/zoom-video-2.3.12.min.js" -o public/js/zoom-video-sdk.min.js
```

```html
<!-- Use local copy instead of CDN -->
<script src="js/zoom-video-sdk.min.js"></script>
```

```javascript
// CDN exports as WebVideoSDK, NOT ZoomVideo
const ZoomVideo = WebVideoSDK.default;
```

## Quick Start

```javascript
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:**

```javascript
// 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:

```javascript
// WRONG
const stream = client.getMediaStream();  // undefined!
await client.join(...);

// CORRECT
await client.join(...);
const stream = client.getMediaStream();  // Works
```

### Use attachVideo() NOT renderVideo()

`renderVideo()` is **deprecated**. Use `attachVideo()` which returns a VideoPlayer element:

```javascript
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:

```javascript
// 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.**

```javascript
// 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:

```javascript
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-corp
```

**Note:** As of v1.11.2, SharedArrayBuffer is elective (not strictly required).

### Check HD Capability Before Enabling

```javascript
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

```javascript
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

```javascript
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 // 4
```

### Virtual Backgrounds

```javascript
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:

```javascript
// 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:

```javascript
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

```javascript
await stream.startVideo();
await stream.stopVideo();
```

### Start/Stop Audio

```javascript
await stream.startAudio();
await stream.muteAudio();
await stream.unmuteAudio();
await stream.stopAudio();
```

### Switch Devices

```javascript
// 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

```javascript
// 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

```javascript
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)

```javascript
const recordingClient = client.getRecordingClient();

await recordingClient.startCloudRecording();
await recordingClient.stopCloudRecording();

client.on('recording-change', (payload) => {
  console.log('Recording status:', payload.state);
});
```

### Leave/End Session

```javascript
// 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

```javascript
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](concepts/sdk-architecture-pattern.md)** - Universal 3-step pattern for ANY feature
- **[Singleton Hierarchy](concepts/singleton-hierarchy.md)** - 4-level navigation guide

### Complete Examples
- **[Session Join Pattern](examples/session-join-pattern.md)** - JWT auth + session join with full code
- **[Video Rendering](examples/video-rendering.md)** - attachVideo() patterns
- **[Screen Share](examples/screen-share.md)** - Send and receive screen shares
- **[Event Handling](examples/event-handling.md)** - Required events
- **[Chat](examples/chat.md)** - In-session messaging
- **[Recording](examples/recording.md)** - Cloud recording control
- **[Transcription](examples/transcription.md)** - Live captions

### Framework Integrations
- **[React Hooks](examples/react-hooks.md)** - Official @zoom/videosdk-react library
- **[Framework Integrations](examples/framework-integrations.md)** - Next.js, Vue/Nuxt patterns

### Troubleshooting
- **[Common Issues](troubleshooting/common-issues.md)** - Quick diagnostics & error codes

### References
- **[API Reference](references/web-reference.md)** - Complete method signatures
- **[Events Reference](references/events-reference.md)** - All event types
- **[SKILL.md](SKILL.md)** - Complete navigation guide

## Official Sample Repositories

| Type | Repository |
|------|------------|
| Web Sample | [videosdk-web-sample](https://github.com/zoom/videosdk-web-sample) |
| React SDK | [videosdk-react](https://github.com/zoom/videosdk-react) |
| Next.js | [videosdk-nextjs-quickstart](https://github.com/zoom/videosdk-nextjs-quickstart) |
| Vue/Nuxt | [videosdk-vue-nuxt-quickstart](https://github.com/zoom/videosdk-vue-nuxt-quickstart) |
| Auth Endpoint | [videosdk-auth-endpoint-sample](https://github.com/zoom/videosdk-auth-endpoint-sample) |
| UI Toolkit | [videosdk-zoom-ui-toolkit-react-sample](https://github.com/zoom/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](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:**

1. **Read the architecture pattern** → [concepts/sdk-architecture-pattern.md](concepts/sdk-architecture-pattern.md)
   - Universal formula: Create Client → Init → Join → Get Stream → Use
   - Once you understand this, you can implement any feature

2. **Implement session join** → [examples/session-join-pattern.md](examples/session-join-pattern.md)
   - Complete working JWT + session join code

3. **Listen to events** → [examples/event-handling.md](examples/event-handling.md)
   - **CRITICAL**: The SDK is event-driven, you must listen for events

4. **Implement video** → [examples/video-rendering.md](examples/video-rendering.md)
   - Use attachVideo(), NOT renderVideo()

5. **Troubleshoot any issues** → [troubleshooting/common-issues.md](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 types
```

---

## By Use Case

### I want to build a video app
1. [SDK Architecture Pattern](concepts/sdk-architecture-pattern.md) - Understand the pattern
2. [Session Join Pattern](examples/session-join-pattern.md) - Join sessions
3. [Video Rendering](examples/video-rendering.md) - Display video
4. [Event Handling](examples/event-handling.md) - Listen for video events

### I'm getting runtime errors
1. [Common Issues](troubleshooting/common-issues.md) - Error code tables
2. "getMediaStream() is undefined" → Call AFTER join() completes

### I want to receive screen shares
1. [Screen Share](examples/screen-share.md) - startShareView() patterns
2. [Event Handling](examples/event-handling.md) - active-share-change event

### I want to send screen shares
1. [Screen Share](examples/screen-share.md) - startShareScreen() patterns
2. Check isStartShareScreenWithVideoElement() for element type

### I want to use chat
1. [Chat](examples/chat.md) - Send/receive messages
2. getChatClient() for ChatClient access

### I want to record sessions
1. [Recording](examples/recording.md) - Cloud recording (host only)
2. getRecordingClient() for RecordingClient access

### I want to use live transcription
1. [Transcription](examples/transcription.md) - Enable live captions
2. getLiveTranscriptionClient() for LiveTranscriptionClient access

### I want to use command channel
1. [Command Channel](examples/command-channel.md) - Custom signaling between participants
2. Must call getCommandClient() AFTER join()

### I want to implement a specific feature
1. [SDK Architecture Pattern](concepts/sdk-architecture-pattern.md) - **START HERE!**
2. [Singleton Hierarchy](concepts/singleton-hierarchy.md) - Navigate to the feature
3. [API Reference](references/web-reference.md) - Method signatures

### I'm using React
1. [React Hooks](examples/react-hooks.md) - Official @zoom/videosdk-react library
2. Provides hooks: useSession, useSessionUsers, useVideoState, useAudioState
3. Pre-built components: VideoPlayerComponent, ScreenSharePlayerComponent

### I'm using Next.js or Vue/Nuxt
1. [Framework Integrations](examples/framework-integrations.md) - SSR considerations
2. Server-side JWT generation patterns
3. Client-side only SDK usage

---

## Most Critical Documents

### 1. SDK Architecture Pattern (MASTER DOCUMENT)
**[concepts/sdk-architecture-pattern.md](concepts/sdk-architecture-pattern.md)**

The universal 5-step pattern:
1. Create client
2. Initialize SDK
3. Join session
4. Get stream
5. Use features + listen to events

### 2. Common Issues (MOST COMMON PROBLEMS)
**[troubleshooting/common-issues.md](troubleshooting/common-issues.md)**

Common issues:
- getMediaStream() returns undefined
- Video not displaying
- renderVideo() deprecated

### 3. Singleton Hierarchy (NAVIGATION MAP)
**[concepts/singleton-hierarchy.md](concepts/singleton-hierarchy.md)**

4-level deep navigation showing how to reach every feature.

---

## Key Learnings

### Critical Discoveries:

1. **getMediaStream() ONLY works after join()**
   - The stream object is not available until session is joined
   - See: [SDK Architecture Pattern](concepts/sdk-architecture-pattern.md)

2. **Use attachVideo() NOT renderVideo()**
   - renderVideo() is deprecated
   - attachVideo() returns a VideoPlayer element to append to DOM
   - See: [Video Rendering](examples/video-rendering.md)

3. **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](examples/event-handling.md)

4. **Peer Videos on Mid-Session Join**
   - Existing participants' videos won't auto-render
   - Must manually iterate getAllUser() and attachVideo()
   - See: [Video Rendering](examples/video-rendering.md)

5. **CDN vs NPM**
   - CDN exports as `WebVideoSDK.default`, not `ZoomVideo`
   - Some networks/ad blockers may block `source.zoom.us` - allowlist or use a permitted fallback strategy
   - See: [Session Join Pattern](examples/session-join-pattern.md)

6. **SharedArrayBuffer for HD**
   - Required for 720p/1080p video
   - Need COOP/COEP headers on server
   - Check with `stream.isSupportHDVideo()`

7. **Screen Share Element Type**
   - Check `isStartShareScreenWithVideoElement()` for correct element type
   - See: [Screen Share](examples/screen-share.md)

8. **Command Channel Setup Order**
   - Must call getCommandClient() AFTER client.join()
   - Register listeners AFTER join, not before
   - Web uses getCommandClient() not getCmdChannel()
   - See: [Command Channel](examples/command-channel.md)

9. **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](examples/video-rendering.md) - Use attachVideo(), check events

### "renderVideo() doesn't work"
→ [Video Rendering](examples/video-rendering.md) - Use attachVideo() instead

### "How do I implement [feature]?"
→ [SDK Architecture Pattern](concepts/sdk-architecture-pattern.md)

### "How do I navigate to [client]?"
→ [Singleton Hierarchy](concepts/singleton-hierarchy.md)

### "What error code means what?"
→ [Common Issues](troubleshooting/common-issues.md)

---

## Document Version

Based on **Zoom Video SDK for Web v2.3.x**

---

**Happy coding!**

Remember: The [SDK Architecture Pattern](concepts/sdk-architecture-pattern.md) is your key to unlocking the entire SDK. Read it first!

## Operations

- [RUNBOOK.md](RUNBOOK.md) - 5-minute preflight and debugging checklist.

Источник: anthropics/knowledge-work-plugins / zoom-plugin / video-sdk/web ↗. Ссылка проверена 2026-10-10.