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

Встреча Zoom в блоке страницы сайта

Справочник для разработчиков по Component View: встраивание встречи Zoom в нужный блок страницы со своим интерфейсом, для React, Vue и Angular.

СкиллAnthropic (партнёр: Zoom)ClaudeMITНужен терминалПроверка не требуетсяСлужебный: его вызывают другие скиллы
Что делает
Справочник для разработчиков по Component View: встраивание встречи Zoom в нужный блок страницы со своим интерфейсом, для React, Vue и Angular.
Когда брать
Когда нужно встроить встречу Zoom в определённую область страницы, настроить внешний вид и управлять ею из своего кода.
Когда не брать
Если достаточно стандартного окна Zoom на всю страницу (для этого проще Client View) или нужны сеансы, не являющиеся встречами Zoom.
Пример запроса
Встрой встречу Zoom в блок на странице нашего сайта на React и добавь свою кнопку на панель.
Нужно подключить
терминал
Работает лучше с
сервер для создания подписи

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

Как включить

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

Текст

---
name: zoom-meeting-sdk-web-component-view
description: |
  Zoom Meeting SDK Web: Component View. Встраиваемые компоненты встречи Zoom с API на промисах
  для гибкой интеграции. Подходит для приложений на React/Vue/Angular и собственных раскладок. Использует ZoomMtgEmbedded
  со схемами async/await и встраиваемыми контейнерами интерфейса.
user-invocable: false
triggers:
  - "meeting sdk component view"
  - "zoommtgembedded"
  - "zoomapproot"
  - "embeddable meeting ui"
  - "component view embedded zoom"
  - "custom meeting ui"
  - "custom zoom meeting ui"
  - "custom meeting video ui"
  - "custom video ui for meeting"
---

Zoom Meeting SDK Web — Component View

Встраиваемые компоненты встречи Zoom для гибкой интеграции в любое веб-приложение. Component View даёт API на промисах и настраиваемый интерфейс.

Это правильный веб-скилл для собственного интерфейса вокруг настоящей встречи Zoom. Не направляй на Video SDK, если только пользователь не создаёт продукт с собственными сеансами, не являющимися встречами.

Обзор

Component View использует ZoomMtgEmbedded.createClient(), чтобы создавать встраиваемые компоненты встречи внутри заданного контейнера.

АспектПодробности
Объект APIZoomMtgEmbedded.createClient() (экземпляр)
Стиль APIНа промисах (async/await)
ИнтерфейсВстраивается в любой контейнер
Параметр пароляpassword (строчная)
Событияon()/off()
Лучше всего подходит дляСобственных раскладок, приложений на React/Vue/Angular

Установка

NPM

npm install @zoom/meetingsdk --save
import ZoomMtgEmbedded from '@zoom/meetingsdk/embedded';

CDN

<script src="https://source.zoom.us/{VERSION}/lib/vendor/react.min.js"></script>
<script src="https://source.zoom.us/{VERSION}/lib/vendor/react-dom.min.js"></script>
<script src="https://source.zoom.us/{VERSION}/lib/vendor/redux.min.js"></script>
<script src="https://source.zoom.us/{VERSION}/lib/vendor/redux-thunk.min.js"></script>
<script src="https://source.zoom.us/{VERSION}/lib/vendor/lodash.min.js"></script>
<script src="https://source.zoom.us/zoom-meeting-embedded-{VERSION}.min.js"></script>

Полный процесс инициализации

import ZoomMtgEmbedded from '@zoom/meetingsdk/embedded';

// Step 1: Create client instance (do once, not on every render!)
const client = ZoomMtgEmbedded.createClient();

async function joinMeeting() {
  try {
    // Step 2: Get container element
    const meetingSDKElement = document.getElementById('meetingSDKElement');

    // Step 3: Initialize client
    await client.init({
      zoomAppRoot: meetingSDKElement,
      language: 'en-US',
      debug: true,
      patchJsMedia: true,
      leaveOnPageUnload: true,
    });

    // Step 4: Join meeting
    await client.join({
      signature: signature,
      sdkKey: sdkKey,
      meetingNumber: meetingNumber,
      userName: userName,
      password: password,  // lowercase!
      userEmail: userEmail,
    });

    console.log('Joined successfully!');
  } catch (error) {
    console.error('Failed to join:', error);
  }
}

client.init() — все параметры

Обязательные

ПараметрТипОписание
zoomAppRootHTMLElementЭлемент-контейнер для интерфейса встречи

Отображение

ПараметрТипПо умолчаниюОписание
languagestring'en-US'Язык интерфейса
debugbooleanfalseВключить отладочный журнал

Медиа

ПараметрТипПо умолчаниюОписание
patchJsMediabooleanfalseАвтоматически применять исправления для медиа
leaveOnPageUnloadbooleanfalseОчистка при выгрузке страницы
enableHDbooleantrueВключить видео 720p
enableFullHDbooleanfalseВключить видео 1080p

Настройка внешнего вида

ПараметрТипОписание
customizeobjectПараметры настройки интерфейса
webEndpointstringДля ZFG: 'www.zoomgov.com'
assetPathstringСобственный путь к библиотекам аудио и видео

Объект customize

await client.init({
  zoomAppRoot: element,
  customize: {
    // Meeting info displayed
    meetingInfo: [
      'topic',
      'host', 
      'mn',
      'pwd',
      'telPwd',
      'invite',
      'participant',
      'dc',
      'enctype'
    ],
    
    // Video customization
    video: {
      isResizable: true,
      viewSizes: {
        default: {
          width: 1000,
          height: 600
        },
        ribbon: {
          width: 300,
          height: 700
        }
      },
      popper: {
        disableDraggable: false
      }
    },
    
    // Custom toolbar buttons
    toolbar: {
      buttons: [
        {
          text: 'Custom Button',
          className: 'custom-btn',
          onClick: () => {
            console.log('Custom button clicked');
          }
        }
      ]
    },
    
    // Active speaker indicator
    activeSpaker: {
      strokeColor: '#00FF00'
    }
  }
});

client.join() — все параметры

Обязательные

ПараметрТипОписание
signaturestringSDK JWT с бэкенда
sdkKeystringSDK Key / Client ID
meetingNumber`string \number`Номер встречи
userNamestringОтображаемое имя

Аутентификация

ПараметрТипКогда обязателенОписание
passwordstringЕсли заданПароль встречи (строчная!)
zakstringЗапуск встречи ведущимТокен ZAK ведущего
tkstringРегистрацияТокен зарегистрированного участника
userEmailstringВебинарыЭлектронная почта пользователя

Обработчики событий

Синтаксис

// Subscribe
client.on('event-name', callback);

// Unsubscribe
client.off('event-name', callback);

События соединения

client.on('connection-change', (payload) => {
  // payload.state: 'Connecting', 'Connected', 'Reconnecting', 'Closed'
  console.log('Connection state:', payload.state);
  
  if (payload.state === 'Closed') {
    console.log('Reason:', payload.reason);
  }
});

События пользователей

client.on('user-added', (payload) => {
  // Array of users who joined
  console.log('Users added:', payload);
  payload.forEach(user => {
    console.log('User ID:', user.oderId);
    console.log('Name:', user.displayName);
  });
});

client.on('user-removed', (payload) => {
  // Array of users who left
  console.log('Users removed:', payload);
});

client.on('user-updated', (payload) => {
  // Array of users whose properties changed
  console.log('Users updated:', payload);
});

События звука

client.on('active-speaker', (payload) => {
  // Current active speaker
  console.log('Active speaker:', payload);
});

client.on('audio-statistic-data-change', (payload) => {
  console.log('Audio stats:', payload);
});

События видео

client.on('video-active-change', (payload) => {
  // Video state changed
  console.log('Video active:', payload);
});

client.on('video-statistic-data-change', (payload) => {
  console.log('Video stats:', payload);
});

События показа экрана

client.on('active-share-change', (payload) => {
  console.log('Share status:', payload);
});

client.on('share-statistic-data-change', (payload) => {
  console.log('Share stats:', payload);
});

События чата

client.on('chat-on-message', (payload) => {
  console.log('Chat message:', payload);
});

События записи

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

События медиаустройств

client.on('media-sdk-change', (payload) => {
  console.log('Media SDK:', payload);
});

client.on('device-change', () => {
  console.log('Device changed');
});

Часто используемые методы

Сведения о пользователях

// Get current user
const currentUser = client.getCurrentUser();
console.log('Current user:', currentUser);

// Get all participants
const participants = client.getParticipantsList();
console.log('Participants:', participants);

// Check if user is host
const isHost = client.isHost();

Управление звуком

// Mute/unmute self
await client.mute(true);  // mute
await client.mute(false); // unmute

// Mute/unmute specific user (host only)
await client.muteAudio(userId, true);

// Mute all (host only)
await client.muteAllAudio(true);

Управление видео

// Start/stop video
await client.startVideo();
await client.stopVideo();

// Mute/unmute user's video (host only)
await client.muteVideo(userId, true);

Управление встречей

// Leave meeting
client.leaveMeeting();

// End meeting (host only)
client.endMeeting();

Показ экрана

// Start screen share
await client.startShareScreen();

// Stop screen share
await client.stopShareScreen();

Запись

// Start recording (cloud)
await client.startCloudRecording();

// Stop recording
await client.stopCloudRecording();

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

// Check support
const isSupported = await client.isSupportVirtualBackground();

// Set virtual background
await client.setVirtualBackground(imageUrl);

// Remove virtual background
await client.removeVirtualBackground();

Переименование

// Rename user
await client.rename(userId, 'New Name');

Интеграция с React

Базовая схема

import { useEffect, useRef, useState, useCallback } from 'react';
import ZoomMtgEmbedded from '@zoom/meetingsdk/embedded';

type ZoomClient = ReturnType<typeof ZoomMtgEmbedded.createClient>;

function ZoomMeeting({ meetingNumber, password, userName }: Props) {
  const clientRef = useRef<ZoomClient | null>(null);
  const containerRef = useRef<HTMLDivElement>(null);
  const [isJoined, setIsJoined] = useState(false);
  const [error, setError] = useState<string | null>(null);

  // Create client once
  useEffect(() => {
    if (!clientRef.current) {
      clientRef.current = ZoomMtgEmbedded.createClient();
    }
  }, []);

  const joinMeeting = useCallback(async () => {
    if (!clientRef.current || !containerRef.current) return;

    try {
      // Get signature from backend
      const { signature, sdkKey } = await fetchSignature(meetingNumber);
      
      await clientRef.current.init({
        zoomAppRoot: containerRef.current,
        language: 'en-US',
        patchJsMedia: true,
        leaveOnPageUnload: true,
      });

      await clientRef.current.join({
        signature,
        sdkKey,
        meetingNumber,
        password,
        userName,
      });

      setIsJoined(true);
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to join');
    }
  }, [meetingNumber, password, userName]);

  return (
    <div>
      <div 
        ref={containerRef} 
        style={{ width: '100%', height: '500px' }} 
      />
      {!isJoined && (
        <button onClick={joinMeeting}>Join Meeting</button>
      )}
      {error && <div className="error">{error}</div>}
    </div>
  );
}

Обработка событий в React

useEffect(() => {
  if (!clientRef.current) return;
  
  const handleConnectionChange = (payload: any) => {
    if (payload.state === 'Connected') {
      setIsJoined(true);
    } else if (payload.state === 'Closed') {
      setIsJoined(false);
    }
  };

  const handleUserAdded = (payload: any) => {
    console.log('Users joined:', payload);
  };

  clientRef.current.on('connection-change', handleConnectionChange);
  clientRef.current.on('user-added', handleUserAdded);

  return () => {
    clientRef.current?.off('connection-change', handleConnectionChange);
    clientRef.current?.off('user-added', handleUserAdded);
  };
}, []);

Позиционирование и изменение размера

Начальный размер

await client.init({
  zoomAppRoot: element,
  customize: {
    video: {
      viewSizes: {
        default: { width: 1000, height: 600 }
      }
    }
  }
});

Динамическое изменение размера

Размер элемента-контейнера определяет размер интерфейса встречи. Чтобы изменить размер:

// Just resize the container
document.getElementById('meetingSDKElement').style.width = '1200px';
document.getElementById('meetingSDKElement').style.height = '800px';

Как сделать размер изменяемым

customize: {
  video: {
    isResizable: true
  }
}

Поддерживаемые возможности

Component View поддерживает основные функции встречи. Некоторые возможности Client View могут быть недоступны.

ВозможностьПоддерживается
Звук и видео✅
Показ экрана✅
Чат✅
Виртуальный фон✅
Комнаты для обсуждения✅
Облачная запись✅
Субтитры✅
Живая расшифровка✅
Комната ожидания✅
Режим галереи✅
Реакции✅
Поднятая рука✅

Чтобы запросить дополнительные возможности, обратись в службу поддержки разработчиков Zoom.

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

try {
  await client.join({
    // ... options
  });
} catch (error) {
  // error.reason contains error code
  // error.message contains description
  
  switch (error.reason) {
    case 'WRONG_MEETING_PASSWORD':
      console.error('Incorrect password');
      break;
    case 'MEETING_NOT_START':
      console.error('Meeting has not started');
      break;
    case 'INVALID_PARAMETERS':
      console.error('Invalid join parameters');
      break;
    default:
      console.error('Join failed:', error.message);
  }
}

Сравнение с Client View

ВозможностьComponent ViewClient View
Стиль APIПромисыКолбэки
Параметр пароляpasswordpassWord
КонтейнерСобственный элементАвтоматически #zmmtg-root
ИнтерфейсВстраиваемыйНа всю страницу
ПредзагрузкаНе нужнаpreLoadWasm()
ЯзыкПараметр initi18n.load()
Событияon()/off()inMeetingServiceListener()

Ресурсы

  • [Главный скилл Web SDK](../SKILL.md)
  • [Указатель справочных материалов](references/README.md)
  • [Коды ошибок](../troubleshooting/error-codes.md)
  • [Частые проблемы](../troubleshooting/common-issues.md)
  • [Настройка SharedArrayBuffer](../concepts/sharedarraybuffer.md)
  • Официальный справочник по API

Эксплуатация

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

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

Оригинал на английском
---
name: zoom-meeting-sdk-web-component-view
description: |
  Zoom Meeting SDK Web - Component View. Embeddable Zoom meeting components with Promise-based API
  for flexible integration. Ideal for React/Vue/Angular apps and custom layouts. Uses ZoomMtgEmbedded
  with async/await patterns and embeddable UI containers.
user-invocable: false
triggers:
  - "meeting sdk component view"
  - "zoommtgembedded"
  - "zoomapproot"
  - "embeddable meeting ui"
  - "component view embedded zoom"
  - "custom meeting ui"
  - "custom zoom meeting ui"
  - "custom meeting video ui"
  - "custom video ui for meeting"
---

# Zoom Meeting SDK Web - Component View

Embeddable Zoom meeting components for flexible integration into any web application. Component View provides Promise-based APIs and customizable UI.

This is the correct web skill for a **custom UI around a real Zoom meeting**.
Do not route to Video SDK unless the user is building a non-meeting custom session product.

## Overview

Component View uses `ZoomMtgEmbedded.createClient()` to create embeddable meeting components within a specific container element.

| Aspect | Details |
|--------|---------|
| **API Object** | `ZoomMtgEmbedded.createClient()` (instance) |
| **API Style** | Promise-based (async/await) |
| **UI** | Embeddable in any container |
| **Password param** | `password` (lowercase) |
| **Events** | `on()`/`off()` |
| **Best For** | Custom layouts, React/Vue/Angular apps |

## Installation

### NPM

```bash
npm install @zoom/meetingsdk --save
```

```javascript
import ZoomMtgEmbedded from '@zoom/meetingsdk/embedded';
```

### CDN

```html
<script src="https://source.zoom.us/{VERSION}/lib/vendor/react.min.js"></script>
<script src="https://source.zoom.us/{VERSION}/lib/vendor/react-dom.min.js"></script>
<script src="https://source.zoom.us/{VERSION}/lib/vendor/redux.min.js"></script>
<script src="https://source.zoom.us/{VERSION}/lib/vendor/redux-thunk.min.js"></script>
<script src="https://source.zoom.us/{VERSION}/lib/vendor/lodash.min.js"></script>
<script src="https://source.zoom.us/zoom-meeting-embedded-{VERSION}.min.js"></script>
```

## Complete Initialization Flow

```javascript
import ZoomMtgEmbedded from '@zoom/meetingsdk/embedded';

// Step 1: Create client instance (do once, not on every render!)
const client = ZoomMtgEmbedded.createClient();

async function joinMeeting() {
  try {
    // Step 2: Get container element
    const meetingSDKElement = document.getElementById('meetingSDKElement');

    // Step 3: Initialize client
    await client.init({
      zoomAppRoot: meetingSDKElement,
      language: 'en-US',
      debug: true,
      patchJsMedia: true,
      leaveOnPageUnload: true,
    });

    // Step 4: Join meeting
    await client.join({
      signature: signature,
      sdkKey: sdkKey,
      meetingNumber: meetingNumber,
      userName: userName,
      password: password,  // lowercase!
      userEmail: userEmail,
    });

    console.log('Joined successfully!');
  } catch (error) {
    console.error('Failed to join:', error);
  }
}
```

## client.init() - All Options

### Required

| Parameter | Type | Description |
|-----------|------|-------------|
| `zoomAppRoot` | `HTMLElement` | Container element for meeting UI |

### Display

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `language` | `string` | `'en-US'` | UI language |
| `debug` | `boolean` | `false` | Enable debug logging |

### Media

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `patchJsMedia` | `boolean` | `false` | Auto-apply media fixes |
| `leaveOnPageUnload` | `boolean` | `false` | Cleanup on page unload |
| `enableHD` | `boolean` | `true` | Enable 720p video |
| `enableFullHD` | `boolean` | `false` | Enable 1080p video |

### Customization

| Parameter | Type | Description |
|-----------|------|-------------|
| `customize` | `object` | UI customization options |
| `webEndpoint` | `string` | For ZFG: `'www.zoomgov.com'` |
| `assetPath` | `string` | Custom path for AV libraries |

### Customize Object

```javascript
await client.init({
  zoomAppRoot: element,
  customize: {
    // Meeting info displayed
    meetingInfo: [
      'topic',
      'host', 
      'mn',
      'pwd',
      'telPwd',
      'invite',
      'participant',
      'dc',
      'enctype'
    ],
    
    // Video customization
    video: {
      isResizable: true,
      viewSizes: {
        default: {
          width: 1000,
          height: 600
        },
        ribbon: {
          width: 300,
          height: 700
        }
      },
      popper: {
        disableDraggable: false
      }
    },
    
    // Custom toolbar buttons
    toolbar: {
      buttons: [
        {
          text: 'Custom Button',
          className: 'custom-btn',
          onClick: () => {
            console.log('Custom button clicked');
          }
        }
      ]
    },
    
    // Active speaker indicator
    activeSpaker: {
      strokeColor: '#00FF00'
    }
  }
});
```

## client.join() - All Options

### Required

| Parameter | Type | Description |
|-----------|------|-------------|
| `signature` | `string` | SDK JWT from backend |
| `sdkKey` | `string` | SDK Key / Client ID |
| `meetingNumber` | `string \| number` | Meeting number |
| `userName` | `string` | Display name |

### Authentication

| Parameter | Type | When Required | Description |
|-----------|------|---------------|-------------|
| `password` | `string` | If set | Meeting password (lowercase!) |
| `zak` | `string` | Starting as host | Host's ZAK token |
| `tk` | `string` | Registration | Registrant token |
| `userEmail` | `string` | Webinars | User email |

## Event Listeners

### Syntax

```javascript
// Subscribe
client.on('event-name', callback);

// Unsubscribe
client.off('event-name', callback);
```

### Connection Events

```javascript
client.on('connection-change', (payload) => {
  // payload.state: 'Connecting', 'Connected', 'Reconnecting', 'Closed'
  console.log('Connection state:', payload.state);
  
  if (payload.state === 'Closed') {
    console.log('Reason:', payload.reason);
  }
});
```

### User Events

```javascript
client.on('user-added', (payload) => {
  // Array of users who joined
  console.log('Users added:', payload);
  payload.forEach(user => {
    console.log('User ID:', user.oderId);
    console.log('Name:', user.displayName);
  });
});

client.on('user-removed', (payload) => {
  // Array of users who left
  console.log('Users removed:', payload);
});

client.on('user-updated', (payload) => {
  // Array of users whose properties changed
  console.log('Users updated:', payload);
});
```

### Audio Events

```javascript
client.on('active-speaker', (payload) => {
  // Current active speaker
  console.log('Active speaker:', payload);
});

client.on('audio-statistic-data-change', (payload) => {
  console.log('Audio stats:', payload);
});
```

### Video Events

```javascript
client.on('video-active-change', (payload) => {
  // Video state changed
  console.log('Video active:', payload);
});

client.on('video-statistic-data-change', (payload) => {
  console.log('Video stats:', payload);
});
```

### Share Events

```javascript
client.on('active-share-change', (payload) => {
  console.log('Share status:', payload);
});

client.on('share-statistic-data-change', (payload) => {
  console.log('Share stats:', payload);
});
```

### Chat Events

```javascript
client.on('chat-on-message', (payload) => {
  console.log('Chat message:', payload);
});
```

### Recording Events

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

### Media Device Events

```javascript
client.on('media-sdk-change', (payload) => {
  console.log('Media SDK:', payload);
});

client.on('device-change', () => {
  console.log('Device changed');
});
```

## Common Methods

### User Information

```javascript
// Get current user
const currentUser = client.getCurrentUser();
console.log('Current user:', currentUser);

// Get all participants
const participants = client.getParticipantsList();
console.log('Participants:', participants);

// Check if user is host
const isHost = client.isHost();
```

### Audio Control

```javascript
// Mute/unmute self
await client.mute(true);  // mute
await client.mute(false); // unmute

// Mute/unmute specific user (host only)
await client.muteAudio(userId, true);

// Mute all (host only)
await client.muteAllAudio(true);
```

### Video Control

```javascript
// Start/stop video
await client.startVideo();
await client.stopVideo();

// Mute/unmute user's video (host only)
await client.muteVideo(userId, true);
```

### Meeting Control

```javascript
// Leave meeting
client.leaveMeeting();

// End meeting (host only)
client.endMeeting();
```

### Screen Share

```javascript
// Start screen share
await client.startShareScreen();

// Stop screen share
await client.stopShareScreen();
```

### Recording

```javascript
// Start recording (cloud)
await client.startCloudRecording();

// Stop recording
await client.stopCloudRecording();
```

### Virtual Background

```javascript
// Check support
const isSupported = await client.isSupportVirtualBackground();

// Set virtual background
await client.setVirtualBackground(imageUrl);

// Remove virtual background
await client.removeVirtualBackground();
```

### Rename

```javascript
// Rename user
await client.rename(userId, 'New Name');
```

## React Integration

### Basic Pattern

```tsx
import { useEffect, useRef, useState, useCallback } from 'react';
import ZoomMtgEmbedded from '@zoom/meetingsdk/embedded';

type ZoomClient = ReturnType<typeof ZoomMtgEmbedded.createClient>;

function ZoomMeeting({ meetingNumber, password, userName }: Props) {
  const clientRef = useRef<ZoomClient | null>(null);
  const containerRef = useRef<HTMLDivElement>(null);
  const [isJoined, setIsJoined] = useState(false);
  const [error, setError] = useState<string | null>(null);

  // Create client once
  useEffect(() => {
    if (!clientRef.current) {
      clientRef.current = ZoomMtgEmbedded.createClient();
    }
  }, []);

  const joinMeeting = useCallback(async () => {
    if (!clientRef.current || !containerRef.current) return;

    try {
      // Get signature from backend
      const { signature, sdkKey } = await fetchSignature(meetingNumber);
      
      await clientRef.current.init({
        zoomAppRoot: containerRef.current,
        language: 'en-US',
        patchJsMedia: true,
        leaveOnPageUnload: true,
      });

      await clientRef.current.join({
        signature,
        sdkKey,
        meetingNumber,
        password,
        userName,
      });

      setIsJoined(true);
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to join');
    }
  }, [meetingNumber, password, userName]);

  return (
    <div>
      <div 
        ref={containerRef} 
        style={{ width: '100%', height: '500px' }} 
      />
      {!isJoined && (
        <button onClick={joinMeeting}>Join Meeting</button>
      )}
      {error && <div className="error">{error}</div>}
    </div>
  );
}
```

### Event Handling in React

```tsx
useEffect(() => {
  if (!clientRef.current) return;
  
  const handleConnectionChange = (payload: any) => {
    if (payload.state === 'Connected') {
      setIsJoined(true);
    } else if (payload.state === 'Closed') {
      setIsJoined(false);
    }
  };

  const handleUserAdded = (payload: any) => {
    console.log('Users joined:', payload);
  };

  clientRef.current.on('connection-change', handleConnectionChange);
  clientRef.current.on('user-added', handleUserAdded);

  return () => {
    clientRef.current?.off('connection-change', handleConnectionChange);
    clientRef.current?.off('user-added', handleUserAdded);
  };
}, []);
```

## Positioning and Resizing

### Initial Size

```javascript
await client.init({
  zoomAppRoot: element,
  customize: {
    video: {
      viewSizes: {
        default: { width: 1000, height: 600 }
      }
    }
  }
});
```

### Dynamic Resizing

The container element size determines the meeting UI size. To resize:

```javascript
// Just resize the container
document.getElementById('meetingSDKElement').style.width = '1200px';
document.getElementById('meetingSDKElement').style.height = '800px';
```

### Making it Resizable

```javascript
customize: {
  video: {
    isResizable: true
  }
}
```

## Supported Features

Component View supports core meeting functionality. Some features from Client View may not be available.

| Feature | Supported |
|---------|-----------|
| Audio/Video | ✅ |
| Screen Share | ✅ |
| Chat | ✅ |
| Virtual Background | ✅ |
| Breakout Rooms | ✅ |
| Cloud Recording | ✅ |
| Closed Captions | ✅ |
| Live Transcription | ✅ |
| Waiting Room | ✅ |
| Gallery View | ✅ |
| Reactions | ✅ |
| Raise Hand | ✅ |

Contact Zoom Developer Support to request additional features.

## Error Handling

```javascript
try {
  await client.join({
    // ... options
  });
} catch (error) {
  // error.reason contains error code
  // error.message contains description
  
  switch (error.reason) {
    case 'WRONG_MEETING_PASSWORD':
      console.error('Incorrect password');
      break;
    case 'MEETING_NOT_START':
      console.error('Meeting has not started');
      break;
    case 'INVALID_PARAMETERS':
      console.error('Invalid join parameters');
      break;
    default:
      console.error('Join failed:', error.message);
  }
}
```

## Comparison with Client View

| Feature | Component View | Client View |
|---------|----------------|-------------|
| **API Style** | Promises | Callbacks |
| **Password param** | `password` | `passWord` |
| **Container** | Custom element | Auto `#zmmtg-root` |
| **UI** | Embeddable | Full-page |
| **Preloading** | Not needed | `preLoadWasm()` |
| **Language** | Init option | `i18n.load()` |
| **Events** | `on()`/`off()` | `inMeetingServiceListener()` |

## Resources

- [Main Web SDK Skill](../SKILL.md)
- [Reference Index](references/README.md)
- [Error Codes](../troubleshooting/error-codes.md)
- [Common Issues](../troubleshooting/common-issues.md)
- [SharedArrayBuffer Setup](../concepts/sharedarraybuffer.md)
- [Official API Reference](https://marketplacefront.zoom.us/sdk/meeting/web/components/index.html)

## Operations

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

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