1 Enregistrement automatique des flux en direct d'Amazon IVS sur S3 |
---|
2 Archivage des messages de chat Web avec Amazon IVS Chat Logging |
3 Lecture de flux en direct Amazon IVS avec relecture de chat |
Dans nos derniers articles, nous avons examiné comment enregistrer automatiquement les flux en direct d'Amazon Interactive Video Service (Amazon IVS) sur Amazon S3 et comment consigner les messages envoyés à une salle de discussion Amazon IVS (voir les liens ci-dessus). Dans cet article, nous allons réunir ces deux concepts pour compléter l'expérience utilisateur et créer une lecture à la demande des flux en direct passés avec une relecture complète du chat.
Comme nous l'avons vu dans notre dernier article, les messages de discussion qui sont enregistrés dans la destination de journalisation incluent un horodatage basé sur l'heure GMT représentant la date et l'heure auxquelles l'événement a été publié par la salle de discussion Amazon IVS. Pour réaliser une véritable relecture à la demande d'un flux en direct avec une relecture interactive d'un message au moment le plus proche possible, nous devons obtenir un flux régulier d'horodatages basés sur GMT à partir du flux enregistré que nous pouvons utiliser pour déterminer ce que les messages de chat doivent être visibles à tout moment dans la lecture du flux. Il n'existe actuellement aucune source documentée fournissant ces informations, mais examinons le SDK du lecteur Amazon IVS et voyons si nous pouvons trouver quelque chose qui nous aidera dans cette tâche.
Lorsque j'ai essayé de résoudre ce problème, ma première pensée a été de jeter un coup d'œil aux métadonnées associées à un flux en direct pour voir s'il y avait des informations précieuses cachées à l'intérieur. Heureusement, il semble y avoir une valeur dans le flux régulier de métadonnées qui peuvent être utilisées à des fins de lecture de chat. Lors de mes tests, chaque flux contient des métadonnées ID3 qui semblent être injectées par le processus de transcodage Amazon IVS. Ces balises ID3 contiennent un horodatage utile que nous pouvons utiliser pour faciliter la relecture du chat. Pour écouter ces événements, nous pouvons attacher un gestionnaire qui écoute le type d'événement IVSPlayer.MetadataEventType.ID3
. Ce type d'événement est documenté, mais la documentation n'en dit pas grand-chose et ne donne aucune garantie sur ce qu'il peut contenir.
Vous voulez éviter les fonctionnalités non documentées ? Si vous êtes préoccupé par l'utilisation d'une fonctionnalité non documentée, vous pouvez injecter vos propres métadonnées chronométrées dans votre flux en direct avec l'horodatage approprié lorsque de nouveaux messages sont publiés dans vos salles de discussion Amazon IVS. Gardez à l'esprit qu'il existe des limites à la taille et à la fréquence de publication des événements
PutMetadata
via l'API.
Configurons un lecteur Amazon IVS pour lire un flux enregistré à l'aide du SDK du lecteur. Tout d'abord, nous allons inclure le dernier SDK du lecteur Amazon IVS via une balise <script>
.
Nouveau sur Amazon IVS ? Consultez la série de blogs Premiers pas avec Amazon Interactive Video Service . Si vous avez des questions sur le démarrage, postez un commentaire sur n'importe quel article de cette série (ou ci-dessous) !
<script src="https://player.live-video.net/1.16.0/amazon-ivs-player.min.js"></script>
Comme d'habitude, nous devrons inclure un élément <video>
dans notre balisage HTML qui sera utilisé pour la lecture.
<video id="video-player" muted controls autoplay playsinline></video>
Nous pouvons maintenant créer une instance du lecteur IVS. Je code en dur l'URL ci-dessous, mais vous pouvez obtenir cette URL via la méthode décrite dans ce post [todo: link].
const streamUrl = 'https://[redacted].cloudfront.net/ivs/v1/[redacted]/[redacted]/2022/11/17/18/6/[redacted]/media/hls/master.m3u8'; const videoEl = document.getElementById('video-player'); const ivsPlayer = IVSPlayer.create(); ivsPlayer.attachHTMLVideoElement(videoEl); ivsPlayer.load(streamUrl); ivsPlayer.play();
Comme mentionné ci-dessus, pour être utile à cette fin, nous avons besoin d'un flux régulier d'horodatages. Pour déterminer la fréquence de réception des métadonnées ID3, ajoutons un peu de temps. Tout d'abord, capturons un horodatage dès que le flux commence à jouer.
ivsPlayer.addEventListener(IVSPlayer.PlayerState.PLAYING, (evt) => { window.time = Date.now(); });
Ensuite, nous allons ajouter l'écouteur d'événement ID3, enregistrer la synchronisation et réinitialiser le minuteur.
ivsPlayer.addEventListener(IVSPlayer.MetadataEventType.ID3, (evt) => { const now = Date.now(); console.log(`${(now - window.time) / 1000} seconds since last event`); window.time = now; });
Nous pouvons maintenant démarrer la lecture et observer la console pour voir à quelle fréquence les événements sont déclenchés.
Dans mes tests, les événements sont déclenchés toutes les 1 à 2 secondes. Ce n'est pas en temps réel, mais c'est probablement suffisant pour la plupart des scénarios. Examinons maintenant l'événement pour voir quelles données il contient.
window.ivsPlayer.addEventListener(IVSPlayer.MetadataEventType.ID3, (evt) => { console.log(evt); });
Lorsque nous commençons la lecture avec l'écouteur ci-dessus attaché, nous pouvons voir les informations suivantes enregistrées dans la console du navigateur.
C'est une information très intéressante, mais un peu énigmatique. D'après mes tests, transc_s
semble être l'horodatage que nous recherchons. Modifions le gestionnaire d'événements pour saisir cet horodatage et le consigner.
window.ivsPlayer.addEventListener(IVSPlayer.MetadataEventType.ID3, (evt) => { const segmentMetadata = evt.find((tag) => tag.desc === 'segmentmetadata'); const segmentMetadataInfo = JSON.parse(segmentMetadata.info[0]); const timestamp = segmentMetadataInfo['transc_s']; const timestampWithMs = timestamp * 1000; console.log(timestampWithMs); console.log(new Date(timestamp)); });
Cela produit la sortie suivante pour mon test.
Si je cherche un moment aléatoire dans la vidéo, l'horodatage approprié est toujours correct. Cela signifie que toutes les 1 à 2 secondes, nous connaissons un horodatage GMT valide du moment où l'événement a été capturé dans le flux. Cela signifie que nous pouvons supposer que tous les messages de chat qui ont été envoyés avant cet horodatage ont été publiés sur le chat et doivent être visibles dans le conteneur de chat.
Lorsque ma page se charge, je peux utiliser la méthode décrite dans le post précédent [todo: link] de cette série pour récupérer l'intégralité du journal de discussion pour le flux et le rendre dans le conteneur de discussion <div>
. Étant donné qu'aucun message ne doit être visible au tout début du flux, je m'assurerai qu'ils contiennent une classe qui les masque à l'utilisateur et stocke un attribut de données avec l'horodatage approprié afin que je puisse savoir quels messages doivent être visibles étant donné n'importe quel horodatage dans le flux.
window.chatLog = await getChatLogs(logGroupName, chatArn, startTime, endTime); renderChat();
Ma fonction renderChat()
gère la publication de chaque message dans le conteneur de discussion.
const renderChat = () => { const chatContainer = document.getElementById('chat'); window.chatLog.forEach(msg => { const msgTemplate = document.getElementById('chatMsgTemplate'); const msgEl = msgTemplate.content.cloneNode(true); const ts = new Date(msg.event_timestamp).getTime() * 1000; msgEl.querySelector('.msg-container').setAttribute('data-timestamp', ts); msgEl.querySelector('.chat-username').innerHTML = msg.payload.Attributes.username; msgEl.querySelector('.msg').innerHTML = msg.payload.Content; chatContainer.appendChild(msgEl); }); };
Maintenant, je peux modifier l'écouteur ID3 pour appeler une fonction replayChat()
et lui transmettre l'horodatage actuel.
window.ivsPlayer.addEventListener(IVSPlayer.MetadataEventType.ID3, (evt) => { const segmentMetadata = evt.find((tag) => tag.desc === 'segmentmetadata'); const segmentMetadataInfo = JSON.parse(segmentMetadata.info[0]); const timestamp = segmentMetadataInfo['transc_s']; const timestampWithMs = timestamp * 1000; replayChat(timestampWithMs); });
Dans replayChat()
, je peux trouver tous les nœuds de chat qui contiennent un horodatage inférieur ou égal à l'horodatage actuel du flux enregistré et afficher/masquer tout message de chat basé sur cet horodatage.
const replayChat = (currentTimestamp) => { Array.from(document.querySelectorAll('[data-timestamp]')).forEach(node => { const chatMsgTs = Number(node.getAttribute('data-timestamp')); const isVisible = chatMsgTs <= currentTimestamp; if (isVisible) { node.classList.remove('d-none'); } else { node.classList.add('d-none'); } }); const chatContainer = document.getElementById('chat'); chatContainer.scrollTop = chatContainer.scrollHeight; }
À ce stade, nous avons atteint l'objectif de lire un flux en direct Amazon IVS enregistré avec une relecture complète du chat.
Dans cet article, nous avons examiné comment combiner des flux en direct Amazon IVS enregistrés avec des messages de chat enregistrés pour créer une relecture à la demande d'un flux avec des messages de chat correctement chronométrés.