从 <track> 读取元数据一个 HTML5 <video>使用字幕 [英] Reading metadata from the <track> of an HTML5 <video> using Captionator

查看:33
本文介绍了从 <track> 读取元数据一个 HTML5 <video>使用字幕的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法从 WebVTT 文件中读取元数据的工作示例,该文件由 中的 元素指定一个 HTML5 页面.需要明确的是,我不是在谈论从视频文件本身中读取元数据(例如,就像使用 MPEG 传输流一样).我要说的是用于为视频添加字幕的 元素. 的属性之一是 kind,它可以指定为以下任意值:

  • 字幕
  • 说明
  • 字幕
  • 导航
  • 章节
  • 元数据

我正在尝试使用 metadata 类型来访问存储在相应 WebVTT 文件中的文本,我打算使用 JavaScript 对其进行操作.我知道这是可能的,因为它是 Silvia Pfeiffer 提到的以及 Captionator 的制作者,这是 JavaScript polyfill我用来实现解释 <track> 标签的功能.但是,我无法让它工作.

我的代码基于 Captionator 文档的字幕示例.我添加了一个按钮来检索元数据并在单击该按钮时显示它.不幸的是,它一直显示未定义"而不是元数据.任何想法我可能做错了什么?或者,有谁知道我可以查看的工作示例在哪里?我在任何地方都找不到.

如果你想看看我的代码,我已经把它包含在下面:

<头><title>HTML5 视频隐藏字幕示例</title><meta charset="utf-8"><link rel="stylesheet" type="text/css" media="screen" href="js/Captionator-v0.5-12/css/captions.css"/><身体><h1>HTML5 视频隐藏式字幕示例</h1><div><p id="metadataText">元数据文本应该出现在这里</p><input type='button' onclick='changeText()' value='点击这里显示元数据文本'/>

<视频控制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 label="Metadata Track" kind="metadata" src="http://localhost:8080/Videos/Timed_Text_Tracks/testVideo_metadata.vtt" type="text/webvtt" srclang="en"/></视频><!-- 包括字幕--><script type="text/javascript" src="js/Captionator-v0.5-12/js/captionator.js"></script><!-- 示例用法--><script type="text/javascript" src="js/Captionator-v0.5-12/js/captionator-example-api.js"></script><script type="text/javascript">window.addEventListener("加载",function() {captionator.captionify(空,空,{调试模式:!!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));},错误的);函数更改文本(){document.getElementById('metadataText').innerHTML = testVar;var cueText = document.getElementById("video").tracks[0].activeCues[0].getCueAsSource();document.getElementById('metadataText').innerHTML = cueText;}

我的 WebVTT 文件如下所示:

WEBVTT000:00.000 -->00:04.000测试 1 2 3...

解决方案

您访问提示的方式是正确的 - 没有问题(尽管 Captionator 0.6 中 .tracks 属性更改为 .textTracks 属性以更符合规范.如果您能忍受偶尔出现的错误,我建议您使用 0.6 以获得更高的标准合规性 - 我已将以下代码编写为如果您想继续使用稳定分支,请使用 .textTracks - 替换 .tracks.)

该问题与文本轨道本身的加载有关.目前,您实际上并没有告诉 Captionator 加载曲目.由于这是异步发生的,并且根据请求,在其内容不可用时不可避免地会出现延迟,因此您需要以适应加载时间和潜在加载错误的方式编写代码.

您也不会等待 Captionator 本身加载 - 用户可能会在发生这种情况之前不知不觉地点击按钮 - 触发令人讨厌的 JavaScript 错误.在您的本地机器上进行测试时,这不会是一个问题,但是一旦您部署到 Internet,您就会看到各种竞争条件和其他问题.考虑禁用按钮,直到页面和字幕数据都加载完毕.

<小时>

我已尝试使 Captionator API 尽可能接近将很快在浏览器中登陆的实际 JS API - 所以将来这将与您与本机浏览器功能交互的方式相同.一旦该功能在本机可用,Captionator 就会让开,您的代码应该(假设他们不再更改 API!)只需使用本机 API.

首先,您需要实际请求 Captionator 加载内容.这是我将曲目的显示模式"设置为 SHOWING2 来完成的.

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

或者,您可以将轨道的状态分配给 HIDDEN (1) - 这仍然会触发加载,并且cueChange 事件仍然会触发 - 但不会绘制提示到屏幕.在 Captionator 中,我根本不会将元数据轨道绘制到屏幕上,但开发中的(有缺陷的)WebKit API 会.

video.textTracks[0].mode = 1;//隐藏

然后您需要监听提示加载和可用的时间:

video.textTracks[0].onload = function() {/* 你的代码在这里... */}

或者当出现问题时:

video.textTracks[0].onerror = function() {/* 哇,出了点问题... */}

加载内容后,您可以访问 TextTrack.cues 数组(好吧,技术上是 TextTrackCueList.)在加载发生之前,TextTrack.cues 属性将为 null.

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

请注意 Captionator 会解析每个提示的 提示文本除非曲目类型为 metadata - 所以请确保您分配正确的轨道种类.您最终可能会丢弃 Captionator 认为无效"的数据或标签.您也可以为常规提示关闭此检查,方法是将 processCueHTML 选项设置为 false.

<小时>

考虑到这一点,以下是我重写您的代码的方法:

<p id="metadataText">元数据文本应该出现在这里</p><input type='button' onclick='changeText()' value='点击这里显示元数据文本' id="changetext" disabled/>

<视频控制autobuffer id="videoTest" width="512" height="288"><!-- 您的视频来源等...--><!-- 元数据轨道--><track label="Metadata Track" kind="metadata" src="metadata.vtt" type="text/webvtt" srclang="en"/></视频><!-- 包括字幕--><script type="text/javascript" src="captionator.js"></script><script type="text/javascript">document.addEventListener("readystatechange",function(event) {如果(document.readyState ===完成"){captionator.captionify();document.querySelectorAll("#changetext")[0].removeAttribute("disabled");}},错误的);函数更改文本(){//获取metadataText段落var textOutput = document.querySelectorAll("#metadataText")[0];//获取元数据文本轨道var metadataTrack = document.querySelectorAll("video")[0].textTracks[0];if (metadataTrack.readyState === captionator.TextTrack.LOADED) {//提示已经准备好显示了!textOutput.innerHTML = metadataTrack.cues[0].text;} 别的 {//我们检查是否还没有分配模式.if (metadataTrack.mode !== captionator.TextTrack.SHOWING) {textOutput.innerHTML = "字幕加载...";//文件尚未加载.装进去!metadataTrack.mode = captionator.TextTrack.SHOWING;//您也可以使用 captionator.TextTrack.HIDDEN.metadataTrack.onload = function() {textOutput.innerHTML = metadataTrack.cues[0].text;}metadataTrack.onerror = function() {textOutput.innerHTML = "加载标题时出错!";}}}}

在这里,我们将禁用该按钮,以防止连接速度较慢的用户(或只是反应速度非常快的人!)在 Captionator 或元数据轨道准备就绪之前点击它,并在此时监听加载事件我们重新启用按钮,并可以正常检索提示文本.

I am having trouble getting a working example that reads metadata from a WebVTT file, which was specified by the <track> element of a <video> in an HTML5 page. To be clear, I am not talking about reading the metadata out of the video file itself (as you would with an MPEG Transport Stream, for instance). What I'm talking about is the <track> element that is used for captioning videos. One of the attributes of a <track> is kind, which can be specified as any of the following values:

  • Subtitles
  • Descriptions
  • Captions
  • Navigation
  • Chapters
  • Metadata

I am trying to use the metadata type to access text stored in the corresponding WebVTT file, which I intend to manipulate using JavaScript. I know this is possible, as it is mentioned by Silvia Pfeiffer as well as by the maker of Captionator, which is the JavaScript polyfill that I am using to implement the functionality of interpreting the <track> tags. However, I just can't get it to work.

My code is based on the Captionator documentation's captions example. I added a button to retrieve the metadata and display it when I click the button. Unfortunately it keeps displaying "undefined" instead of the metadata. Any ideas what I might be doing incorrectly? Alternatively, does anyone know where a working example is that I could take a look at? I can't find one anywhere.

If you care to take a look at my code, I've included it below:

<!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>

My WebVTT file looks like this:

WEBVTT

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

解决方案

The way you're accessing the cue is correct - no problems there (although there will be a change in Captionator 0.6 from the .tracks property to the .textTracks property to be more in line with the specification. If you can bear the occasional bug I would recommend using 0.6 for its greater standards compliance - I've written the below code to use .textTracks - substitute for .tracks if you'd like to continue using the stable branch.)

The issue relates to the loading of the text tracks themselves. At the moment, you're not actually telling Captionator to load the track. Because this happens asynchronously, and on request, there is that inevitable delay where their content isn't available, you'll need to write your code in a way which accommodates for loading time and the potential load error.

You're also not waiting for Captionator itself to load - potentially a user could unknowingly click the button before this had occurred - triggering a nasty JavaScript error. This won't be such a problem when testing on your local box, but as soon as you deploy to the internet you'll be seeing all sorts of race conditions and other nasties. Consider disabling the button until both the page and the caption data have loaded.


I've tried to make the Captionator API as close as possible to the actual JS API which will be landing in browsers very soon - so in future this will be the same way you'll interact with the native browser functionality. As soon as the functionality is available natively, Captionator will bow out of the way, and your code should (assuming they don't change the API again!) just work with the native API.

First of all, you need to actually request that Captionator load the content. This is done my setting the 'display mode' of the track to SHOWING, or 2.

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

Alternately, you can assign the status of a track to HIDDEN (1) - which still triggers a load, and cueChange events will still fire - but won't paint cues to screen. In Captionator, I don't paint metadata tracks to screen at all, but the (buggy) WebKit API in development will.

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

Then you need to listen for when the cues are loaded and available:

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

Or when something goes wrong:

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

Once the content is loaded, you can access the TextTrack.cues array (well, technically a TextTrackCueList.) Before the load has occurred, the TextTrack.cues property will be null.

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

Be aware that Captionator parses the cue text of every cue, except when the track kind is metadata - so ensure you assign the correct track kind. You might end up with data or tags Captionator thinks are 'invalid' being thrown out. You can turn this check off for regular cues as well, with by setting the processCueHTML option to false.


With that in mind, here's how I'd rewrite your code:

<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>

Here, we're disabling the button, preventing users on slow connections (or just somebody with very quick reflexes!) from hitting it before either Captionator or the metadata track are ready, and listening to a load event - at which point we re-enable the button, and can retrieve the cue text as normal.

这篇关于从 &lt;track&gt; 读取元数据一个 HTML5 &lt;video&gt;使用字幕的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆