使用 Captionator 从 HTML5 <video> 的 <track> 读取元数据
Posted
技术标签:
【中文标题】使用 Captionator 从 HTML5 <video> 的 <track> 读取元数据【英文标题】:Reading metadata from the <track> of an HTML5 <video> using Captionator 【发布时间】:2012-03-11 07:58:54 【问题描述】:我无法获得一个从 WebVTT 文件中读取元数据的工作示例,该文件由 html5 页面中 <video>
的 <track>
元素指定。需要明确的是,我不是在谈论从视频文件本身中读取元数据(例如,您会使用 MPEG 传输流)。我所说的是用于为视频添加字幕的<track>
元素。 <track>
的属性之一是kind
,可以指定为以下任意值:
我正在尝试使用 元数据 类型来访问存储在相应 WebVTT 文件中的文本,我打算使用 javascript 对其进行操作。我知道这是可能的,因为它是 mentioned by Silvia Pfeiffer 和 by the maker of Captionator,这是我用来实现解释 <track>
标签功能的 JavaScript 填充程序。但是,我就是无法让它工作。
我的代码基于Captionator 文档的标题示例。我添加了一个按钮来检索元数据并在单击该按钮时显示它。不幸的是,它一直显示“未定义”而不是元数据。有什么想法我可能做错了吗?或者,有谁知道我可以查看的工作示例在哪里?我在任何地方都找不到。
如果您想看看我的代码,我已将其包含在下面:
<!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" >
<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>
我的 WebVTT 文件如下所示:
WEBVTT
0
00:00.000 --> 00:04.000
Testing 1 2 3 . . .
【问题讨论】:
嘿 - 我是 Captionator 的开发人员,乍一看您所做的似乎是正确的。我正在调查您是否发现了错误 - 我将根据我的发现发布答案。 :) 【参考方案1】:您访问提示的方式是正确的 - 没有问题(尽管 Captionator 0.6 中的 .tracks
属性将更改为 .textTracks
属性以更符合规范。如果您可以承受偶尔出现的错误,我建议使用 0.6 以实现更高的标准合规性 - 我编写了以下代码以使用 .textTracks
- 如果您想继续使用稳定分支,请替换 .tracks
。)
问题与文本轨道本身的加载有关。目前,您实际上并没有告诉 Captionator 加载曲目。因为这是异步发生的,并且在请求时,在其内容不可用时不可避免地会出现延迟,因此您需要以适应加载时间和潜在加载错误的方式编写代码。
您也不必等待 Captionator 本身加载 - 用户可能会在此之前不知情地点击按钮 - 触发令人讨厌的 JavaScript 错误。在您的本地机器上进行测试时,这不会是一个问题,但是一旦您部署到互联网,您就会看到各种竞争条件和其他讨厌的东西。考虑禁用该按钮,直到页面和标题数据都加载完毕。
我已尝试使 Captionator API 尽可能接近实际的 JS API,后者很快就会登陆浏览器 - 所以将来这将与您与本机浏览器功能交互的方式相同。只要该功能在本机可用,Captionator 就会退出,您的代码应该(假设他们不再更改 API!)只需使用本机 API。
首先,您需要实际请求 Captionator 加载内容。这是我将曲目的“显示模式”设置为SHOWING
或2
。
var video = document.getElementByID("myVideo");
video.textTracks[0].mode = 2; // SHOWING
或者,您可以将轨道的状态分配给HIDDEN
(1
) - 这仍会触发加载,并且 cueChange 事件仍将触发 - 但不会将提示绘制到屏幕上。在 Captionator 中,我根本不会将元数据轨道绘制到屏幕上,但开发中的(有缺陷的)WebKit API 会。
video.textTracks[0].mode = 1; // HIDDEN
然后你需要监听 cue 何时加载并可用:
video.textTracks[0].onload = function() /* Your Code Here... */
或者当出现问题时:
video.textTracks[0].onerror = function() /* Whoah, something went wrong... */
加载内容后,您可以访问TextTrack.cues
数组(嗯,技术上是TextTrackCueList
。)在加载发生之前,TextTrack.cues
属性将为null
。
var myCueText = video.textTracks[0].cues[0].text;
请注意,Captionator 会解析每个提示的提示文本,除非轨道类型为 metadata
- 因此请确保分配正确的轨道类型。您最终可能会丢弃 Captionator 认为“无效”的数据或标签。您也可以通过将processCueHTML
选项设置为false
来关闭此检查以获取常规提示。
考虑到这一点,下面是我重写代码的方式:
<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" >
<!-- 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>
在这里,我们禁用了该按钮,以防止连接速度较慢的用户(或者只是反应速度非常快的人!)在 Captionator 或元数据轨道准备好之前点击它,并监听加载事件 - 此时我们重新启用按钮,并且可以正常检索提示文本。
【讨论】:
非常感谢克里斯托弗的详细回复。这是一个很大的帮助!【参考方案2】:您可能需要通过 Ajax 加载元数据 VTT 文件并自行解析和显示。
我从HTML5 Doctors' article on video subtitling 中查看了example。他们使用的是Playr,所以我查看了它的源代码,他们肯定是在异步请求 VTT 文件并在加载后解析内容。
我能够使用以下代码加载 VTT 文件的内容并将其转储到指定的元素中:
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);
我对 Captionator 不熟悉,但它似乎具有将 VTT 文件解析为某种数据结构的功能,即使它不一定支持 metadata
轨道类型。也许您可以将此代码与 Captionator 现有的 VTT 解析器结合使用?
【讨论】:
感谢您的帮助,您的代码对我有用。我觉得这有点违背了使用 WebVTT 和 polyfill 的目的,但我认为目前确实没有一个好的解决方案,因为似乎还没有人实现对metadata
<track>
的支持。
好像是这样。如果您想出一些好的东西,您可以随时将其贡献给 Captionator。
@Steph 我可以向您保证 Captionator 确实支持 metadata
轨道类型。 :)以上是关于使用 Captionator 从 HTML5 <video> 的 <track> 读取元数据的主要内容,如果未能解决你的问题,请参考以下文章