Hasta ahora, en esta serie de blogs, creamos nuestro primer canal de transmisión en vivo, aprendimos cómo crear una experiencia de reproducción en el navegador y mejoramos esa experiencia con el reproductor SDK de Amazon Interactive Video Service (Amazon IVS). En las próximas publicaciones, veremos cómo agregar algo de interactividad a nuestra experiencia de reproducción.
La transmisión en vivo es claramente popular, pero es más que solo el video lo que atrae a los espectadores. Interactuar con la emisora y otros espectadores es una de las principales razones por las que muchas personas siguen volviendo a ciertas transmisiones y transmisores. Amazon IVS nos brinda algunas características bastante sorprendentes que permiten la interactividad, y uno de los elementos más geniales que podemos usar para mejorar nuestra transmisión en vivo son los metadatos cronometrados (obligatorio " ").
<video id="video-player" controls autoplay playsinline></video>
const videoEl = document.getElementById('video-player'); const streamUrl = '//fcc3ddae59ed.us-west-2.playback.live-video.net/api/video/v1/us-west-2.893648527354.channel.xhP3ExfcX8ON.m3u8'; const ivsPlayer = IVSPlayer.create(); ivsPlayer.attachHTMLVideoElement(videoEl); ivsPlayer.load(streamUrl); ivsPlayer.play();
Esta transmisión es un ejemplo de una transmisión de "trivia en vivo" donde el anfitrión lee algunas preguntas de trivia. Se incrusta un evento de metadatos cronometrado en el momento exacto en que el host lee una pregunta de trivia. Podemos escuchar y responder a este evento. Si recuerda nuestra última publicación, podemos usar addEventListener()
en el reproductor de Amazon IVS para escuchar varios eventos, y TEXT_METADATA_CUE
( ) es uno de esos eventos.
ivsPlayer.addEventListener(IVSPlayer.PlayerEventType.TEXT_METADATA_CUE, (e) => { console.log(e); });
Si reproducimos nuestra transmisión, podemos verificar la consola después de que el anfitrión lea una pregunta y observe el evento registrado. Debería verse similar a esto: { "startTime": 61.04233333333333, "endTime": 61.04233333333333, "type": "TextMetadataCue", "description": "", "text": "{\"question\": \"From what language does the term RSVP originate from?\",\"answers\": [ \"Russian\", \"Italian\", \"French\", \"Portuguese\" ],\"correctIndex\": 2}", "owner": "metadata.live-video.net" }
La clave startTime
representa el tiempo transcurrido desde que comenzó la transmisión hasta que tuvo lugar el evento (61 segundos en el ejemplo anterior). Lo interesante que buscamos aquí es la clave de text
, que contiene los metadatos. Aquí, es una cadena JSON, pero puede ser lo que necesites que sea.
const metadata = JSON.parse(e.text);
La estructura de metadatos analizados utiliza la siguiente estructura: { "question": "From what language does the term RSVP originate from?", "answers": [ "Russian", "Italian", "French", "Portuguese" ], "correctIndex": 2 }
<div class="card mt-3"> <div class="card-header bg-dark text-white"> <h4>Question</h4> </div> <div class="card-body"> <div class="card-title"> <h4 id="question"></h4> </div> <div id="answerContainer"> <ul id="answers" class="list-group"></ul> </div> </div> <div class="card-footer text-center"> <button class="btn btn-dark" id="check-answer-btn" disabled>Submit</button> </div> </div>
Así que tenemos un contenedor para nuestra pregunta y las respuestas. También hemos agregado un botón para verificar la respuesta que inicialmente está disabled
. Agreguemos algo de código dentro de nuestro controlador de eventos para almacenar la respuesta correcta en el alcance global para que podamos verificar la respuesta del usuario más adelante.
window.correctIndex = metadata.correctIndex;
Ahora podemos habilitar el botón Enviar, mostrar la pregunta y borrar el contenedor de respuestas. // enable the submit button document.getElementById('check-answer-btn').removeAttribute('disabled'); // display the question document.getElementById('question').innerHTML = metadata.question; // clear previous answers const answersEl = document.getElementById('answers'); answersEl.replaceChildren();
Ahora podemos recorrer todas las respuestas en el objeto de metadatos y mostrarlas en la página. // render the answers for this question metadata.answers.forEach((a, i) => { // create an answer container const answerEl = document.createElement('li'); answerEl.classList.add('list-group-item'); // radio button to select the answer const answerRadio = document.createElement('input'); answerRadio.setAttribute('name', 'answer-input'); answerRadio.type = 'radio'; answerRadio.id = `answer-input-${i}`; answerRadio.classList.add('me-2', 'form-check-input'); answerRadio.dataset.index = i; answerEl.appendChild(answerRadio); // label to display the answer text const answerLbl = document.createElement('label'); answerLbl.setAttribute('for', `answer-input-${i}`); answerLbl.innerHTML = a; answerEl.appendChild(answerLbl); answersEl.appendChild(answerEl); });
const checkAnswer = () => { // disable the submit btn document.getElementById('check-answer-btn').setAttribute('disabled', 'disabled'); // check the current answer const selectedAnswer = document.querySelector('input[name="answer-input"]:checked'); const selectedIdx = parseInt(selectedAnswer.dataset.index); // highlight the correct answer document.querySelector(`input[data-index="${window.correctIndex}"]`).nextSibling.classList.add('text-success'); // if they're wrong, highlight the incorrect answer if (selectedIdx !== window.correctIndex) { selectedAnswer.nextSibling.classList.add('text-danger'); } }
No olvide adjuntar un detector de eventos para el evento de click
en nuestro botón Enviar . Agregaremos eso en nuestra función init()
.
document.getElementById('check-answer-btn').addEventListener('click', checkAnswer);
¡Y estamos listos para verlo en acción! Si estás jugando en casa, compara tu código con el código de la demostración a continuación. Si no, échale un vistazo de todos modos para ver la solución final. ¡Pruébelo y vea cuántas preguntas puede acertar! Hemos visto cómo consumir metadatos, pero aún no hemos visto cómo producirlos. No te preocupes, ¡no es tan difícil de hacer! Hay varias formas de producir metadatos cronometrados y todas requieren el ARN del canal . Puede obtener este valor de la consola de administración de Amazon IVS en los detalles del canal o a través de la CLI de AWS.
$ aws \ ivs \ list-channels \ --filter-by-name [YOUR CHANNEL NAME] \ --query "channels[0].arn" \ --output text
¿Necesita instalar la CLI? Revisar la
$ aws \ ivs \ put-metadata \ --channel-arn [YOUR CHANNEL ARN] \ --metadata '{"test": true}'
. import AWS from 'aws-sdk'; const Ivs = new AWS.IVS({ region: 'us-east-1', credentials }); const putMetadata = async (metadata) => { const input = { channelArn: '[YOUR CHANNEL ARN]', metadata: JSON.stringify(metadata) }; let output; try { output = await Ivs.putMetadata(input).promise(); } catch (e) { console.error(e); if (e.name === 'ChannelNotBroadcasting') { output = { offline: true }; } else { throw new Error(e); } } return output; }
. import boto3 client = boto3.client('ivs') response = client.put_metadata( channelArn='[YOUR CHANNEL ARN]', metadata='{"python": true}' ) print(response)
.