Table des matières
Introduction
Dans un monde où le travail à distance et les interactions virtuelles sont devenus omniprésents, les solutions de communication en temps réel représentent un pilier fondamental de la collaboration moderne. AWS Chime SDK se distingue comme une plateforme puissante qui permet aux développeurs d'intégrer des fonctionnalités avancées de visioconférence, d'audioconférence et de partage d'écran directement dans leurs applications.
Contrairement aux solutions packagées comme Zoom ou Microsoft Teams, AWS Chime SDK n'est pas une application clé en main, mais un ensemble de composants modulaires qui offrent une flexibilité exceptionnelle. Cette approche permet de créer des expériences sur mesure, parfaitement adaptées à vos besoins spécifiques et à votre marque.
AWS Chime SDK fournit les blocs de construction fondamentaux pour créer des expériences de communication en temps réel dans vos applications web, iOS, Android et autres plateformes, sans que vos utilisateurs n'aient besoin d'installer des logiciels supplémentaires ou de créer des comptes séparés.
Dans cet article, nous explorerons en profondeur les capacités d'AWS Chime SDK, comment il fonctionne, et surtout, comment l'implémenter dans vos propres applications pour créer des expériences de visioconférence véritablement interactives. Que vous construisiez une application de télémédecine, une plateforme éducative, un outil de service client ou tout autre système nécessitant des communications en temps réel, vous découvrirez comment Chime SDK peut vous aider à atteindre vos objectifs.
Qu'est-ce qu'AWS Chime SDK ?
AWS Chime SDK est un ensemble d'API, de composants et de bibliothèques client permettant aux développeurs d'intégrer des communications audio, vidéo et de partage d'écran en temps réel dans leurs applications. Contrairement au service AWS Chime standard qui est une solution complète de réunion, Chime SDK est conçu pour les développeurs souhaitant créer leurs propres expériences personnalisées.
Composants clés
Media Services : Pour la gestion des flux audio et vidéo en temps réel
Messaging : Pour l'envoi et la réception de messages texte en temps réel
PSTN Audio : Pour l'intégration avec des systèmes téléphoniques traditionnels
Identity : Pour la gestion des identités et l'attribution des autorisations
Data Messages : Pour l'envoi de données personnalisées entre participants
Meeting Events : Pour recevoir des notifications sur les événements de réunion
Client Libraries : Des bibliothèques pour JavaScript, iOS et Android
Architecture du service
AWS Chime SDK suit une architecture distribuée qui comprend plusieurs composants clés :
Backend AWS Chime : Géré par AWS, ce backend orchestre les sessions de communication
API de contrôle : Permet de créer et gérer des réunions, des participants et des politiques
Service multimédia : Gère les flux audio/vidéo et optimise la qualité en fonction des conditions réseau
Bibliothèques client : S'intègrent dans vos applications pour connecter les utilisateurs au service
AWS Global Network : Infrastructure mondiale qui garantit une faible latence et une haute disponibilité
Modèle de tarification
AWS Chime SDK utilise un modèle de paiement à l'usage, ce qui signifie que vous ne payez que pour ce que vous utilisez. Les tarifs sont basés sur le nombre d'attendees-minutes pour les réunions, le nombre de messages envoyés pour la messagerie, et le nombre de minutes d'appel pour les services PSTN. Il n'y a pas de frais minimum, de coûts d'installation ou d'engagements à long terme.
Capacités principales d'AWS Chime SDK
AWS Chime SDK offre un ensemble complet de fonctionnalités qui permettent de créer des expériences de communication riches et interactives :
Communications audio et vidéo en temps réel
Vidéo HD : Support pour la vidéo haute définition avec adaptation dynamique de la qualité
Audio cristallin : Traitement audio avancé avec suppression du bruit et de l'écho
Partage d'écran : Capacité à partager des écrans entiers ou des applications spécifiques
Arrière-plans virtuels : Possibilité d'implémenter le flou ou le remplacement d'arrière-plan
Mise en page adaptative : Organisation dynamique des vignettes vidéo en fonction du nombre de participants
Mode présentateur : Mise en évidence automatique de l'orateur actif
Messagerie en temps réel
La messagerie Chime SDK permet d'enrichir vos réunions avec des interactions textuelles :
Chats de réunion : Communication textuelle pendant les sessions
Canaux persistants : Discussions continues en dehors des réunions
Messagerie 1:1 : Communications privées entre participants
Transfert de fichiers : Partage de documents et de médias
Indicateurs de présence : Statuts en ligne/hors ligne des utilisateurs
Notifications de lecture : Confirmation de lecture des messages
Intégration téléphonique (PSTN)
AWS Chime SDK permet d'intégrer des communications téléphoniques traditionnelles à vos applications :
SIP Trunking : Connexion aux systèmes téléphoniques existants
Numéros de téléphone : Attribution de numéros dans 100+ pays
Appels entrants/sortants : Gestion des appels téléphoniques
IVR (Réponse Vocale Interactive) : Création de menus vocaux
Transcription en temps réel : Conversion voix-texte pendant les appels
Routage intelligent : Acheminement des appels basé sur des règles
Fonctionnalités interactives
AWS Chime SDK permet de créer des expériences de réunion hautement engageantes grâce à ces fonctionnalités interactives :
Sondages et quizz : Création de questionnaires interactifs pendant les réunions
Tableaux blancs : Collaboration visuelle en temps réel
Réactions : Émojis et autres réactions non verbales
Levée de main : Système de gestion des tours de parole
Breakout rooms : Séparation des participants en sous-groupes
Contrôles de modération : Gestion des droits et permissions des participants
Le saviez-vous ?
AWS Chime SDK est utilisé par de grandes entreprises comme Slack, Mural et Epic Games pour leurs solutions de communication. Par exemple, Slack utilise Chime SDK pour alimenter ses fonctionnalités d'appels audio et vidéo directs entre utilisateurs.
Commencer avec AWS Chime SDK
Maintenant que nous avons une bonne compréhension de ce qu'est AWS Chime SDK et de ses capacités, voyons comment l'intégrer dans une application web.
Prérequis
Un compte AWS actif
Node.js et npm installés
Des connaissances de base en JavaScript et React
Un éditeur de code comme Visual Studio Code
Les permissions IAM appropriées pour utiliser AWS Chime SDK
Implémentation basique d'une visioconférence
Voici un guide étape par étape pour intégrer une visioconférence basique dans une application React :
Étape 1 : Installation des dépendances
1# Création d'un nouveau projet React (si vous n'en avez pas déjà un)
2npx create-react-app chime-video-demo
3cd chime-video-demo
4
5# Installation des bibliothèques AWS Chime SDK
6npm install amazon-chime-sdk-js
7npm install aws-sdk
8
9# Installation des dépendances de backend (pour notre serveur)
10npm install express cors uuid
Étape 2 : Configuration du backend
Créez un fichier server.js à la racine du projet :
1// server.js
2const express = require('express');
3const cors = require('cors');
4const AWS = require('aws-sdk');
5const { v4: uuidv4 } = require('uuid');
6
7// Configuration d'AWS
8AWS.config.update({
9 region: 'us-east-1', // Remplacez par votre région
10 credentials: new AWS.Credentials({
11 accessKeyId: process.env.AWS_ACCESS_KEY_ID,
12 secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY
13 })
14});
15
16const chime = new AWS.Chime({ region: 'us-east-1' });
17// Définir le point de terminaison Chime (choisir le bon point de terminaison pour votre région)
18chime.endpoint = new AWS.Endpoint('https://service.chime.aws.amazon.com');
19
20const app = express();
21app.use(cors());
22app.use(express.json());
23
24// Route pour créer une nouvelle réunion
25app.post('/meetings', async (req, res) => {
26 try {
27 // Créer une nouvelle réunion
28 const meeting = await chime.createMeeting({
29 ClientRequestToken: uuidv4(),
30 MediaRegion: 'us-east-1', // Ou une région plus proche de vos utilisateurs
31 ExternalMeetingId: `ChimeDemo-${uuidv4().substring(0, 8)}` // ID externe pour votre référence
32 }).promise();
33
34 // Créer un participant (attendee)
35 const attendee = await chime.createAttendee({
36 MeetingId: meeting.Meeting.MeetingId,
37 ExternalUserId: `user-${uuidv4().substring(0, 8)}` // ID externe pour le participant
38 }).promise();
39
40 // Renvoyer les informations de réunion et de participant
41 res.json({
42 meeting: meeting.Meeting,
43 attendee: attendee.Attendee
44 });
45 } catch (err) {
46 console.error('Error creating meeting:', err);
47 res.status(500).json({ error: err.message });
48 }
49});
50
51// Route pour rejoindre une réunion existante
52app.post('/attendees', async (req, res) => {
53 try {
54 const { meetingId } = req.body;
55 if (!meetingId) {
56 return res.status(400).json({ error: 'Meeting ID is required' });
57 }
58
59 // Créer un nouveau participant pour une réunion existante
60 const attendee = await chime.createAttendee({
61 MeetingId: meetingId,
62 ExternalUserId: `user-${uuidv4().substring(0, 8)}`
63 }).promise();
64
65 res.json({ attendee: attendee.Attendee });
66 } catch (err) {
67 console.error('Error creating attendee:', err);
68 res.status(500).json({ error: err.message });
69 }
70});
71
72// Route pour terminer une réunion
73app.post('/meetings/:meetingId/end', async (req, res) => {
74 try {
75 const { meetingId } = req.params;
76 await chime.deleteMeeting({
77 MeetingId: meetingId
78 }).promise();
79
80 res.json({ message: 'Meeting deleted successfully' });
81 } catch (err) {
82 console.error('Error deleting meeting:', err);
83 res.status(500).json({ error: err.message });
84 }
85});
86
87const PORT = process.env.PORT || 3001;
88app.listen(PORT, () => {
89 console.log(`Server running on port ${PORT}`);
90});
Étape 3 : Création du composant de visioconférence
Maintenant, créons le composant React pour la visioconférence :
1// src/components/VideoMeeting.js
2import React, { useState, useEffect, useRef } from 'react';
3import {
4 ConsoleLogger,
5 DefaultDeviceController,
6 DefaultMeetingSession,
7 LogLevel,
8 MeetingSessionConfiguration
9} from 'amazon-chime-sdk-js';
10
11const VideoMeeting = () => {
12 const [meetingId, setMeetingId] = useState('');
13 const [joinedMeeting, setJoinedMeeting] = useState(false);
14 const [audioVideo, setAudioVideo] = useState(null);
15 const [attendeeId, setAttendeeId] = useState('');
16 const [attendees, setAttendees] = useState([]);
17
18 const videoTileRef = useRef({});
19 const meetingSessionRef = useRef(null);
20 const localVideoRef = useRef(null);
21 const remoteVideoTilesRef = useRef({});
22
23 // Fonction pour créer une nouvelle réunion
24 const createMeeting = async () => {
25 try {
26 const response = await fetch('http://localhost:3001/meetings', {
27 method: 'POST',
28 headers: {
29 'Content-Type': 'application/json'
30 }
31 });
32
33 const data = await response.json();
34 setMeetingId(data.meeting.MeetingId);
35 setAttendeeId(data.attendee.AttendeeId);
36
37 joinMeeting(data.meeting, data.attendee);
38 } catch (err) {
39 console.error('Error creating meeting:', err);
40 }
41 };
42
43 // Fonction pour rejoindre une réunion
44 const joinMeeting = async (meeting, attendee) => {
45 try {
46 // Configurer le logger
47 const logger = new ConsoleLogger('ChimeMeetingLogs', LogLevel.INFO);
48
49 // Configurer le contrôleur de périphériques
50 const deviceController = new DefaultDeviceController(logger);
51
52 // Créer la configuration de la session
53 const configuration = new MeetingSessionConfiguration(meeting, attendee);
54
55 // Créer la session de réunion
56 const meetingSession = new DefaultMeetingSession(
57 configuration,
58 logger,
59 deviceController
60 );
61
62 meetingSessionRef.current = meetingSession;
63 const av = meetingSession.audioVideo;
64 setAudioVideo(av);
65
66 // Configurer les observateurs
67 setupVideoTileObservers(av);
68 setupAttendeeObservers(av);
69
70 // Démarrer la session
71 await av.start();
72
73 // Activer les périphériques locaux
74 await av.startLocalVideoTile();
75 await av.realtimeMuteLocalAudio(); // Commencer en mode muet
76
77 setJoinedMeeting(true);
78 } catch (err) {
79 console.error('Error joining meeting:', err);
80 }
81 };
82
83 // Configurer les observateurs de tuiles vidéo
84 const setupVideoTileObservers = (av) => {
85 // Gestion des tuiles vidéo
86 av.addObserver({
87 // Appelé quand une nouvelle tuile vidéo est créée
88 videoTileDidUpdate: (tileState) => {
89 if (!tileState.boundAttendeeId) {
90 return;
91 }
92
93 const tileId = tileState.tileId;
94 videoTileRef.current[tileId] = tileState;
95
96 // Si c'est une vidéo locale
97 if (tileState.localTile) {
98 av.bindVideoElement(tileId, localVideoRef.current);
99 } else {
100 // Si c'est une vidéo distante
101 const videoElement = document.createElement('video');
102 videoElement.id = `video-${tileId}`;
103 document.getElementById('remote-videos').appendChild(videoElement);
104 av.bindVideoElement(tileId, videoElement);
105
106 // Stocker la référence pour le nettoyage ultérieur
107 remoteVideoTilesRef.current[tileId] = videoElement;
108 }
109 },
110
111 // Appelé quand une tuile vidéo est supprimée
112 videoTileWasRemoved: (tileId) => {
113 if (remoteVideoTilesRef.current[tileId]) {
114 const videoElement = remoteVideoTilesRef.current[tileId];
115 if (videoElement.parentNode) {
116 videoElement.parentNode.removeChild(videoElement);
117 }
118 delete remoteVideoTilesRef.current[tileId];
119 }
120 delete videoTileRef.current[tileId];
121 }
122 });
123 };
124
125 // Configurer les observateurs de participants
126 const setupAttendeeObservers = (av) => {
127 // Gérer les participants
128 av.realtimeSubscribeToAttendeeIdPresence((attendeeId, present) => {
129 if (present) {
130 // Nouveau participant rejoint
131 setAttendees(prev => [...prev, attendeeId]);
132 } else {
133 // Participant quitte
134 setAttendees(prev => prev.filter(id => id !== attendeeId));
135 }
136 });
137 };
138
139 // Fonction pour quitter la réunion
140 const leaveMeeting = async () => {
141 if (audioVideo) {
142 audioVideo.stopLocalVideoTile();
143 audioVideo.stop();
144
145 // Nettoyer les éléments vidéo distants
146 Object.values(remoteVideoTilesRef.current).forEach(videoElement => {
147 if (videoElement.parentNode) {
148 videoElement.parentNode.removeChild(videoElement);
149 }
150 });
151
152 remoteVideoTilesRef.current = {};
153 setJoinedMeeting(false);
154 setAttendees([]);
155
156 // Si vous êtes l'hôte, vous pouvez aussi terminer la réunion
157 if (meetingId) {
158 try {
159 await fetch(`http://localhost:3001/meetings/${meetingId}/end`, {
160 method: 'POST'
161 });
162 } catch (err) {
163 console.error('Error ending meeting:', err);
164 }
165 }
166 }
167 };
168
169 // Fonction pour activer/désactiver le micro
170 const toggleMute = async () => {
171 if (!audioVideo) return;
172
173 const muted = await audioVideo.realtimeIsLocalAudioMuted();
174 if (muted) {
175 await audioVideo.realtimeUnmuteLocalAudio();
176 } else {
177 await audioVideo.realtimeMuteLocalAudio();
178 }
179 };
180
181 // Fonction pour activer/désactiver la caméra
182 const toggleVideo = async () => {
183 if (!audioVideo) return;
184
185 const videoTile = audioVideo.getLocalVideoTile();
186 if (videoTile && videoTile.state().active) {
187 audioVideo.stopLocalVideoTile();
188 } else {
189 audioVideo.startLocalVideoTile();
190 }
191 };
192
193 // Nettoyer lors du démontage du composant
194 useEffect(() => {
195 return () => {
196 if (joinedMeeting) {
197 leaveMeeting();
198 }
199 };
200 }, [joinedMeeting]);
201
202 return (
203 <div className="video-meeting-container">
204 <h1>AWS Chime SDK Video Meeting</h1>
205
206 {!joinedMeeting ? (
207 <div className="meeting-controls">
208 <button onClick={createMeeting}>Créer une nouvelle réunion</button>
209 <div>
210 <input
211 type="text"
212 placeholder="Entrez l'ID de réunion"
213 value={meetingId}
214 onChange={(e) => setMeetingId(e.target.value)}
215 />
216 <button onClick={() => joinExistingMeeting()}>Rejoindre une réunion existante</button>
217 </div>
218 </div>
219 ) : (
220 <div className="meeting-room">
221 <div className="video-container">
222 <div className="local-video-container">
223 <h3>Vous</h3>
224 <video ref={localVideoRef} className="local-video" />
225 </div>
226
227 <div id="remote-videos" className="remote-videos-container">
228 <h3>Participants ({attendees.length - 1})</h3>
229 {/* Les vidéos distantes seront injectées ici */}
230 </div>
231 </div>
232
233 <div className="meeting-controls">
234 <button onClick={toggleMute}>Activer/Désactiver Micro</button>
235 <button onClick={toggleVideo}>Activer/Désactiver Caméra</button>
236 <button onClick={leaveMeeting} className="leave-button">Quitter la réunion</button>
237 </div>
238
239 <div className="meeting-info">
240 <p>ID de réunion: {meetingId}</p>
241 <p>Partagez cet ID avec d'autres personnes pour qu'elles puissent rejoindre votre réunion.</p>
242 </div>
243 </div>
244 )}
245 </div>
246 );
247};
248
249export default VideoMeeting;
Étape 4 : Intégration dans l'application principale
1// src/App.js
2import React from 'react';
3import './App.css';
4import VideoMeeting from './components/VideoMeeting';
5
6function App() {
7 return (
8 <div className="App">
9 <VideoMeeting />
10 </div>
11 );
12}
13
14export default App;
Étape 5 : Ajout de styles CSS basiques
1/* src/App.css */
2.video-meeting-container {
3 max-width: 1200px;
4 margin: 0 auto;
5 padding: 20px;
6}
7
8.meeting-controls {
9 margin: 20px 0;
10 display: flex;
11 gap: 10px;
12 flex-wrap: wrap;
13}
14
15.video-container {
16 display: flex;
17 flex-wrap: wrap;
18 gap: 20px;
19 margin-bottom: 20px;
20}
21
22.local-video-container, .remote-videos-container {
23 background-color: #f5f5f5;
24 border-radius: 8px;
25 padding: 10px;
26}
27
28.local-video {
29 width: 300px;
30 height: 225px;
31 background-color: #333;
32 border-radius: 4px;
33}
34
35.remote-videos-container {
36 flex-grow: 1;
37 min-height: 225px;
38 display: flex;
39 flex-wrap: wrap;
40 gap: 10px;
41}
42
43.remote-videos-container video {
44 width: 300px;
45 height: 225px;
46 background-color: #333;
47 border-radius: 4px;
48}
49
50button {
51 padding: 10px 15px;
52 background-color: #4CAF50;
53 color: white;
54 border: none;
55 border-radius: 4px;
56 cursor: pointer;
57}
58
59button:hover {
60 background-color: #45a049;
61}
62
63.leave-button {
64 background-color: #f44336;
65}
66
67.leave-button:hover {
68 background-color: #d32f2f;
69}
70
71input[type="text"] {
72 padding: 8px;
73 border: 1px solid #ddd;
74 border-radius: 4px;
75 margin-right: 5px;
76}
77
78.meeting-info {
79 background-color: #e1f5fe;
80 padding: 10px;
81 border-radius: 4px;
82 margin-top: 20px;
83}
Étape 6 : Démarrer l'application
1# Dans un terminal, démarrez le serveur backend
2node server.js
3
4# Dans un autre terminal, démarrez l'application frontend
5npm start
Cette implémentation de base permet la création de réunions, la gestion des participants, et les contrôles audio/vidéo essentiels. Elle peut être étendue avec des fonctionnalités plus avancées comme le partage d'écran, le chat, ou les arrière-plans virtuels.
Fonctionnalités avancées
Maintenant que nous avons mis en place une application de visioconférence de base, explorons quelques fonctionnalités plus avancées qui peuvent rendre votre expérience véritablement interactive.
Partage d'écran
Le partage d'écran est une fonctionnalité essentielle pour les réunions collaboratives. Voici comment l'implémenter :
1// Ajoutez ces fonctions à votre composant VideoMeeting
2
3// Fonction pour démarrer le partage d'écran
4const startScreenShare = async () => {
5 if (!audioVideo) return;
6
7 try {
8 // Demander l'accès au flux d'écran
9 const screenStream = await navigator.mediaDevices.getDisplayMedia({
10 video: true
11 });
12
13 // Récupérer la piste vidéo du flux d'écran
14 const screenTrack = screenStream.getVideoTracks()[0];
15
16 // Arrêter le partage d'écran lorsque l'utilisateur termine
17 screenTrack.addEventListener('ended', () => {
18 stopScreenShare();
19 });
20
21 // Démarrer le partage d'écran via Chime SDK
22 await audioVideo.startContentShare(screenStream);
23 setIsScreenSharing(true);
24 } catch (err) {
25 console.error('Error starting screen share:', err);
26 }
27};
28
29// Fonction pour arrêter le partage d'écran
30const stopScreenShare = async () => {
31 if (!audioVideo) return;
32
33 try {
34 await audioVideo.stopContentShare();
35 setIsScreenSharing(false);
36 } catch (err) {
37 console.error('Error stopping screen share:', err);
38 }
39};
40
41// Ajouter cet observateur dans setupVideoTileObservers
42audioVideo.addContentShareObserver({
43 contentShareDidStart: () => {
44 console.log('Content share started');
45 },
46 contentShareDidStop: () => {
47 console.log('Content share stopped');
48 }
49});
50
51// Puis ajouter un bouton dans l'interface
52<button onClick={isScreenSharing ? stopScreenShare : startScreenShare}>
53 {isScreenSharing ? 'Arrêter le partage' : 'Partager l\'écran'}
54</button>
Chat en temps réel
Ajouter un chat textuel à votre visioconférence enrichit l'interaction :
1// Ajouter ces états et fonctions à votre composant VideoMeeting
2const [messages, setMessages] = useState([]);
3const [messageInput, setMessageInput] = useState('');
4
5// Configurer la gestion des messages de données
6const setupDataMessageObservers = (av) => {
7 // S'abonner au canal de chat (topic: 'chat')
8 av.realtimeSubscribeToReceiveDataMessage('chat', (dataMessage) => {
9 const messageInfo = {
10 senderId: dataMessage.senderAttendeeId,
11 timestamp: new Date(dataMessage.timestampMs),
12 text: dataMessage.text()
13 };
14
15 setMessages(prev => [...prev, messageInfo]);
16 });
17};
18
19// Fonction pour envoyer un message
20const sendMessage = () => {
21 if (!messageInput.trim() || !audioVideo) return;
22
23 // Créer un encodeur de texte
24 const textEncoder = new TextEncoder();
25 // Convertir le message en tableau d'octets
26 const messageData = textEncoder.encode(messageInput);
27
28 // Envoyer le message sur le canal 'chat'
29 audioVideo.realtimeSendDataMessage('chat', messageData);
30
31 // Effacer l'input
32 setMessageInput('');
33};
34
35// Ajouter cet appel dans la fonction joinMeeting après avoir configuré les autres observateurs
36setupDataMessageObservers(av);
37
38// Puis ajouter ce composant d'interface à votre composant de réunion
39<div className="chat-container">
40 <h3>Chat</h3>
41 <div className="messages-container">
42 {messages.map((msg, index) => (
43 <div key={index} className="message">
44 <span className="sender">{msg.senderId === attendeeId ? 'Vous' : `Participant ${msg.senderId.substring(0, 5)}`}</span>
45 <span className="timestamp">{msg.timestamp.toLocaleTimeString()}</span>
46 <p className="message-text">{msg.text}</p>
47 </div>
48 ))}
49 </div>
50 <div className="message-input">
51 <input
52 type="text"
53 value={messageInput}
54 onChange={(e) => setMessageInput(e.target.value)}
55 placeholder="Tapez votre message..."
56 onKeyPress={(e) => e.key === 'Enter' && sendMessage()}
57 />
58 <button onClick={sendMessage}>Envoyer</button>
59 </div>
60</div>
Sondages interactifs
Les sondages sont un excellent moyen d'engager les participants pendant une réunion :
1// Ajouter ces états et fonctions à votre composant VideoMeeting
2const [polls, setPolls] = useState([]);
3const [showPollCreator, setShowPollCreator] = useState(false);
4const [pollQuestion, setPollQuestion] = useState('');
5const [pollOptions, setPollOptions] = useState(['', '']);
6
7// Configuration pour les messages de sondage
8const setupPollObservers = (av) => {
9 // S'abonner au canal 'poll'
10 av.realtimeSubscribeToReceiveDataMessage('poll', (dataMessage) => {
11 try {
12 const pollData = JSON.parse(dataMessage.text());
13
14 if (pollData.type === 'new_poll') {
15 // Nouvel sondage
16 setPolls(prev => [...prev, {
17 id: pollData.pollId,
18 question: pollData.question,
19 options: pollData.options,
20 votes: pollData.options.map(() => 0),
21 createdBy: dataMessage.senderAttendeeId,
22 myVote: null
23 }]);
24 } else if (pollData.type === 'vote') {
25 // Vote pour un sondage existant
26 setPolls(prev => prev.map(poll => {
27 if (poll.id === pollData.pollId) {
28 const newVotes = [...poll.votes];
29 newVotes[pollData.optionIndex] += 1;
30 return { ...poll, votes: newVotes };
31 }
32 return poll;
33 }));
34 }
35 } catch (err) {
36 console.error('Error processing poll message:', err);
37 }
38 });
39};
40
41// Fonction pour créer un nouveau sondage
42const createPoll = () => {
43 if (!pollQuestion.trim() || !audioVideo) return;
44
45 // Filtrer les options vides
46 const validOptions = pollOptions.filter(option => option.trim() !== '');
47 if (validOptions.length < 2) return;
48
49 const pollId = `poll-${Date.now()}`;
50 const pollData = {
51 type: 'new_poll',
52 pollId,
53 question: pollQuestion,
54 options: validOptions
55 };
56
57 // Envoyer le sondage à tous les participants
58 const textEncoder = new TextEncoder();
59 const messageData = textEncoder.encode(JSON.stringify(pollData));
60 audioVideo.realtimeSendDataMessage('poll', messageData);
61
62 // Réinitialiser le créateur de sondage
63 setPollQuestion('');
64 setPollOptions(['', '']);
65 setShowPollCreator(false);
66};
67
68// Fonction pour voter à un sondage
69const votePoll = (pollId, optionIndex) => {
70 if (!audioVideo) return;
71
72 // Enregistrer le vote localement d'abord
73 setPolls(prev => prev.map(poll => {
74 if (poll.id === pollId) {
75 return { ...poll, myVote: optionIndex };
76 }
77 return poll;
78 }));
79
80 // Envoyer le vote à tous les participants
81 const voteData = {
82 type: 'vote',
83 pollId,
84 optionIndex
85 };
86
87 const textEncoder = new TextEncoder();
88 const messageData = textEncoder.encode(JSON.stringify(voteData));
89 audioVideo.realtimeSendDataMessage('poll', messageData);
90};
91
92// Fonction pour ajouter une option de sondage
93const addPollOption = () => {
94 setPollOptions([...pollOptions, '']);
95};
96
97// Ajouter cet appel dans la fonction joinMeeting après avoir configuré les autres observateurs
98setupPollObservers(av);
99
100// Puis ajouter ces composants d'interface
101<div className="poll-container">
102 <h3>Sondages</h3>
103
104 {/* Liste des sondages actifs */}
105 {polls.map((poll, index) => (
106 <div key={index} className="poll">
107 <h4>{poll.question}</h4>
108 <div className="poll-options">
109 {poll.options.map((option, optIndex) => (
110 <div key={optIndex} className="poll-option">
111 <button
112 onClick={() => votePoll(poll.id, optIndex)}
113 disabled={poll.myVote !== null}
114 className={poll.myVote === optIndex ? 'selected' : ''}
115 >
116 {option}
117 </button>
118 <div className="poll-result">
119 <div
120 className="poll-bar"
121 style={{
122 width: `${poll.votes.reduce((a, b) => a + b, 0) > 0 ?
123 (poll.votes[optIndex] / poll.votes.reduce((a, b) => a + b, 0) * 100) : 0}%`
124 }}
125 ></div>
126 <span>{poll.votes[optIndex]} votes</span>
127 </div>
128 </div>
129 ))}
130 </div>
131 </div>
132 ))}
133
134 {/* Créateur de sondage */}
135 {showPollCreator ? (
136 <div className="poll-creator">
137 <h4>Créer un nouveau sondage</h4>
138 <input
139 type="text"
140 placeholder="Question"
141 value={pollQuestion}
142 onChange={(e) => setPollQuestion(e.target.value)}
143 />
144 {pollOptions.map((option, index) => (
145 <input
146 key={index}
147 type="text"
148 placeholder={`Option ${index + 1}`}
149 value={option}
150 onChange={(e) => {
151 const newOptions = [...pollOptions];
152 newOptions[index] = e.target.value;
153 setPollOptions(newOptions);
154 }}
155 />
156 ))}
157 <button onClick={addPollOption}>+ Ajouter une option</button>
158 <div className="poll-actions">
159 <button onClick={() => setShowPollCreator(false)}>Annuler</button>
160 <button onClick={createPoll}>Créer le sondage</button>
161 </div>
162 </div>
163 ) : (
164 <button onClick={() => setShowPollCreator(true)}>Créer un sondage</button>
165 )}
166</div>
Autres fonctionnalités interactives
AWS Chime SDK permet également d'implémenter des fonctionnalités comme les réactions emoji, les tableaux blancs collaboratifs, la transcription en temps réel, la levée de main, et bien d'autres. Chacune de ces fonctionnalités peut être construite en utilisant une combinaison de l'API de base et des messages de données en temps réel.
Bonnes pratiques pour AWS Chime SDK
Pour créer une expérience de visioconférence optimale avec AWS Chime SDK, voici quelques bonnes pratiques à suivre :
Optimisation des performances
Gestion adaptative de la qualité vidéo : Ajustez la résolution et le framerate en fonction de la bande passante disponible
Mise en cache des ressources : Stockez localement les informations de réunion pour une reconnexion rapide en cas de déconnexion
Préchargement des bibliothèques : Chargez les bibliothèques Chime SDK à l'avance pour réduire le temps de démarrage
Gestion efficace des tuiles vidéo : Limitez le nombre de flux vidéo affichés simultanément pour préserver les performances
Optimisation des ressources média : Relâchez les ressources inutilisées (caméra, micro) lorsqu'elles ne sont pas actives
Amélioration de l'expérience utilisateur
Feedback visuel clair : Indiquez clairement l'état des périphériques (micro, caméra) et de la connexion
Tests de périphériques : Permettez aux utilisateurs de tester leur micro et caméra avant de rejoindre une réunion
Mode économie de données : Offrez des options pour réduire la consommation de bande passante
Disposition adaptative : Ajustez l'interface en fonction du nombre de participants et de la taille de l'écran
Gestion des erreurs élégante : Fournissez des messages d'erreur clairs et des solutions de secours
1// Exemple de test de périphériques avant la réunion
2const testAudioVideoDevices = async () => {
3 try {
4 // Créer un contrôleur de périphériques
5 const logger = new ConsoleLogger('DeviceTest', LogLevel.INFO);
6 const deviceController = new DefaultDeviceController(logger);
7
8 // Liste des périphériques audio d'entrée (microphones)
9 const audioInputDevices = await deviceController.listAudioInputDevices();
10 console.log('Microphones disponibles:', audioInputDevices);
11
12 // Liste des périphériques audio de sortie (haut-parleurs)
13 const audioOutputDevices = await deviceController.listAudioOutputDevices();
14 console.log('Haut-parleurs disponibles:', audioOutputDevices);
15
16 // Liste des périphériques vidéo (caméras)
17 const videoInputDevices = await deviceController.listVideoInputDevices();
18 console.log('Caméras disponibles:', videoInputDevices);
19
20 // Tester l'accès au microphone
21 if (audioInputDevices.length > 0) {
22 await deviceController.startAudioInput(audioInputDevices[0].deviceId);
23 console.log('Microphone connecté avec succès');
24
25 // Créer un analyseur audio pour visualiser le niveau sonore
26 const audioAnalyserNode = deviceController.createAnalyserNodeForAudioInput();
27 // Utiliser audioAnalyserNode pour créer un indicateur de niveau sonore
28 }
29
30 // Tester l'accès à la caméra
31 if (videoInputDevices.length > 0) {
32 await deviceController.startVideoInput(videoInputDevices[0].deviceId);
33 console.log('Caméra connectée avec succès');
34
35 // Prévisualiser la vidéo
36 const videoElement = document.getElementById('video-preview');
37 deviceController.bindVideoElement(videoElement);
38 }
39
40 return {
41 audioInputDevices,
42 audioOutputDevices,
43 videoInputDevices
44 };
45 } catch (err) {
46 console.error('Erreur lors du test des périphériques:', err);
47 throw err;
48 }
49};
Considérations de sécurité
Protection des informations de réunion : Utilisez des mécanismes d'authentification pour limiter l'accès aux réunions
Contrôle d'accès granulaire : Attribuez des rôles (hôte, participant) avec des permissions appropriées
Chiffrement des communications : Assurez-vous que toutes les communications sont chiffrées
Rotation des identifiants : Régénérez les jetons de présence pour les sessions de longue durée
Audit des événements : Enregistrez les activités importantes comme les connexions et déconnexions
Cas d'utilisation réels
AWS Chime SDK est utilisé dans de nombreux secteurs pour créer des expériences de communication personnalisées. Voici quelques cas d'utilisation concrets :
Télémédecine
Les plateformes de télémédecine utilisent AWS Chime SDK pour connecter les patients et les professionnels de santé via des consultations vidéo sécurisées. Ces solutions incluent souvent :
Salles d'attente virtuelles pour gérer les rendez-vous
Partage sécurisé de documents médicaux pendant les consultations
Intégration avec des systèmes de dossiers médicaux électroniques
Possibilité d'inviter des spécialistes pour des consultations multidisciplinaires
Enregistrement des sessions avec le consentement du patient pour le suivi
Exemple : Amwell
Amwell, une plateforme de télésanté leader, utilise AWS Chime SDK pour permettre aux médecins de consulter les patients à distance, réduisant ainsi les délais d'attente et améliorant l'accès aux soins, en particulier dans les zones rurales.
Éducation en ligne
Les plateformes d'apprentissage en ligne utilisent AWS Chime SDK pour créer des salles de classe virtuelles interactives avec des fonctionnalités comme :
Tableaux blancs interactifs pour les explications visuelles
Salles de sous-groupes pour les travaux collaboratifs
Systèmes de levée de main et de sondages pour l'engagement des élèves
Partage de documents et de présentations éducatives
Enregistrement des cours pour révision ultérieure
Service client virtuel
Les entreprises utilisent AWS Chime SDK pour offrir un support client par vidéo, créant une expérience plus personnelle et efficace :
Assistance vidéo intégrée directement dans les applications mobiles ou web
Co-navigation pour guider les clients à travers des processus complexes
Partage d'écran pour le dépannage technique
Intégration avec les systèmes CRM pour un contexte client complet
File d'attente intelligente et routage vers les agents appropriés
Conclusion
AWS Chime SDK représente une solution puissante et flexible pour intégrer des communications audio et vidéo en temps réel dans vos applications. Contrairement aux plateformes de visioconférence prêtes à l'emploi, Chime SDK vous donne un contrôle total sur l'expérience utilisateur, vous permettant de créer des solutions parfaitement adaptées à vos besoins spécifiques.
Les points clés à retenir incluent :
Flexibilité et personnalisation : Créez une expérience de communication qui s'intègre parfaitement à votre application et à votre marque
Évolutivité : Gérez des milliers d'utilisateurs simultanés grâce à l'infrastructure mondiale d'AWS
Richesse des fonctionnalités : Audio, vidéo, partage d'écran, chat, et bien plus encore dans une seule solution
Modèle de paiement à l'usage : Optimisez vos coûts en ne payant que pour ce que vous utilisez
Intégration transparente : Combinez Chime SDK avec d'autres services AWS pour des solutions complètes
Dans un monde où les communications distantes sont devenues essentielles, AWS Chime SDK offre aux développeurs les outils nécessaires pour créer des expériences de communication riches et engageantes. Que vous développiez une application de télémédecine, une plateforme éducative, ou un système de service client, Chime SDK vous permet d'intégrer des communications en temps réel de manière efficace et économique.
Pour commencer avec AWS Chime SDK, consultez la documentation officielle et explorez les exemples disponibles sur le GitHub d'AWS. N'hésitez pas à expérimenter avec les différentes fonctionnalités pour découvrir comment elles peuvent améliorer votre application.