问题描述
我无法获得一个从WebVTT文件中读取元数据的工作示例,该文件由< code>< track>
HTML5页面中的< video> 。清楚的是,我不是在讨论从视频文件本身读取元数据(例如,像使用MPEG传输流一样)。我在说的是用于字幕视频的< track>
元素。 < track>
的属性之一是 kind
,它可以被指定为以下任何值:
- 字幕
- 描述
- 字幕 >
- 导航
- 章节
- 元数据
我试图使用元数据类型来访问存储在相应的WebVTT文件中的文本,我打算使用JavaScript进行操作。我知道这是可能的,因为它是所提及的以及Captionator制造商的,这是JavaScript的polyfill我用来实现解释
< track>
标签的功能。但是,我无法让它工作。
我的代码基于文档的标题示例。我添加了一个按钮来检索元数据并在单击按钮时显示它。不幸的是,它不断显示未定义而不是元数据。任何想法我可能做错了吗?或者,有没有人知道我可以看一看哪个工作示例?我在任何地方都找不到。
如果你想看看我的代码,我已将它包含在下面:
<!DOCTYPE html>
< html>
< head>
< title> HTML5视频隐藏式字幕示例< / title>
< meta charset =utf-8>
< link rel =stylesheettype =text / cssmedia =screenhref =js / Captionator-v0.5-12 / css / captions.css/>
< / head>
< body>
< h1> HTML5视频隐藏式字幕示例< / h1>
< div>
< p id =metadataText>元数据文字应显示在这里< / p>
< input type ='button'onclick ='changeText()'value ='点击此处显示元数据文本'/>
< / div>
< video controls autobuffer id =videoTestwidth =1010height =464>
< source src =http:// localhost:8080 / Videos / testVideo.webmtype =video / webm/>
< source src =http:// localhost:8080 / Videos / testVideo.mp4type =video / mp4/>
< track label =Metadata Trackkind =metadatasrc =http:// localhost:8080 / Videos / Timed_Text_Tracks / testVideo_metadata.vtttype =text / webvttsrclang =en/ >
< / video>
< script type =text / javascriptsrc =js / Captionator-v0.5-12 / js / captionator.js>< / script>
<! - 示例用法 - >
< script type =text / javascriptsrc =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
测试1 2 3。 。 。
解决方案您访问提示的方式是正确的 - 没问题(虽然Captionator 0.6会从
.tracks
属性改为.textTracks
属性如果你能承受偶尔的错误,我会建议使用0.6来达到更高的标准 - 我已经写了下面的代码来使用.textTracks
- 如果你想继续使用stable分支,用.tracks
代替。)
这个问题涉及到文本的加载跟踪它们自己。目前,您实际上并未告诉Captionator加载音轨。因为这是异步发生的,并且根据请求,在其内容不可用时存在不可避免的延迟,您需要编写代码以适应加载时间和潜在的加载错误。
您还没有等待Captionator本身加载 - 潜在的用户可能会在不知不觉中点击按钮,从而触发令人讨厌的JavaScript错误。在您的本地盒子上进行测试时,这不会成为这样的问题,但只要您部署到互联网上,您就会看到各种竞争条件和其他问题。考虑禁用该按钮,直到页面和标题数据都已加载。
我试图制作Captionator API尽可能接近真正的JS API,它将很快登陆浏览器 - 所以在将来,这将与您将与本地浏览器功能进行交互的方式相同。只要本地功能可用,Captionator就会自动退出,并且您的代码应该(假设它们不会再更改API)仅适用于本机API。
首先,您需要实际请求Captionator加载内容。这是通过将轨道的显示模式设置为
$完成的。 bSHOWING
或2
。
$ bvar video = document.getElementByID(myVideo);
video.textTracks [0] .mode = 2; // SHOWING
或者,您可以将曲目的状态分配为
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会解析每个提示的 cue text ,除非赛道种类
元数据
- 因此请确保指定正确的赛道种类。你最终可能会得到Captionator认为被抛弃的数据或标签。您也可以通过将processCueHTML
选项设置为false
来关闭常规线索。
考虑到这一点,我将如何重写您的代码:
< DIV>
< p id =metadataText>元数据文本应显示在此处< / p>
< input type ='button'onclick ='changeText()'value ='点击此处显示元数据文本'id =changetextdisabled />
< / div>
< video controls autobuffer id =videoTestwidth =512height =288>
<! - 您的视频来源等... - >
< track label =Metadata Trackkind =metadatasrc =metadata.vtttype =text / webvttsrclang =en/>
< / video>
<! - 包括Captionator - >
< script type =text / javascriptsrc =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(){
//获取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;
} else {
//我们检查我们是否还没有分配模式。
if(metadataTrack.mode!== captionator.TextTrack.SHOWING){
textOutput.innerHTML =Caption loading ...;
//文件尚未加载。加载它!
metadataTrack.mode = captionator.TextTrack.SHOWING; //你也可以使用captionator.TextTrack.HIDDEN。
metadataTrack.onload = function(){
textOutput.innerHTML = metadataTrack.cues [0] .text;
}
metadataTrack.onerror = function(){
textOutput.innerHTML =加载标题时出错!;
}
}
}
}
< / script>
在这里,我们正在关闭按钮,阻止用户进行慢速连接(或者只是很快)在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>
iskind
, 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
, or2
.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 aTextTrackCueList
.) Before the load has occurred, theTextTrack.cues
property will benull
.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 theprocessCueHTML
option tofalse
.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.
这篇关于从< track>中读取元数据HTML5< video>使用Captionator的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!