HTML5视频尺寸

132

我正在尝试使用JavaScript获取一个视频的尺寸,然后将其叠加到页面上,但是它返回的是海报图像的尺寸而不是实际视频的尺寸,因为它似乎是在视频加载之前计算的。


你放弃了吗?这里有很好的线索作为答案! - Ruan Mendes
7个回答

172

需要注意的是,Sime Vidas之前提供的解决方案在现代浏览器中实际上不起作用,因为videoWidth和videoHeight属性直到“loadedmetadata”事件触发后才会被设置。

如果你在VIDEO元素呈现后足够长的时间内查询这些属性,它有时可能会起作用,但在大多数情况下,这将返回这两个属性的值为0。

为了确保获取正确的属性值,你需要做类似以下的操作:

var v = document.getElementById("myVideo");
v.addEventListener( "loadedmetadata", function (e) {
    var width = this.videoWidth,
        height = this.videoHeight;
}, false );

注意:我没有考虑到使用attachEvent而不是addEventListener的Internet Explorer 9以下版本,因为该浏览器的9以下版本无论如何都不支持HTML5视频。


我得到了宽度和高度都是100的值,但视频并没有100像素。不确定原因... - Mikel
2
很不幸,在Chrome for Android 49上无法正常工作;只有在视频开始播放后才能获得信息。对此还有什么进一步的见解吗?PS1:我只尝试了使用文件选择器输入元素选定本地文件的URL。PS2:在iOS Safari上确实可以工作。 - Visionscaper
我在 Chromium Bug 追踪器上创建了此问题:https://bugs.chromium.org/p/chromium/issues/detail?id=598218 - Visionscaper
11
这并非百分之百可行。极少数情况下,当“loadedmetadata”触发时,videoWidth和videoHeight将为零。我在Chromium 69上看到过这种情况。监听“loadeddata”更加安全可靠。 - cleong

128

这是否适用于ogg格式?因为我认为视频不会包含这样的元数据。 - Elliot
@Elliot 我在Chrome上测试了这个演示:http://people.opera.com/howcome/2007/video/controls.html,它可以正常工作... - Šime Vidas
似乎链接又坏了。 - Martin Delille
抱歉,链接并没有损坏。 - Martin Delille
2
使用 URL.createObjectURL(file) 播放本地文件时始终为零。 - Exlord

37

可直接使用的函数

这是一个可直接使用的函数,可以异步返回视频的尺寸,而无需改变文档中的任何内容

// ---- Definitions ----- //

/**
 Returns the dimensions of a video asynchrounsly.
 @param {String} url Url of the video to get dimensions from.
 @return {Promise<{width: number, height: number}>} Promise which returns the dimensions of the video in 'width' and 'height' properties.
 */
function getVideoDimensionsOf(url){
    return new Promise(resolve => {
        // create the video element
        const video = document.createElement('video');

        // place a listener on it
        video.addEventListener( "loadedmetadata", function () {
            // retrieve dimensions
            const height = this.videoHeight;
            const width = this.videoWidth;

            // send back result
            resolve({height, width});
        }, false);

        // start download meta-datas
        video.src = url;
    });
}


// ---- Use ---- //
getVideoDimensionsOf("https://www.w3schools.com/html/mov_bbb.mp4")
   .then(console.log);

如果你想查看代码片段使用的视频,请访问此链接:大野兔


用 Promise 异步地传递视频标签数据,非常好的使用方法,正是我正在寻找的,谢谢。 - Ray Andison
优秀的代码,并且具有良好的浏览器支持:自Chrome 32、Opera 19、Firefox 29、Safari 8和Microsoft Edge以来,Promise已默认启用。 - Jeff Clayton
运行此代码片段会得到 Undefined - NineCattoRules

15

正确链接:https://www.w3.org/TR/html5/embedded-content-0.html#event-media-loadedmetadata - Visionscaper
1
@Visionscaper 已修复,谢谢。如果他人的回答没有改变原意,可以随意进行小的编辑。 - Ruan Mendes
踩票者:我希望能得到解释,以便改进! - Ruan Mendes

3
这是在Vue中实现的方法:
<template>
    <div>
        <video src="video.mp4" @loadedmetadata="getVideoDimensions"></video>
    </div>
</template>

<script>
export default {
    methods: {
        getVideoDimensions (e) {
            console.log(e.target.videoHeight)
            console.log(e.target.videoWidth)
        }
    }
}
</script>

1

需要注意的是,在某些情况下,例如HLS流,"onmetadataloaded"也不起作用。
在这种情况下,此解决方案非常有效。

var video = document.getElementById("video")
video.onplaying = function () {
    var width = video.videoWidth
    var height = video.videoHeight
    console.log("video dimens loaded w="+width+" h="+height)
}

-1
在Vuejs中,我在mounted标签中使用以下代码。
var app = new Vue({
    el: '#id_homepage',
    mounted: function () {
        var v = document.getElementById("id_video");
        var width = v.offsetWidth;
        v.height = Math.floor(width*(9/16)); // dynamically setting video height to maintain aspect ratio
    },
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接