1 Grabación automática de transmisiones en vivo de Amazon IVS en S3 |
---|
2 Archivado de mensajes de chat web con Amazon IVS Chat Logging |
3 Reproducción de transmisión en vivo de Amazon IVS con reproducción de chat |
Al tratar de resolver este problema, lo primero que pensé fue echar un vistazo a los metadatos asociados con una transmisión en vivo para ver si hay información valiosa oculta en ellos. Afortunadamente, parece haber un valor en el flujo regular de metadatos que se puede usar para nuestros propósitos de reproducción de chat. En mis pruebas, cada transmisión contiene metadatos ID3 que parecen haber sido inyectados por el proceso de transcodificación de Amazon IVS. Estas etiquetas ID3 contienen una marca de tiempo útil que podemos usar para ayudar con la reproducción del chat. Para escuchar estos eventos, podemos adjuntar un controlador que escuche el tipo de evento IVSPlayer.MetadataEventType.ID3
. Este tipo de evento está documentado, pero los no dicen mucho al respecto ni garantizan lo que puede contener.
¿ Quiere evitar funciones no documentadas ? Si le preocupa usar una función no documentada, puede con la marca de tiempo adecuada cuando se publiquen nuevos mensajes en sus salas de chat de Amazon IVS. Tenga en cuenta que existen de eventos
PutMetadata
a través de la API.
Configuremos un reproductor de Amazon IVS para reproducir una transmisión grabada con Player SDK. En primer lugar, incluiremos el SDK de reproductor de Amazon IVS más reciente a través de una etiqueta <script>
.
¿Nuevo en Amazon IVS? Consulte la serie de blogs . Si tiene preguntas sobre cómo comenzar, publique un comentario en cualquier publicación de esa serie (o debajo).
<script src="//player.live-video.net/1.16.0/amazon-ivs-player.min.js"></script>
Como de costumbre, necesitaremos incluir un elemento <video>
en nuestro marcado HTML que se usará para la reproducción.
<video id="video-player" muted controls autoplay playsinline></video>
const streamUrl = '//[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();
ivsPlayer.addEventListener(IVSPlayer.PlayerState.PLAYING, (evt) => { window.time = Date.now(); });
ivsPlayer.addEventListener(IVSPlayer.MetadataEventType.ID3, (evt) => { const now = Date.now(); console.log(`${(now - window.time) / 1000} seconds since last event`); window.time = now; });
window.ivsPlayer.addEventListener(IVSPlayer.MetadataEventType.ID3, (evt) => { console.log(evt); });
Esta es una información muy interesante, pero un poco críptica. Según mis pruebas, transc_s
parece ser la marca de tiempo que buscamos. Modifiquemos el controlador de eventos para tomar esa marca de tiempo y registrarla.
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)); });
Cuando se carga mi página, puedo utilizar el método descrito en la publicación anterior [todo: enlace] de esta serie para recuperar todo el registro de chat de la transmisión y representarlo en el contenedor de chat <div>
. Dado que ningún mensaje debe estar visible al comienzo de la transmisión, me aseguraré de que las llamadas contengan una clase que los oculte del usuario y almacene un atributo de datos con la marca de tiempo adecuada para poder saber qué mensajes deben estar visibles. dada cualquier marca de tiempo en la transmisión.
window.chatLog = await getChatLogs(logGroupName, chatArn, startTime, endTime); renderChat();
Mi función renderChat()
maneja la publicación de cada mensaje en el contenedor de chat.
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); }); };
Ahora puedo modificar el oyente ID3 para llamar a una función replayChat()
y pasarle la marca de tiempo actual.
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); });
En replayChat()
, puedo encontrar todos los nodos de chat que contienen una marca de tiempo menor o igual que la marca de tiempo actual de la transmisión grabada y mostrar/ocultar cualquier mensaje de chat basado en esa marca de tiempo.
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; }