zoom-meeting-sdk-web-component-view

Par anthropics · knowledge-work-plugins

Zoom Meeting SDK Web - Vue Composant. Composants de réunion Zoom intégrables avec une API basée sur les Promise pour une intégration flexible. Idéal pour les applications React/Vue/Angular et les mises en page personnalisées. Utilise `ZoomMtgEmbedded` avec des patterns async/await et des conteneurs UI intégrables.

npx skills add https://github.com/anthropics/knowledge-work-plugins --skill zoom-meeting-sdk-web-component-view

Zoom Meeting SDK Web - Component View

Des composants de réunion Zoom intégrables pour une intégration flexible dans n'importe quelle application web. Component View fournit des APIs basées sur les Promises et une interface utilisateur personnalisable.

C'est la bonne skill web pour une interface utilisateur personnalisée autour d'une vraie réunion Zoom. Ne routez pas vers Video SDK sauf si l'utilisateur construit un produit de session personnalisé sans réunion.

Aperçu

Component View utilise ZoomMtgEmbedded.createClient() pour créer des composants de réunion intégrables dans un élément conteneur spécifique.

Aspect Détails
Objet API ZoomMtgEmbedded.createClient() (instance)
Style API Basée sur les Promises (async/await)
Interface utilisateur Intégrable dans n'importe quel conteneur
Paramètre mot de passe password (minuscules)
Événements on()/off()
Idéal pour Mises en page personnalisées, applications React/Vue/Angular

Installation

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>

Flux d'initialisation complet

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

// Étape 1 : Créer l'instance client (faire une seule fois, pas à chaque rendu !)
const client = ZoomMtgEmbedded.createClient();

async function joinMeeting() {
  try {
    // Étape 2 : Obtenir l'élément conteneur
    const meetingSDKElement = document.getElementById('meetingSDKElement');

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

    // Étape 4 : Rejoindre la réunion
    await client.join({
      signature: signature,
      sdkKey: sdkKey,
      meetingNumber: meetingNumber,
      userName: userName,
      password: password,  // minuscules !
      userEmail: userEmail,
    });

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

client.init() - Toutes les options

Obligatoire

Paramètre Type Description
zoomAppRoot HTMLElement Élément conteneur pour l'interface utilisateur de réunion

Affichage

Paramètre Type Par défaut Description
language string 'en-US' Langue de l'interface utilisateur
debug boolean false Activer la journalisation de débogage

Média

Paramètre Type Par défaut Description
patchJsMedia boolean false Appliquer automatiquement les correctifs média
leaveOnPageUnload boolean false Nettoyer au déchargement de la page
enableHD boolean true Activer la vidéo 720p
enableFullHD boolean false Activer la vidéo 1080p

Personnalisation

Paramètre Type Description
customize object Options de personnalisation de l'interface utilisateur
webEndpoint string Pour ZFG : 'www.zoomgov.com'
assetPath string Chemin personnalisé pour les bibliothèques AV

Objet Customize

await client.init({
  zoomAppRoot: element,
  customize: {
    // Informations de réunion affichées
    meetingInfo: [
      'topic',
      'host', 
      'mn',
      'pwd',
      'telPwd',
      'invite',
      'participant',
      'dc',
      'enctype'
    ],

    // Personnalisation vidéo
    video: {
      isResizable: true,
      viewSizes: {
        default: {
          width: 1000,
          height: 600
        },
        ribbon: {
          width: 300,
          height: 700
        }
      },
      popper: {
        disableDraggable: false
      }
    },

    // Boutons de barre d'outils personnalisés
    toolbar: {
      buttons: [
        {
          text: 'Custom Button',
          className: 'custom-btn',
          onClick: () => {
            console.log('Custom button clicked');
          }
        }
      ]
    },

    // Indicateur de locuteur actif
    activeSpaker: {
      strokeColor: '#00FF00'
    }
  }
});

client.join() - Toutes les options

Obligatoire

Paramètre Type Description
signature string SDK JWT depuis le backend
sdkKey string SDK Key / Client ID
meetingNumber string \| number Numéro de réunion
userName string Nom d'affichage

Authentification

Paramètre Type Quand c'est obligatoire Description
password string Si défini Mot de passe de réunion (minuscules !)
zak string En tant qu'animateur Token ZAK de l'animateur
tk string Enregistrement Token de participant enregistré
userEmail string Webinaires E-mail de l'utilisateur

Écouteurs d'événements

Syntaxe

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

// Se désabonner
client.off('event-name', callback);

Événements de connexion

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

Événements utilisateur

client.on('user-added', (payload) => {
  // Tableau des utilisateurs qui ont rejoint
  console.log('Users added:', payload);
  payload.forEach(user => {
    console.log('User ID:', user.oderId);
    console.log('Name:', user.displayName);
  });
});

client.on('user-removed', (payload) => {
  // Tableau des utilisateurs qui ont quitté
  console.log('Users removed:', payload);
});

client.on('user-updated', (payload) => {
  // Tableau des utilisateurs dont les propriétés ont changé
  console.log('Users updated:', payload);
});

Événements audio

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

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

Événements vidéo

client.on('video-active-change', (payload) => {
  // État vidéo modifié
  console.log('Video active:', payload);
});

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

Événements de partage

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

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

Événements de chat

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

Événements d'enregistrement

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

Événements de périphérique média

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

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

Méthodes courantes

Informations utilisateur

// Obtenir l'utilisateur actuel
const currentUser = client.getCurrentUser();
console.log('Current user:', currentUser);

// Obtenir tous les participants
const participants = client.getParticipantsList();
console.log('Participants:', participants);

// Vérifier si l'utilisateur est animateur
const isHost = client.isHost();

Contrôle audio

// Couper/activer le son de soi-même
await client.mute(true);  // couper
await client.mute(false); // activer

// Couper/activer le son d'un utilisateur spécifique (animateur uniquement)
await client.muteAudio(userId, true);

// Couper le son de tous (animateur uniquement)
await client.muteAllAudio(true);

Contrôle vidéo

// Démarrer/arrêter la vidéo
await client.startVideo();
await client.stopVideo();

// Couper/activer la vidéo d'un utilisateur (animateur uniquement)
await client.muteVideo(userId, true);

Contrôle de réunion

// Quitter la réunion
client.leaveMeeting();

// Terminer la réunion (animateur uniquement)
client.endMeeting();

Partage d'écran

// Démarrer le partage d'écran
await client.startShareScreen();

// Arrêter le partage d'écran
await client.stopShareScreen();

Enregistrement

// Démarrer l'enregistrement (cloud)
await client.startCloudRecording();

// Arrêter l'enregistrement
await client.stopCloudRecording();

Arrière-plan virtuel

// Vérifier la prise en charge
const isSupported = await client.isSupportVirtualBackground();

// Définir l'arrière-plan virtuel
await client.setVirtualBackground(imageUrl);

// Supprimer l'arrière-plan virtuel
await client.removeVirtualBackground();

Renommer

// Renommer l'utilisateur
await client.rename(userId, 'New Name');

Intégration React

Modèle de base

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

  // Créer le client une seule fois
  useEffect(() => {
    if (!clientRef.current) {
      clientRef.current = ZoomMtgEmbedded.createClient();
    }
  }, []);

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

    try {
      // Obtenir la signature depuis le 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>
  );
}

Gestion des événements dans 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);
  };
}, []);

Positionnement et redimensionnement

Taille initiale

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

Redimensionnement dynamique

La taille de l'élément conteneur détermine la taille de l'interface utilisateur de réunion. Pour redimensionner :

// Redimensionner simplement le conteneur
document.getElementById('meetingSDKElement').style.width = '1200px';
document.getElementById('meetingSDKElement').style.height = '800px';

Rendre redimensionnable

customize: {
  video: {
    isResizable: true
  }
}

Fonctionnalités prises en charge

Component View prend en charge les fonctionnalités principales de réunion. Certaines fonctionnalités de Client View peuvent ne pas être disponibles.

Fonctionnalité Prise en charge
Audio/Vidéo
Partage d'écran
Chat
Arrière-plan virtuel
Breakout Rooms
Enregistrement cloud
Sous-titres codés
Transcription en direct
Salle d'attente
Galerie
Réactions
Lever la main

Contactez Zoom Developer Support pour demander des fonctionnalités supplémentaires.

Gestion des erreurs

try {
  await client.join({
    // ... options
  });
} catch (error) {
  // error.reason contient le code d'erreur
  // error.message contient la 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);
  }
}

Comparaison avec Client View

Fonctionnalité Component View Client View
Style API Promises Callbacks
Paramètre mot de passe password passWord
Conteneur Élément personnalisé Auto #zmmtg-root
Interface utilisateur Intégrable Page complète
Préchargement Non nécessaire preLoadWasm()
Langue Option d'initialisation i18n.load()
Événements on()/off() inMeetingServiceListener()

Ressources

Opérations

  • RUNBOOK.md - Liste de contrôle de vol de 5 minutes et débogage.

Skills similaires