2 Arquivamento de mensagens de bate-papo da Web com registro de bate-papo do Amazon IVS |
3 Reprodução de transmissão ao vivo do Amazon IVS com reprodução de bate-papo |
Ao tentar resolver esse problema, meu primeiro pensamento foi dar uma olhada nos metadados associados a uma transmissão ao vivo para ver se havia alguma informação valiosa escondida nela. Felizmente, parece haver um valor no fluxo regular de metadados que pode ser usado para nossos propósitos de reprodução de bate-papo. Em meus testes, cada stream contém metadados ID3 que parecem ser injetados pelo processo de transcodificação do Amazon IVS. Essas tags ID3 contêm um registro de data e hora útil que podemos usar para ajudar na reprodução do bate-papo. Para escutar esses eventos, podemos anexar um manipulador que escuta o tipo de evento IVSPlayer.MetadataEventType.ID3
. Este tipo de evento está documentado, mas os não dizem muito sobre ele ou dão qualquer garantia sobre o que ele pode conter.
Quer evitar recursos não documentados ? Se estiver preocupado em usar um recurso não documentado, você pode com o carimbo de data/hora adequado quando novas mensagens forem postadas em suas salas de bate-papo do Amazon IVS. Lembre-se de que há eventos
PutMetadata
por meio da API.
Vamos configurar um player Amazon IVS para reproduzir um stream gravado usando o Player SDK. Primeiro, incluiremos o SDK do player Amazon IVS mais recente por meio de uma tag <script>
.
Novo no Amazon IVS? Confira a série de blogs . Se você tiver dúvidas sobre como começar, poste um comentário em qualquer postagem dessa série (ou abaixo)!
<script src="//player.live-video.net/1.16.0/amazon-ivs-player.min.js"></script>
Como de costume, precisaremos incluir um elemento <video>
em nossa marcação HTML que será usado para reprodução.
<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 é uma informação muito interessante, mas um pouco enigmática. Com base em meus testes, transc_s
parece ser o carimbo de data/hora que procuramos. Vamos modificar o manipulador de eventos para obter esse carimbo de data/hora e registrá-lo.
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)); });
Quando minha página é carregada, posso utilizar o método descrito na postagem anterior [todo: link] desta série para recuperar todo o log de bate-papo do stream e renderizá-lo no contêiner de bate-papo <div>
. Como nenhuma mensagem deve estar visível no início do stream, garantirei que elas contenham uma classe que as oculte do usuário e armazene um atributo de dados com o carimbo de data/hora adequado para que eu possa saber quais mensagens devem ser visíveis dado qualquer carimbo de data/hora no fluxo.
window.chatLog = await getChatLogs(logGroupName, chatArn, startTime, endTime); renderChat();
Minha função renderChat()
lida com a postagem de cada mensagem no contêiner de bate-papo.
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); }); };
Agora posso modificar o ouvinte ID3 para chamar uma função replayChat()
e passar o registro de data e hora atual.
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); });
Em replayChat()
, posso encontrar todos os nós de bate-papo que contêm um registro de data e hora menor ou igual ao registro de data e hora atual do fluxo gravado e mostrar/ocultar qualquer mensagem de bate-papo com base nesse registro de data e hora.
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; }