Lectura de metadatos de la <pista> de un <video> HTML5 usando Captionator

Tengo problemas para get un ejemplo de trabajo que lea los metadatos de un file WebVTT, que fue especificado por el elemento <track> de un <video> en una página HTML5. Para ser claros, no estoy hablando de leer los metadatos del file de video en sí (como lo haría con un MPEG Transport Stream, por ejemplo). De lo que estoy hablando es del elemento <track> que se usa para subtitular videos. Uno de los attributes de un <track> es kind , que se puede especificar como cualquiera de los siguientes valores:

  • Subtítulos
  • Descripciones
  • Subtítulos
  • Navegación
  • Capítulos
  • Metadata

Estoy tratando de usar el tipo de metadatos para acceder al text almacenado en el file WebVTT correspondiente, que pretendo manipular usando JavaScript. Sé que esto es posible, como lo mencionan Silvia Pfeiffer y el creador de Captionator , que es el relleno policial de JavaScript que estoy usando para implementar la funcionalidad de interpretar las tags <track> . Sin embargo, simplemente no puedo hacer que funcione.

Mi código se basa en el ejemplo de subtítulos de la documentation del Captionator . Agregué un button para recuperar los metadatos y mostrarlos cuando hago clic en el button. Desafortunadamente, sigue mostrando "indefinido" en lugar de los metadatos. ¿Alguna idea de lo que podría estar haciendo incorrectamente? De forma alternativa, ¿alguien sabe dónde puedo echar un vistazo a un ejemplo de trabajo? No puedo encontrar uno en ninguna parte.

Si le interesa echar un vistazo a mi código, lo he incluido a continuación:

 <!DOCTYPE html> <html> <head> <title>HTML5 Video Closed Captioning Example</title> <meta charset="utf-8"> <link rel="stylesheet" type="text/css" media="screen" href="js/Captionator-v0.5-12/css/captions.css"/> </head> <body> <h1>HTML5 Video Closed Captioning Example</h1> <div> <p id="metadataText">Metadata text should appear here</p> <input type='button' onclick='changeText()' value='Click here to display the metadata text'/> </div> <video controls autobuffer id="videoTest" width="1010" height="464"> <source src="http://localhost:8080/Videos/testVideo.webm" type="video/webm" /> <source src="http://localhost:8080/Videos/testVideo.mp4" type="video/mp4" /> <!-- WebVTT Track Metadata Example --> <track label="Metadata Track" kind="metadata" src="http://localhost:8080/Videos/Timed_Text_Tracks/testVideo_metadata.vtt" type="text/webvtt" srclang="en" /> </video> <!-- Include Captionator --> <script type="text/javascript" src="js/Captionator-v0.5-12/js/captionator.js"></script> <!-- Example Usage --> <script type="text/javascript" src="js/Captionator-v0.5-12/js/captionator-example-api.js"></script> <script type="text/javascript"> window.addEventListener("load",function() { captionator.captionify(null,null,{ debugMode: !!window.location.search.match(/debug/i), sizeCuesByTextBoundingBox: !!window.location.search.match(/boundingBox/i), enableHighResolution: !!window.location.search.match(/highres/i), }); var videoObject = document.getElementsByTagName("video")[0]; videoObject.volume = 0; document.body.appendChild(generateMediaControls(videoObject)); },false); function changeText() { document.getElementById('metadataText').innerHTML = testVar; var cueText = document.getElementById("video").tracks[0].activeCues[0].getCueAsSource(); document.getElementById('metadataText').innerHTML = cueText; } </script> </body> </html> 

Mi file WebVTT se ve así:

 WEBVTT 0 00:00.000 --> 00:04.000 Testing 1 2 3 . . . 

La forma de acceder a la input es correcta: no hay problemas allí (aunque habrá un cambio en el Captionator 0.6 desde la propiedad .tracks a la propiedad .textTracks para estar más en línea con la especificación. Si puede soportar el error ocasional) Recomendaría usar 0.6 para un mayor cumplimiento de las normas. He escrito el código a continuación para usar .textTracks . Sustituya las .tracks si desea continuar usando la twig estable.

El problema se relaciona con la carga de las pistas de text. Por el momento, en realidad no le está diciendo a Captionator que cargue la pista . Debido a que esto ocurre de manera asincrónica, y previa request, existe la inevitable demora en la que su contenido no está disponible, deberá escribir su código de una manera que se adapte al time de carga y al posible error de carga.

Tampoco está esperando que se cargue Captionator en sí, ya que un usuario podría hacer clic en el button sin saberlo antes de que esto ocurriera, lo que desencadenaría un desagradable error de JavaScript. Esto no será un problema cuando lo pruebes en tu caja local, pero tan pronto como te instales en Internet estarás viendo todo tipo de condiciones de carrera y otras cosas desagradables. Considere deshabilitar el button hasta que la página y los datos de los subtítulos se hayan cargado.


Intenté hacer que la API de Captionator se acercara lo más posible a la API de JS real que aterrizará en los browseres muy pronto, por lo que en el futuro será de la misma manera que interactuarás con la funcionalidad del browser nativo. Tan pronto como la funcionalidad esté disponible de forma nativa, Captionator se apartará del path, y su código debería (suponiendo que no vuelvan a cambiar la API) simplemente trabajar con la API nativa.

En primer lugar, debe solicitar que Captionator cargue el contenido. Esto se hace configurando el 'modo de visualización' de la pista para SHOWING , o 2 .

 var video = document.getElementByID("myVideo"); video.textTracks[0].mode = 2; // SHOWING 

Alternativamente, puede asignar el estado de una pista a HIDDEN ( 1 ), que aún activa una carga, y los events de cueChange aún se dispararán, pero no dibujará señales en la pantalla. En Captionator, no pinto las pistas de metadatos en la pantalla, pero la API WebKit (defectuosa) en desarrollo lo hará.

 video.textTracks[0].mode = 1; // HIDDEN 

Luego debe escuchar cuando las pistas están cargadas y disponibles:

 video.textTracks[0].onload = function() { /* Your Code Here... */ } 

O cuando algo sale mal:

 video.textTracks[0].onerror = function() { /* Whoah, something went wrong... */ } 

Una vez que se carga el contenido, puede acceder a la matriz TextTrack.cues (bueno, técnicamente una TextTrackCueList ). Antes de que se haya producido la carga, la propiedad TextTrack.cues será null .

 var myCueText = video.textTracks[0].cues[0].text; 

Tenga en count que Captionator analiza el text de cada cue, excepto cuando el tipo de pista es metadata , así que asegúrese de asignar el tipo de pista correcto. Es posible que termine con datos o tags que el Captionator piensa que están siendo 'no válidos'. También puede desactivar esta processCueHTML para las pistas regulares, estableciendo la opción processCueHTML en false .


Con eso en mente, así es como reescribí tu código:

 <div> <p id="metadataText">Metadata text should appear here</p> <input type='button' onclick='changeText()' value='Click here to display the metadata text' id="changetext" disabled /> </div> <video controls autobuffer id="videoTest" width="512" height="288"> <!-- Your video sources etc... --> <!-- The metadata track --> <track label="Metadata Track" kind="metadata" src="metadata.vtt" type="text/webvtt" srclang="en" /> </video> <!-- Include Captionator --> <script type="text/javascript" src="captionator.js"></script> <script type="text/javascript"> document.addEventListener("readystatechange",function(event) { if (document.readyState === "complete") { captionator.captionify(); document.querySelectorAll("#changetext")[0].removeAttribute("disabled"); } },false); function changeText() { // Get the metadataText paragraph var textOutput = document.querySelectorAll("#metadataText")[0]; // Get the metadata text track var metadataTrack = document.querySelectorAll("video")[0].textTracks[0]; if (metadataTrack.readyState === captionator.TextTrack.LOADED) { // The cue is already ready to be displayed! textOutput.innerHTML = metadataTrack.cues[0].text; } else { // We check to see whether we haven't already assigned the mode. if (metadataTrack.mode !== captionator.TextTrack.SHOWING) { textOutput.innerHTML = "Caption loading..."; // The file isn't loaded yet. Load it in! metadataTrack.mode = captionator.TextTrack.SHOWING; // You can use captionator.TextTrack.HIDDEN too. metadataTrack.onload = function() { textOutput.innerHTML = metadataTrack.cues[0].text; } metadataTrack.onerror = function() { textOutput.innerHTML = "Error loading caption!"; } } } } </script> 

Aquí, estamos deshabilitando el button, impidiendo que los usuarios con conexiones lentas (¡o solo alguien con reflections muy rápidos!) Lo toquen antes de que el Captionator o la pista de metadatos estén listos y escuchando un evento de carga, momento en el que volvemos a habilite el button, y puede recuperar el text de reference como de costumbre.

Es posible que deba cargar su file de metadata VTT a través de Ajax y analizar y mostrarlo usted mismo.

Miré el ejemplo del artículo de HTML5 Doctors sobre subtítulos de video . Están usando Playr , así que revisé su código fuente, y definitivamente están solicitando el file VTT de forma asíncrona y parsing el contenido una vez que se carga.

Pude cargar el contenido del file VTT y volcarlo en el elemento especificado con el siguiente código:

 function changeText() { var track = document.getElementById("videoTest").querySelector("track"); var req_track = new XMLHttpRequest(); req_track.open('GET', track.getAttribute("src")); req_track.onreadystatechange = function(){ if(req_track.readyState == 4 && (req_track.status == 200 || req_track.status == 0)){ if(req_track.responseText != ''){ document.getElementById("metadataText").innerHTML = req_track.responseText; } } } req_track.send(null); } 

No estoy familiarizado con Captionator, pero parece que tiene algunas capacidades para analizar files VTT en algún tipo de estructura de datos, incluso si no necesariamente admite el tipo de seguimiento de metadata . ¿Tal vez puedas usar una combinación de este código y el analizador VTT existente del Captionator?