从文件中单独检索 HTML5 视频时长

IT技术 javascript html video html5-video
2021-01-13 18:46:15

我正在构建一个带有自定义界面的 HTML5 视频播放器,但在显示视频时长信息时遇到了一些问题。

我的 HTML 很简单:

<video id="video" poster="image.jpg" controls>     
    <source src="video_path.mp4" type="video/mp4" />
    <source src="video_path.ogv" type="video/ogg" /> 
</video>
<ul class="controls"> 
<li class="time"><p><span id="timer">0</span> of <span id="duration">0</span></p></li>  
</ul>

我用来获取和插入持续时间的 javascript 是

var duration = $('#duration').get(0);
var vid_duration = Math.round(video.duration);
duration.firstChild.nodeValue = vid_duration;

问题是什么都没有发生。我知道视频文件有持续时间数据,因为如果我只使用默认控件,它显示正常。

但真正奇怪的是,如果我像这样在代码中放入 alert(duration)

alert(duration);
var vid_duration = Math.round(video.duration);
duration.firstChild.nodeValue = vid_duration;

然后它工作正常(减去弹出的烦人警报)。任何想法这里发生了什么或我如何解决它?

更新:好的,虽然我还没有完全解决这个问题,但我确实想出了一个解决我最关心的问题......用户体验的解决方法。

首先,视频直到观众点击播放按钮后才开始加载,所以我假设无法提取持续时间信息(我不知道如何解决这个特定问题......尽管我假设它只涉及将视频元数据与视频分开加载,但我什至不知道这是否可能)。

所以为了避开没有持续时间数据的事实,我决定完全隐藏持续时间信息(实际上是整个控件),直到你点击播放。

也就是说,如果有人知道如何从视频文件中单独加载视频元数据,请分享。我认为应该彻底解决这个问题。

6个回答

去做:

var myVideoPlayer = document.getElementById('video_player');
myVideoPlayer.addEventListener('loadedmetadata', function() {
    console.log(myVideoPlayer.duration);
});

当浏览器从视频接收到所有元数据时触发。

[编辑] 从那时起,更好的方法是收听 'durationchange' 而不是 'loadedmetadata',后者可能不可靠,例如:

myVideoPlayer.addEventListener('durationchange', function() {
    console.log('Duration change', myVideoPlayer.duration);
});
而不是像在接受的答案中那样连续轮询,一旦视频知道它有可用的元数据,这个实际上就会被调用。确实干净多了。
2021-03-19 18:46:15
这很好用!我的页面上有一些视频,我很想收集所有的持续时间。有没有办法动态执行此操作(无需复制每个视频的代码?)我正在使用 jQuery。
2021-03-20 18:46:15
什么是“myVideoPlayer”: var myVideoPlayer = $('#myvideo').get(0); ?
2021-03-31 18:46:15
它在 chrome 版本 49.0.2623.87 m 中对我不起作用。当它被解雇时,持续时间仍然是无穷大......
2021-04-01 18:46:15
我证实了我的假设......这也是 videoPlayer 评估的内容,这段代码确实有效!!谢谢!
2021-04-03 18:46:15

问题出在 WebKit 浏览器中;视频元数据在视频之后加载,因此在 JS 运行时不可用。需要查询readyState属性;这有一系列从 0 到 4 的值,让您知道视频处于什么状态;加载元数据后,您将获得值 1。

因此,您需要执行以下操作:

window.setInterval(function(t){
  if (video.readyState > 0) {
    var duration = $('#duration').get(0);
    var vid_duration = Math.round(video.duration);
    duration.firstChild.nodeValue = vid_duration;
    clearInterval(t);
  }
},500);

我还没有测试过那个代码,但它(或类似的东西)应该可以工作。

developer.mozilla.org上有关于媒体元素属性的更多信息

请参阅下面的@Mikushi 答案以获得更清洁的解决方案
2021-03-19 18:46:15
我的 readyState 是 4,但我仍然没有得到持续时间。你能检查一下我的问题吗https://stackoverflow.com/questions/52167815/html5-video-duration-infinity-while-readystate-4
2021-03-31 18:46:15

HTML5 规范只允许预加载元数据:

<video id="video" poster="image.jpg" controls preload="metadata">     
    <source src="video_path.mp4" type="video/mp4" />
    <source src="video_path.ogv" type="video/ogg" /> 
</video>

http://www.w3.org/TR/html-markup/video.html#video.attrs.preload

这是对您的代码的修改

var duration = document.getElementById("duration");
var vid_duration = Math.round(document.getElementById("video").duration);
//alert(vid_duration);
duration.innerHTML = vid_duration;
//duration.firstChild.nodeValue = vid_duration;

希望这可以帮助。

看起来你在使用IE,你为什么不使用document.getElementById方法来检索视频对象?

嘿谢谢你的回应。不幸的是它不起作用......我仍然遇到同样的问题,没有调用警报声明......视频持续时间没有被拉入(它只是显示为0)而且我真的没有不使用 getElementById 的一个原因...我只是喜欢 jQuery 选择器,所以我正在使用它们。
2021-03-15 18:46:15
好吧,你在 1 个视频标签中有 2 个视频源,你能把每个源放在 1 个视频标签下,看看它是否有效吗?
2021-03-19 18:46:15

既不听“loadedmetadata”或“durationchange”,video.duration 也不可靠。
尝试加载“ https://media.w3.org/2018/10/w3c-particles.webm

有一个聪明而有效的方法。

//first, seek to a big number time
video.currentTime = 7*24*60*1000;
//then listen 'seeked' event. when this event occur, that means video duration can access normally
video.onseeked = ()=>{
  alert("the duration is: "+video.duration);
  video.onseeked = undefined;
};
这适用于无论您等待多长时间,持续时间都不会从无穷大更新为整数的视频。通常发生在 webm 文件中。谢谢
2021-04-06 18:46:15