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 (
passwordici, paspassWord) - 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 :
- Choisissez votre vue - Client View vs Component View - Comprenez les différences architecturales clés
- Démarrage rapide - Client View ou Component View - Obtenez une réunion fonctionnelle en quelques minutes
- SharedArrayBuffer - concepts/sharedarraybuffer.md - Requis pour la vidéo HD, la vue galerie, les arrière-plans virtuels
- 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 ?
- Component View vous donne une API basée sur les Promises et une interface utilisateur intégrable
- Client View vous donne l'expérience Zoom en page entière familière
- Pour une interface de réunion personnalisée, préférez d'abord Component View
- Exemple de routage inter-produits : ../../general/use-cases/custom-meeting-ui-web.md
- Prise en charge des navigateurs - Matrice de fonctionnalités par navigateur
- Chemin d'approfondissement exact : component-view/SKILL.md
Vous rencontrez des problèmes ?
- Erreurs de connexion → Vérifiez la génération de signature et l'orthographe du mot de passe (
passWordvspassword) - 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() :
- Exécutez les diagnostiques de permissions/appareil/réseau Probe.
- Appliquez la politique de disponibilité (
allow,warn,block). - Continuez vers la connexion Meeting SDK uniquement pour
allow/avertissements approuvéswarn.
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(ouclientIdpour les applications plus récentes)meetingNumberrole(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
-
App Privilege Token (OBF) - Recommandé pour les bots
ZoomMtg.join({ ... obfToken: 'your-app-privilege-token' }); -
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
- SKILL.md - Guide complet de navigation
- client-view/SKILL.md - Référence Client View complète
- component-view/SKILL.md - Référence Component View complète
Concepts
- concepts/sharedarraybuffer.md - Exigences vidéo HD
- concepts/browser-support.md - Matrice de fonctionnalités par navigateur
Dépannage
- troubleshooting/error-codes.md - Tous les codes d'erreur SDK
- troubleshooting/common-issues.md - Diagnostics rapides
Exemples
- client-view/SKILL.md - Guide Client View complet
- component-view/SKILL.md - Intégration React Component View
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
- Docs officielles : https://developers.zoom.us/docs/meeting-sdk/web/
- Référence API Client View : https://marketplacefront.zoom.us/sdk/meeting/web/index.html
- Référence API Component View : https://marketplacefront.zoom.us/sdk/meeting/web/components/index.html
- Forum développeurs : https://devforum.zoom.us/
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
- SKILL.md#authentification-endpoint - Génération de signature
- SKILL.md#exigences-dautorisation-mise-à-jour-2026 - Tokens OBF
Vidéo HD et performance
- concepts/sharedarraybuffer.md - Activer 720p/1080p
Événements et callbacks
- SKILL.md#écouteurs-dévénements-client-view - Événements Client View
- SKILL.md#écouteurs-dévénements-component-view - Événements Component View
Government (ZFG)
- SKILL.md#zoom-for-government-zfg - Configuration ZFG
CDN Chine
- SKILL.md#cdn-chine - CDN spécifique à la 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
-
L'orthographe du mot de passe diffère entre les vues !
- Client View :
passWord(W majuscule) - Component View :
password(minuscule)
- Client View :
-
SharedArrayBuffer requis pour les fonctionnalités HD
- Vidéo 720p/1080p
- Vue galerie (25 vidéos)
- Arrière-plans virtuels
-
Changement d'autorisation mars 2026
- Les applications rejoignant des réunions externes ont besoin de tokens OBF ou ZAK
Ressources externes
- Docs officielles : https://developers.zoom.us/docs/meeting-sdk/web/
- API Client View : https://marketplacefront.zoom.us/sdk/meeting/web/index.html
- API Component View : https://marketplacefront.zoom.us/sdk/meeting/web/components/index.html
- Exemples GitHub : https://github.com/zoom/meetingsdk-web-sample
Opérations
- RUNBOOK.md - Checklist de préflight et débogage de 5 minutes.