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.