获取真正的HTML5视频宽度和高度

27

我有一个视频元素:

var video = window.content.document.createElement("video");
video.width = width;
video.height = height; 
video.style.backgroundColor = "black";
window.content.document.body.appendChild(video);

我正在通过Firefox的getUserMedia()检索其源代码:

window.navigator.getMedia = ( window.navigator.getUserMedia || window.navigator.webkitGetUserMedia || window.navigator.mozGetUserMedia || window.navigator.msGetUserMedia);

window.navigator.getMedia( //constraints, sucessCallback, errorCallback
    {video: true, audio: false},
    function(stream) {
        if (window.navigator.mozGetUserMedia) 
            video.mozSrcObject = stream;
        else 
        {
            var vendorURL = window.URL || window.webkitURL;
            video.src = vendorURL.createObjectURL(stream);
        }
        video.play();
    },
    function(err) {
        console.log("Error: " + err);
    }
);

问题是我需要知道视频的“活动区域”,但返回值为0:

video.onloadedmetadata = function(){

    console.log(this.width + "x" +this.height); 
    console.log(this.videoWidth + "x" +this.videoHeight);
}

那我如何检索真实的数值呢?:enter image description here


1
当我在使用 FF 运行您的代码时,this.width 和 this.height 返回视频元素的实际尺寸。只是为了测试,我将 video.width 和 video.height 设置为 400,第一条控制台输出返回了 400x400。 - Sam
4个回答

29
这里有两个问题:
  1. video.videoWidthvideo.videoHeight 属性在 loadedmetadata 事件触发时并没有立即设置。这是一个FireFox中的错误,现在已经被修复(感谢@Martin Ekblom指出了这个错误)。
  2. 视频本身并没有占据整个视频元素的区域,而是缩放以适应元素内部。
我不认为有一种直接的方法来获取活动区域的尺寸,但在自己苦苦挣扎后,我想出了一种解决方案,可以从我们已知的值中计算出它的尺寸:
function videoDimensions(video) {
  // Ratio of the video's intrisic dimensions
  var videoRatio = video.videoWidth / video.videoHeight;
  // The width and height of the video element
  var width = video.offsetWidth, height = video.offsetHeight;
  // The ratio of the element's width to its height
  var elementRatio = width/height;
  // If the video element is short and wide
  if(elementRatio > videoRatio) width = height * videoRatio;
  // It must be tall and thin, or exactly equal to the original ratio
  else height = width / videoRatio;
  return {
    width: width,
    height: height
  };
}

基本上,我们取视频元素的宽高比、视频的宽高比和视频元素的尺寸,并使用它们来确定视频所占据的区域。这假定视频的适应方法没有通过CSS进行修改(不确定目前是否可能,但规范允许这样做)。有关更多详细信息和其他一些内容,请参见我写的博客文章("查找HTML5视频活动区域的真实尺寸"),该博客受到此问题及其不完整答案的启发。有趣的是,虽然规范特别提到了围绕视频的可能边缘(黑边和白边),但我没有找到任何其他提及它的地方,除了你的问题。

我认为这个问题在FireFox开发者版51.0a2中不会被修复。在loadedmetadata事件触发后,视频的宽度/高度被报告为640 x 480,而在我的情况下是错误的。 - smatthews1999
2
@Natewami getUserMedia。我能够使用video元素的clientWidth和clientHeight。 - smatthews1999
@Nateowami,你的网站已经挂了。对于其他人来说,你可以在这里阅读他的博客文章:https://nathanielpaulus.wordpress.com/2016/09/04/finding-the-true-dimensions-of-an-html5-videos-active-area/ - Yay295
感谢这个视频。我之前不知道那些数值。 - Baptiste Gavalda
当我在浏览器的监视表达式中首次打开video.videoHeight或video.videoWidth时,我获得了0或undefined。 我建议添加以下语句:setInterval(function(){ console.log( videoDimensions(video) ); }, 3000);令我惊讶的是,最终我得到了视频流的实际尺寸。 - wgwz
显示剩余4条评论

11
您应该为视频添加一个loadeddata事件监听器,然后尝试读取大小,这是在已解码足够关于流的信息并且可以准确确定尺寸时。但有时获取尺寸需要一些时间,在某些情况下,您可能需要尝试多次(带延迟)直到它起作用。
这可能就是为什么它对Sam有效而对您无效的原因。
以下是我在我的gumhelper库中检查视频大小的方法,并进行多次尝试(如果需要)。请注意,如果不起作用,我们会"放弃"并默认为640 x 480。 https://github.com/sole/gumhelper/blob/master/gumhelper.js#L38

我之前也遇到了同样的问题,后来将loadedmetadata改为loadeddata就解决了。谢谢! - dariru

2

“loadeddata”事件应该仅触发一次。最好使用“timeupdate”事件来重复检查视频宽度和高度是否已设置,特别是在使用getUserMedia时,您不需要真正暂停视频,而是直接进入播放。


1

看起来这个 bug 在 FireFox 37 中已经修复(当前版本是 48)。 - Nateowami

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