zoom-meeting-sdk-web

Par anthropics · knowledge-work-plugins

Zoom Meeting SDK pour le Web - Intégrez les fonctionnalités de réunion Zoom dans vos applications web. Deux options d'intégration : Client View (pleine page, interface Zoom classique) et Component View (intégrable, API basée sur les Promise). Inclut la configuration SharedArrayBuffer pour la vidéo HD, la vue galerie et les arrière-plans virtuels.

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

Zoom Meeting SDK (Web)

Intégrez les capacités de réunion Zoom dans des applications web avec deux options d'intégration : Client View (page entière) ou Component View (intégrable).

Comment implémenter une interface utilisateur vidéo personnalisée pour une réunion Zoom dans une application web

Utilisez Meeting SDK Web Component View.

N'utilisez pas Video SDK pour cette question à moins que l'utilisateur ne construise explicitement un produit de session non-réunion.

Architecture minimale :

Page navigateur
  -> récupérer la signature Meeting SDK depuis le backend
  -> ZoomMtgEmbedded.createClient()
  -> client.init({ zoomAppRoot })
  -> client.join({ signature, sdkKey, meetingNumber, userName, password })
  -> appliquer les options de mise en page/style/personnalisation autour du conteneur de réunion intégré

Implémentation minimale :

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

const client = ZoomMtgEmbedded.createClient();

export async function startEmbeddedMeeting(meetingNumber: string, userName: string, password: string) {
  const sigRes = await fetch('/api/signature', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ meetingNumber, role: 0 }),
  });

  if (!sigRes.ok) throw new Error(`signature_fetch_failed:${sigRes.status}`);

  const { signature, sdkKey } = await sigRes.json();

  await client.init({
    zoomAppRoot: document.getElementById('meetingSDKElement')!,
    language: 'en-US',
    patchJsMedia: true,
    leaveOnPageUnload: true,
    customize: {
      video: { isResizable: true, popper: { disableDraggable: false } },
    },
  });

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

Points de défaillance courants :

  • mauvaise route : Video SDK au lieu de Meeting SDK Component View
  • endpoint de signature backend manquant
  • champ de mot de passe incorrect (password ici, pas passWord)
  • exigences OBF/ZAK manquantes pour les réunions en dehors du compte de l'application
  • en-têtes SharedArrayBuffer manquants quand des fonctionnalités de réunion haut de gamme sont attendues

Règle de routage strict

Si l'utilisateur souhaite une interface utilisateur vidéo personnalisée pour une réunion Zoom dans une application web, routez vers Component View, pas Video SDK.

  • Meeting SDK Component View = interface utilisateur personnalisée pour une vraie réunion Zoom
  • Video SDK Web = interface utilisateur personnalisée pour un produit de session vidéo non-réunion

Pour le chemin direct d'interface de réunion personnalisée, commencez par component-view/SKILL.md.

Nouveau avec Web SDK ? Commencez ici !

Le moyen le plus rapide de maîtriser le SDK :

  1. Choisissez votre vue - Client View vs Component View - Comprenez les différences architecturales clés
  2. Démarrage rapide - Client View ou Component View - Obtenez une réunion fonctionnelle en quelques minutes
  3. SharedArrayBuffer - concepts/sharedarraybuffer.md - Requis pour la vidéo HD, la vue galerie, les arrière-plans virtuels
  4. Diagnostiques de préflight optionnels - ../../probe-sdk/SKILL.md - Validez le navigateur/appareil/réseau avant la connexion

Créez une intégration personnalisée ?

Vous rencontrez des problèmes ?

  • Erreurs de connexion → Vérifiez la génération de signature et l'orthographe du mot de passe (passWord vs password)
  • Vidéo HD ne fonctionne pas → Activez les en-têtes SharedArrayBuffer
  • Navigation complète → SKILL.md

Prérequis

  • Application Zoom avec identifiants Meeting SDK depuis Marketplace
  • Clé SDK (ID client) et secret
  • Navigateur moderne (Chrome, Firefox, Safari, Edge)
  • Endpoint d'authentification backend pour la génération de signature

Besoin d'aide sur l'authentification ? Voir la compétence zoom-oauth pour la génération JWT/signature.

Voulez des diagnostiques de pré-connexion ? Associez probe-sdk avant init()/join() pour filtrer les environnements peu prêts.

Portail de préflight optionnel (Probe SDK)

Pour les environnements instables de première connexion, exécutez les vérifications Probe SDK avant d'appeler ZoomMtg.init() ou client.join() :

  1. Exécutez les diagnostiques de permissions/appareil/réseau Probe.
  2. Appliquez la politique de disponibilité (allow, warn, block).
  3. Continuez vers la connexion Meeting SDK uniquement pour allow/avertissements approuvés warn.

Voir ../../probe-sdk/SKILL.md et ../../general/use-cases/probe-sdk-preflight-readiness-gate.md.

Client View vs Component View

DIFFÉRENCE CRITIQUE : Ce sont deux API complètement différentes avec des patterns différents !

Aspect Client View Component View
Objet ZoomMtg (singleton global) ZoomMtgEmbedded.createClient() (instance)
Style API Callbacks Promises
Interface utilisateur Reprise de page entière Intégrable dans n'importe quel conteneur
Paramètre mot de passe passWord (W majuscule) password (minuscule)
Événements inMeetingServiceListener() on()/off()
Import (npm) import { ZoomMtg } from '@zoom/meetingsdk' import ZoomMtgEmbedded from '@zoom/meetingsdk/embedded'
CDN zoom-meeting-{VERSION}.min.js zoom-meeting-embedded-{VERSION}.min.js
Idéal pour Intégration rapide, interface Zoom standard Mises en page personnalisées, applications React/Vue

Quand utiliser laquelle

Utilisez Client View quand :

  • Vous voulez l'interface de réunion Zoom familière
  • L'intégration rapide est prioritaire à la personnalisation
  • L'expérience de réunion en page entière est acceptable

Utilisez Component View quand :

  • Vous devez intégrer les réunions dans une zone spécifique de votre page
  • Création d'applications React/Vue/Angular
  • Vous voulez la syntaxe async/await basée sur les Promises
  • Le positionnement et le redimensionnement personnalisés sont requis

Installation

NPM (recommandé)

npm install @zoom/meetingsdk --save

CDN

<!-- Dépendances (requises pour les deux vues) -->
<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>

<!-- Client View -->
<script src="https://source.zoom.us/zoom-meeting-{VERSION}.min.js"></script>

<!-- OU Component View -->
<script src="https://source.zoom.us/zoom-meeting-embedded-{VERSION}.min.js"></script>

Remplacez {VERSION} par la dernière version (p. ex., 3.11.0).

Démarrage rapide (Client View)

import { ZoomMtg } from '@zoom/meetingsdk';

// Étape 1 : Vérifier la compatibilité du navigateur
console.log('Configuration requise :', ZoomMtg.checkSystemRequirements());

// Étape 2 : Précharger WebAssembly pour une initialisation plus rapide
ZoomMtg.preLoadWasm();
ZoomMtg.prepareWebSDK();

// Étape 3 : Charger les fichiers de langue (DOIT se terminer avant init)
ZoomMtg.i18n.load('en-US');
ZoomMtg.i18n.onLoad(() => {

  // Étape 4 : Initialiser le SDK
  ZoomMtg.init({
    leaveUrl: 'https://yoursite.com/meeting-ended',
    disableCORP: !window.crossOriginIsolated, // Détection automatique SharedArrayBuffer
    patchJsMedia: true,           // Appliquer automatiquement les correctifs de dépendances médias
    leaveOnPageUnload: true,      // Nettoyer à la fermeture de la page
    externalLinkPage: './external.html', // Page pour les liens externes
    success: () => {

      // Étape 5 : Rejoindre la réunion (noter : passWord avec W majuscule !)
      ZoomMtg.join({
        signature: signature,       // De votre endpoint d'authentification
        meetingNumber: '1234567890',
        userName: 'User Name',
        passWord: 'meeting-password', // W majuscule !
        success: (res) => {
          console.log('Réunion rejointe :', res);

          // Après la connexion : Obtenir les informations de réunion
          ZoomMtg.getAttendeeslist({});
          ZoomMtg.getCurrentUser({
            success: (res) => console.log('Utilisateur courant :', res.result.currentUser)
          });
        },
        error: (err) => {
          console.error('Erreur de connexion :', err);
        }
      });
    },
    error: (err) => {
      console.error('Erreur d\'initialisation :', err);
    }
  });
});

Démarrage rapide (Component View)

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

// Créer une instance client (faire cela UNE FOIS, pas à chaque rendu !)
const client = ZoomMtgEmbedded.createClient();

async function startMeeting() {
  try {
    // Initialiser avec l'élément conteneur
    await client.init({
      zoomAppRoot: document.getElementById('meetingSDKElement'),
      language: 'en-US',
      debug: true,                  // Activer les logs de debug
      patchJsMedia: true,           // Appliquer automatiquement les correctifs médias
      leaveOnPageUnload: true,      // Nettoyer à la fermeture de la page
    });

    // Rejoindre la réunion (noter : password minuscule !)
    await client.join({
      signature: signature,          // De votre endpoint d'authentification
      sdkKey: SDK_KEY,
      meetingNumber: '1234567890',
      userName: 'User Name',
      password: 'meeting-password',  // Minuscule !
    });

    console.log('Connexion réussie !');
  } catch (error) {
    console.error('Échec de la connexion :', error);
  }
}

Endpoint d'authentification (obligatoire)

Les deux vues nécessitent une signature JWT d'un serveur backend. N'exposez jamais votre secret SDK dans le code frontend !

# Cloner l'endpoint d'authentification officiel de Zoom
git clone https://github.com/zoom/meetingsdk-auth-endpoint-sample --depth 1
cd meetingsdk-auth-endpoint-sample
cp .env.example .env
# Éditer .env avec votre clé SDK et secret
npm install && npm run start

Génération de signature

La signature encode :

  • sdkKey (ou clientId pour les applications plus récentes)
  • meetingNumber
  • role (0 = participant, 1 = animateur)
  • iat (timestamp de création)
  • exp (timestamp d'expiration)
  • tokenExp (expiration du token)

IMPORTANT (mars 2026) : Les applications rejoignant des réunions en dehors de leur compte nécessiteront un App Privilege Token (OBF) ou un token ZAK. Voir Exigences d'autorisation.

Flux de travail principal

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│  Obtenir Sig.   │───►│   init()        │───►│   join()        │
│  (depuis back)  │    │   (config SDK)  │    │   (entrer réu)  │
└─────────────────┘    └─────────────────┘    └─────────────────┘
                             │                       │
                             ▼                       ▼
                       success/error            success/error
                        callback                 callback
                     (ou Promise resolve)    (ou Promise resolve)

Référence API Client View

ZoomMtg.init() - Options clés

ZoomMtg.init({
  // Obligatoire
  leaveUrl: string,              // URL de redirection après quitter

  // Options d'affichage
  showMeetingHeader: boolean,    // Afficher numéro/sujet réunion (défaut : true)
  disableInvite: boolean,        // Masquer bouton d'invitation (défaut : false)
  disableRecord: boolean,        // Masquer bouton d'enregistrement (défaut : false)
  disableJoinAudio: boolean,     // Masquer option audio (défaut : false)
  disablePreview: boolean,       // Ignorer aperçu A/V (défaut : false)

  // Vidéo HD (nécessite SharedArrayBuffer)
  enableHD: boolean,             // Activer 720p (défaut : true pour >=2.8.0)
  enableFullHD: boolean,         // Activer 1080p pour webinaires (défaut : false)

  // Options d'affichage
  defaultView: 'gallery' | 'speaker' | 'multiSpeaker',

  // Bascules de fonctionnalités
  isSupportChat: boolean,        // Activer chat (défaut : true)
  isSupportCC: boolean,          // Activer sous-titres (défaut : true)
  isSupportBreakout: boolean,    // Activer salons (défaut : true)
  isSupportPolling: boolean,     // Activer sondages (défaut : true)
  isSupportQA: boolean,          // Activer Q&R pour webinaires (défaut : true)

  // Origine croisée
  disableCORP: boolean,          // Pour développement sans en-têtes COOP/COEP

  // Callbacks
  success: Function,
  error: Function,
});

ZoomMtg.join() - Options clés

ZoomMtg.join({
  // Obligatoire
  signature: string,             // Signature JWT depuis backend
  meetingNumber: string | number,
  userName: string,

  // Authentification
  passWord: string,              // Mot de passe réunion (W majuscule !)
  zak: string,                   // Token ZAK de l'animateur (requis pour démarrer)
  tk: string,                    // Token d'enregistrement (si requis)
  obfToken: string,              // App Privilege Token (pour exigence 2026)

  // Optionnel
  userEmail: string,             // Requis pour webinaires
  customerKey: string,           // Identifiant personnalisé (max 36 caractères)

  // Callbacks
  success: Function,
  error: Function,
});

Écouteurs d'événements (Client View)

// Événements utilisateur
ZoomMtg.inMeetingServiceListener('onUserJoin', (data) => {
  console.log('Utilisateur connecté :', data);
});

ZoomMtg.inMeetingServiceListener('onUserLeave', (data) => {
  console.log('Utilisateur parti :', data);
  // Valeurs de data.reasonCode :
  // 0: OTHER
  // 1: HOST_ENDED_MEETING
  // 2: SELF_LEAVE_FROM_IN_MEETING
  // 3: SELF_LEAVE_FROM_WAITING_ROOM
  // 4: SELF_LEAVE_FROM_WAITING_FOR_HOST_START
  // 5: MEETING_TRANSFER
  // 6: KICK_OUT_FROM_MEETING
  // 7: KICK_OUT_FROM_WAITING_ROOM
  // 8: LEAVE_FROM_DISCLAIMER
});

ZoomMtg.inMeetingServiceListener('onUserUpdate', (data) => {
  console.log('Utilisateur mis à jour :', data);
});

// Statut réunion
ZoomMtg.inMeetingServiceListener('onMeetingStatus', (data) => {
  // status: 1=connexion, 2=connecté, 3=déconnecté, 4=reconnexion
  console.log('Statut réunion :', data.status);
});

// Salle d'attente
ZoomMtg.inMeetingServiceListener('onUserIsInWaitingRoom', (data) => {
  console.log('Utilisateur en salle d\'attente :', data);
});

// Détection du présentateur actif
ZoomMtg.inMeetingServiceListener('onActiveSpeaker', (data) => {
  // [{userId: number, userName: string}]
  console.log('Présentateur actif :', data);
});

// Surveillance de la qualité réseau
ZoomMtg.inMeetingServiceListener('onNetworkQualityChange', (data) => {
  // {level: 0-5, userId, type: 'uplink'}
  // 0-1 = mauvais, 2 = normal, 3-5 = bon
  if (data.level <= 1) {
    console.warn('Qualité réseau faible');
  }
});

// Métriques de performance à la connexion
ZoomMtg.inMeetingServiceListener('onJoinSpeed', (data) => {
  console.log('Métriques de vitesse de connexion :', data);
  // Utile pour les tableaux de bord de suivi des performances
});

// Chat
ZoomMtg.inMeetingServiceListener('onReceiveChatMsg', (data) => {
  console.log('Message chat :', data);
});

// Enregistrement
ZoomMtg.inMeetingServiceListener('onRecordingChange', (data) => {
  console.log('Statut d\'enregistrement :', data);
});

// Partage d'écran
ZoomMtg.inMeetingServiceListener('onShareContentChange', (data) => {
  console.log('Partage de contenu changé :', data);
});

// Transcription (nécessite « enregistrer les sous-titres » activé)
ZoomMtg.inMeetingServiceListener('onReceiveTranscriptionMsg', (data) => {
  console.log('Transcription :', data);
});

// Statut des salons
ZoomMtg.inMeetingServiceListener('onRoomStatusChange', (data) => {
  // status: 2=EnCours, 3=Fermeture, 4=Fermé
  console.log('Statut salon :', data);
});

Méthodes communes (Client View)

// Obtenir les infos utilisateur courant
ZoomMtg.getCurrentUser({
  success: (res) => console.log(res.result.currentUser)
});

// Obtenir tous les participants
ZoomMtg.getAttendeeslist({});

// Contrôle audio/vidéo
ZoomMtg.mute({ userId, mute: true });
ZoomMtg.muteAll({ muteAll: true });

// Chat
ZoomMtg.sendChat({ message: 'Bonjour !', userId: 0 }); // 0 = tout le monde

// Quitter/Terminer
ZoomMtg.leaveMeeting({});
ZoomMtg.endMeeting({});

// Contrôles animateur
ZoomMtg.makeHost({ userId });
ZoomMtg.makeCoHost({ oderId });
ZoomMtg.expel({ userId });  // Retirer participant
ZoomMtg.putOnHold({ oderId, bHold: true });

// Salons
ZoomMtg.createBreakoutRoom({ rooms: [...] });
ZoomMtg.openBreakoutRooms({});
ZoomMtg.closeBreakoutRooms({});

// Arrière-plan virtuel
ZoomMtg.setVirtualBackground({ imageUrl: '...' });

Référence API Component View

client.init() - Options clés

await client.init({
  // Obligatoire
  zoomAppRoot: HTMLElement,      // Élément conteneur

  // Affichage
  language: string,              // p. ex., 'en-US'
  debug: boolean,                // Activer logs debug (défaut : false)

  // Média
  patchJsMedia: boolean,         // Appliquer correctifs média auto (défaut : false)
  leaveOnPageUnload: boolean,    // Nettoyer à fermeture page (défaut : false)

  // Vidéo
  enableHD: boolean,             // Activer 720p
  enableFullHD: boolean,         // Activer 1080p

  // Personnalisation
  customize: {
    video: {
      isResizable: boolean,
      viewSizes: { default: { width, height } }
    },
    meetingInfo: ['topic', 'host', 'mn', 'pwd', 'telPwd', 'invite', 'participant', 'dc', 'enctype'],
    toolbar: {
      buttons: [
        {
          text: 'Bouton personnalisé',
          className: 'custom-btn',
          onClick: () => {
            console.log('Bouton personnalisé cliqué');
          }
        }
      ]
    }
  },

  // Pour ZFG
  webEndpoint: string,
  assetPath: string,             // Chemin personnalisé pour libs AV (auto-hébergement)
});

client.join() - Options clés

await client.join({
  // Obligatoire
  signature: string,
  sdkKey: string,
  meetingNumber: string | number,
  userName: string,

  // Authentification  
  password: string,              // Minuscule ! (différent de Client View)
  zak: string,                   // Token ZAK animateur
  tk: string,                    // Token d'enregistrement

  // Optionnel
  userEmail: string,
});

Écouteurs d'événements (Component View)

// État de connexion
client.on('connection-change', (payload) => {
  // payload.state: 'Connecting', 'Connected', 'Reconnecting', 'Closed'
  console.log('Connexion :', payload.state);
});

// Événements utilisateur
client.on('user-added', (payload) => {
  console.log('Utilisateurs ajoutés :', payload);
});

client.on('user-removed', (payload) => {
  console.log('Utilisateurs retirés :', payload);
});

client.on('user-updated', (payload) => {
  console.log('Utilisateurs mis à jour :', payload);
});

// Présentateur actif
client.on('active-speaker', (payload) => {
  console.log('Présentateur actif :', payload);
});

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

// Se désabonner
client.off('connection-change', handler);

Méthodes communes (Component View)

// Obtenir utilisateur courant
const currentUser = client.getCurrentUser();

// Obtenir tous les participants
const participants = client.getParticipantsList();

// Contrôle audio
await client.mute(true);
await client.muteAudio(userId, true);

// Contrôle vidéo
await client.muteVideo(userId, true);

// Quitter
client.leaveMeeting();

// Terminer (animateur uniquement)
client.endMeeting();

SharedArrayBuffer (CRITIQUE pour HD)

SharedArrayBuffer active les fonctionnalités avancées :

  • Vidéo 720p/1080p
  • Vue galerie
  • Arrière-plans virtuels
  • Suppression du bruit de fond

Activer avec en-têtes HTTP

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

Vérifier dans le navigateur

if (typeof SharedArrayBuffer === 'function') {
  console.log('SharedArrayBuffer activé !');
} else {
  console.warn('Fonctionnalités HD seront limitées');
}

// Ou vérifier l'isolation d'origine croisée
console.log('Isolé en origine croisée :', window.crossOriginIsolated);

Configuration spécifique à la plateforme

Voir concepts/sharedarraybuffer.md pour :

  • Configuration Vercel, Netlify, AWS CloudFront
  • Configuration nginx/Apache
  • Fallback service worker pour GitHub Pages

Configuration de développement (motif deux serveurs)

Les exemples officiels utilisent un motif de deux serveurs pour le développement car les en-têtes COOP/COEP peuvent casser la navigation :

// Serveur 1 : Application principale (port 9999) - SANS en-têtes d'isolation
// Sert index.html, navigation fonctionne normalement

// Serveur 2 : Page réunion (port 9998) - AVEC en-têtes d'isolation
// Sert meeting.html avec support SharedArrayBuffer

// Serveur principal proxifie vers serveur réunion
proxy: [{
  path: '/meeting.html',
  target: 'http://YOUR_MEETING_SERVER_HOST:9998/'
}]

Config Vite avec en-têtes :

// vite.config.ts
export default defineConfig({
  server: {
    headers: {
      'Cross-Origin-Embedder-Policy': 'require-corp',
      'Cross-Origin-Opener-Policy': 'same-origin',
    }
  }
});

Problèmes courants et solutions

Problème Solution
Connexion échoue avec erreur signature Vérifiez génération signature, vérifiez format sdkKey
Typo "passWord" Client View utilise passWord (W majuscule), Component View utilise password
Pas de vidéo HD Activez en-têtes SharedArrayBuffer, vérifiez support navigateur
Callbacks ne se déclenchent pas Assurez-vous que inMeetingServiceListener est appelé après succès d'init
Arrière-plan virtuel ne fonctionne pas Nécessite SharedArrayBuffer + Chrome/Edge
Partage d'écran échoue sur Safari Safari 17+ avec macOS 14+ requis pour client view

Dépannage complet : troubleshooting/common-issues.md

Matrice de support navigateur

Fonctionnalité Chrome Firefox Safari Edge iOS Android
720p (recevoir) Oui Oui Oui Oui Oui Oui
720p (envoyer) Oui* Oui* Oui* Oui* Oui* Oui*
Arrière-plan virtuel Oui Oui Non Oui Non Non
Partage d'écran (envoyer) Oui Oui Safari 17+ Oui Non Non
Vue galerie Oui Oui Oui** Oui Oui Oui

*Nécessite SharedArrayBuffer **Safari 17+ avec macOS Sonoma

Voir concepts/browser-support.md pour la matrice complète.

Exigences d'autorisation (mise à jour 2026)

IMPORTANT : À partir du 2 mars 2026, les applications rejoignant des réunions en dehors de leur compte doivent être autorisées.

Options

  1. App Privilege Token (OBF) - Recommandé pour les bots

    ZoomMtg.join({
      ...
      obfToken: 'your-app-privilege-token'
    });
  2. Token ZAK - Pour les opérations d'animateur

    ZoomMtg.join({
      ...
      zak: 'host-zak-token'
    });

Zoom for Government (ZFG)

Option 1 : Package NPM spécifique à ZFG

{
  "dependencies": {
    "@zoom/meetingsdk": "3.11.2-zfg"
  }
}

Option 2 : Configurer les endpoints ZFG

Client View :

ZoomMtg.setZoomJSLib('https://source.zoomgov.com/{VERSION}/lib', '/av');
ZoomMtg.init({
  webEndpoint: 'www.zoomgov.com',
  ...
});

Component View :

await client.init({
  webEndpoint: 'www.zoomgov.com',
  assetPath: 'https://source.zoomgov.com/{VERSION}/lib/av',
  ...
});

CDN Chine

// Définir avant preLoadWasm()
ZoomMtg.setZoomJSLib('https://jssdk.zoomus.cn/{VERSION}/lib', '/av');

Intégration React

Pattern officiel (depuis zoom/meetingsdk-react-sample)

L'exemple React officiel utilise une initialisation impérative plutôt que des hooks React :

import { ZoomMtg } from '@zoom/meetingsdk';

// Précharger au niveau du module (en dehors du composant)
ZoomMtg.preLoadWasm();
ZoomMtg.prepareWebSDK();

function App() {
  const authEndpoint = import.meta.env.VITE_AUTH_ENDPOINT;
  const meetingNumber = '';
  const passWord = '';
  const role = 0;
  const userName = 'React User';

  const getSignature = async () => {
    const response = await fetch(authEndpoint, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        meetingNumber,
        role,
      }),
    });
    const data = await response.json();
    startMeeting(data.signature);
  };

  const startMeeting = (signature: string) => {
    document.getElementById('zmmtg-root')!.style.display = 'block';

    ZoomMtg.init({
      leaveUrl: window.location.origin,
      patchJsMedia: true,
      leaveOnPageUnload: true,
      success: () => {
        ZoomMtg.join({
          signature,
          meetingNumber,
          userName,
          passWord,
          success: (res) => console.log('Connecté :', res),
          error: (err) => console.error('Erreur connexion :', err),
        });
      },
      error: (err) => console.error('Erreur init :', err),
    });
  };

  return (
    <button onClick={getSignature}>Rejoindre réunion</button>
  );
}

Pièges React (depuis les exemples officiels)

Problème Cause Solution
Récréation client createClient() dans le corps du composant s'exécute à chaque rendu Utiliser useRef pour conserver le client
Pas d'useEffect L'exemple officiel n'utilise pas les hooks de cycle de vie React La méthode leaveOnPageUnload du SDK gère le nettoyage
DOM direct L'exemple utilise getElementById Utiliser useRef<HTMLDivElement> en production
Pas d'état d'erreur Défaillances silencieuses Ajouter useState pour la gestion d'erreur
Effets secondaires au niveau module preLoadWasm() au niveau du module Peut causer des problèmes avec SSR

Pattern React prêt pour la production

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 [isJoining, setIsJoining] = useState(false);
  const [error, setError] = useState<string | null>(null);

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

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

    setIsJoining(true);
    setError(null);

    try {
      // Obtenir signature depuis votre backend
      const response = await fetch('/api/signature', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ meetingNumber, role: 0 }),
      });
      const { signature, sdkKey } = await response.json();

      await clientRef.current.init({
        zoomAppRoot: containerRef.current,
        language: 'en-US',
        patchJsMedia: true,
        leaveOnPageUnload: true,
      });

      await clientRef.current.join({
        signature,
        sdkKey,
        meetingNumber,
        password,
        userName,
      });
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Échec de la connexion');
    } finally {
      setIsJoining(false);
    }
  }, [meetingNumber, password, userName]);

  return (
    <div>
      <div ref={containerRef} style={{ width: '100%', height: '500px' }} />
      <button onClick={joinMeeting} disabled={isJoining}>
        {isJoining ? 'Connexion en cours...' : 'Rejoindre réunion'}
      </button>
      {error && <div className="error">{error}</div>}
    </div>
  );
}

Variables d'environnement (Vite)

# .env.local
VITE_AUTH_ENDPOINT=http://YOUR_AUTH_SERVER_HOST:4000
VITE_SDK_KEY=your_sdk_key
const authEndpoint = import.meta.env.VITE_AUTH_ENDPOINT;
const sdkKey = import.meta.env.VITE_SDK_KEY;

Références détaillées

Documentation principale

Concepts

Dépannage

Exemples

Utilitaires auxiliaires

Extraire le numéro de réunion du lien d'invitation

// Les utilisateurs peuvent coller des liens d'invitation Zoom complets
document.getElementById('meeting_number').addEventListener('input', (e) => {
  // Extraire numéro réunion (9-11 chiffres)
  let meetingNumber = e.target.value.replace(/([^0-9])+/i, '');
  if (meetingNumber.match(/([0-9]{9,11})/)) {
    meetingNumber = meetingNumber.match(/([0-9]{9,11})/)[1];
  }

  // Extraire automatiquement mot de passe du lien d'invitation
  const pwdMatch = e.target.value.match(/pwd=([\d,\w]+)/);
  if (pwdMatch) {
    document.getElementById('password').value = pwdMatch[1];
  }
});

Changement de langue dynamique

// Changer la langue à l'exécution
document.getElementById('language').addEventListener('change', (e) => {
  const lang = e.target.value;
  ZoomMtg.i18n.load(lang);
  ZoomMtg.i18n.reload(lang);
  ZoomMtg.reRender({ lang });
});

Vérifier les exigences système

// Vérifier la compatibilité navigateur avant initialisation
const requirements = ZoomMtg.checkSystemRequirements();
console.log('Infos navigateur :', JSON.stringify(requirements));

if (!requirements.browserInfo.isChrome && !requirements.browserInfo.isFirefox) {
  alert('Pour une meilleure expérience, utilisez Chrome ou Firefox');
}

Dépôts d'exemples

Dépôt Description
meetingsdk-web-sample Exemples officiels (Client View & Component View)
meetingsdk-react-sample Intégration React avec TypeScript + Vite
meetingsdk-web Code source SDK avec helper.html
meetingsdk-auth-endpoint-sample Backend de génération de signature

Ressources officielles


Version de documentation : Basée sur Zoom Web Meeting SDK v3.11+

Besoin d'aide ? Commencez par SKILL.md pour une navigation complète.

Fusionné depuis meeting-sdk/web/SKILL.md

Zoom Meeting SDK (Web) - Index de documentation

Guide de navigation rapide pour toute la documentation Web SDK.

Commencer ici

Document Description
SKILL.md Point d'entrée principal - Démarrages rapides pour les deux vues Client View et Component View

Par type de vue

Client View (page entière)

Document Description
client-view/SKILL.md Référence Client View complète

Component View (intégrable)

Document Description
component-view/SKILL.md Référence Component View complète

Concepts

Document Description
concepts/sharedarraybuffer.md Exigences vidéo HD, en-têtes COOP/COEP
concepts/browser-support.md Matrice de fonctionnalités par navigateur

Exemples

Document Description
examples/client-view-basic.md Intégration Client View basique
examples/component-view-react.md Intégration React avec Component View

Dépannage

Document Description
troubleshooting/error-codes.md Tous les codes d'erreur SDK (plage 3000-10000)
troubleshooting/common-issues.md Diagnostics rapides et corrections

Par sujet

Authentification

Vidéo HD et performance

Événements et callbacks

Government (ZFG)

CDN Chine

Référence rapide

Client View vs Component View

Aspect Client View Component View
Objet ZoomMtg ZoomMtgEmbedded.createClient()
Style API Callbacks Promises
Paramètre mot de passe passWord (W majuscule) password (minuscule)
Événements inMeetingServiceListener() on()/off()

Pièges clés

  1. L'orthographe du mot de passe diffère entre les vues !

    • Client View : passWord (W majuscule)
    • Component View : password (minuscule)
  2. SharedArrayBuffer requis pour les fonctionnalités HD

    • Vidéo 720p/1080p
    • Vue galerie (25 vidéos)
    • Arrière-plans virtuels
  3. Changement d'autorisation mars 2026

    • Les applications rejoignant des réunions externes ont besoin de tokens OBF ou ZAK

Ressources externes

Opérations

  • RUNBOOK.md - Checklist de préflight et débogage de 5 minutes.

Skills similaires