Firefox 和 Chrome 中的 getUserMedia() 视频大小不同

Posted

技术标签:

【中文标题】Firefox 和 Chrome 中的 getUserMedia() 视频大小不同【英文标题】:getUserMedia() video size in Firefox & Chrome differs 【发布时间】:2014-12-12 11:47:56 【问题描述】:

我正在使用getUserMedia(),并且在实施约束时(见下文),它们仅适用于 Chrome 而不是 Mozilla。 Mozilla 中的大小总是显得拉长,最终比 chome 中的大。

var vid_constraints = 
    mandatory: 
        maxHeight: 180,
        maxWidth: 320
    

var constraints =  audio: false, video: vid_constraints ;
navigator.getUserMedia(constraints, successCallback, errorCallback);

读了一些之后,MozGetUserMedia() 似乎不支持分辨率限制。有没有办法显示视频以确保它在 Firefox 和 Chrome 中具有相同的大小/分辨率?

谢谢

编辑 我已修改脚本以拍摄快照。我在 Moz 和 Chrome 中保存了快照 - 结果如下:

(左 = Chrome,右 = Mozilla

认为这可以澄清问题。它看起来像宽高比。

编辑(拍摄 2 次)

是的 - chrome one 的纵横比是 16:9,而 Moz 的纵横比是 4:3。我该如何修改?

【问题讨论】:

Firefox 的哪个版本? @aldanux Firefox 33.0 on Mac OS X 10.9.5 你试过设置视频元素的高宽吗 是的。它只是改变了视频元素的总面积。它自己的视频只是简单地缩放以适应内部。 (不改变比例) 看看那个问题中的this answer:***.com/questions/17502205/webrtc-resolution-limit 似乎是firefox缺乏功能 【参考方案1】:

4 月 15 日编辑

正如@jib 在他的awesome answer 中所指出的,

Firefox [38+] 确实支持约束的子集 getUserMedia(),但不是 Chrome 和 Opera 的过时语法 使用。强制/可选语法在一年前被弃用,并且 前一年的 minWidth 和 minHeight。

所以规范批准的新语法是:

var constraints = 
    audio: false,
    video: 
        width:  min: 1024, ideal: 1280, max: 1920 ,
        height:  min: 576, ideal: 720, max: 1080 ,
    
;

但是,这种语法会在 Chrome 中引发错误。如 cmets 中所述,已制作了 PR 到 adapter.js,包括用于旧 FF 和 chrome 的 polyfill。

这是我的尝试,仅适用于 chrome(但新版本的 FF 似乎接受了神奇而隐藏的 require:['width', 'height']

	var video_constraints = 
		width:  min: 320, max: 480 ,
		height:  min: 240, max: 360 ,
		require: ["width", "height"] // needed pre-Firefox 38 (non-spec)
		;
		

	function getMedia()
     
        if(navigator.webkitGetUserMedia)
				var wkConstraints=mandatory:  ;
				var c = video_constraints;
				for(var i in c)
					switch(i)
					 case 'width': for(j in c[i])
						  switch(j)
							 case 'max': wkConstraints.mandatory.maxWidth = c[i][j]; break;
							 case 'min': wkConstraints.mandatory.minWidth = c[i][j]; break;
							 case 'exact': wkConstraints.mandatory.minWidth = wkConstraints.mandatory.maxWidth = c[i][j]; break;
							 
						; break;

					 case 'height': for(var j in c[i])
						  switch(j)
							 case 'max': wkConstraints.mandatory.maxHeight = c[i][j]; break;
							 case 'min': wkConstraints.mandatory.minHeight = c[i][j]; break;
							 case 'exact': wkConstraints.mandatory.minHeight = wkConstraints.mandatory.maxHeight = c[i][j]; break;
							 
						; break;
					 default: break;
					
				
				video_constraints = wkConstraints;
				

		navigator.getUserMedia = ( 	navigator.getUserMedia ||
							   	navigator.webkitGetUserMedia ||
								navigator.mozGetUserMedia);

        if(!navigator.getUserMedia)
			alert("your browser doesn't support getUserMedia")
			

		
		navigator.getUserMedia(
                
				video: video_constraints,
				audio: false,
				,
			
				function(stream) 
					if (navigator.mozGetUserMedia) 
						video.mozSrcObject = stream;
						 
					else 
						var URL = window.URL || window.webkitURL;
						video.src = URL.createObjectURL(stream);
						
					video.play();
					,

				function(err) 
					console.log(err);
					
				);
		

	  var video= document.querySelector('video');
	  video.addEventListener('playing', loopStart, false);			   
	  function loopStart()
		  this.removeEventListener('playing', loopStart);
		  if(this.videoHeight === 0)
			window.setTimeout(function() 
			  this.pause();
			  this.play();
			  loopStart();
			, 100);
			
			else 
			  this.setAttribute('width', this.videoWidth);
			  this.setAttribute('height', this.videoHeight);
			  
		 
	  getMedia();
<video/>

第一个答案

所以在你回答你自己的问题之前,我开始给你写这篇文章。

如 cmets 中所述,我正在绘制视频的每一帧以适应调整大小的画布。

var video, canvas, streaming = false,
  constrainedWidth = 320,
  constrainedHeight = 180;

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

  //**Deprecated Now, see the update**
  var video_constraints = 
    "mandatory": 
      "minWidth": constrainedWidth,
      "minHeight": constrainedHeight,
      "minFrameRate": "30"
    ,
    "optional": []
  

  navigator.getMedia(
      video: video_constraints,
      audio: false
    ,
    function(stream) 
      if (navigator.mozGetUserMedia) 
        video.mozSrcObject = stream;
       else 
        var vendorURL = window.URL || window.webkitURL;
        video.src = vendorURL.createObjectURL(stream);
      
      video.play();
    ,
    function(err) 
      console.log("An error occured! " + err);
      streamCam();
    
  );




function FFResize() 
  canvas.width = constrainedWidth;
  canvas.height = constrainedHeight;
  canvas.getContext('2d').drawImage(video, 0, 0, constrainedWidth, constrainedHeight);
  setTimeout(function() 
    requestAnimationFrame(FFResize)
  , 10);



window.onload = function() 
  video = document.querySelector('#video'),
    canvas = document.querySelector('#canvas');

  streamCam();

  video.addEventListener('playing', function(ev) 
    if (!streaming) 
      if (video.videoHeight === 0) 
        window.setTimeout(function() 
          video.pause();
          video.play();
        , 100);
       else 
        video.setAttribute('width', video.videoWidth);
        video.setAttribute('height', video.videoHeight);
        canvas.setAttribute('width', constrainedWidth);
        canvas.setAttribute('height', constrainedHeight);
        streaming = true;
        requestAnimationFrame(FFResize);
      
    
  , false);

;
#canvas 
  position: fixed;
  top: 0;
<video id="video"></video>
<canvas id="canvas"></canvas>

这完成了它的工作,但正如您所指出的,限制仍在开发中,让它们与 Firefox 一起工作的唯一方法是在about:config 中手动设置每个浏览器的media.navigator.video.default_

【讨论】:

很好的答案,感谢您的完整解释。你的运行代码 sn-p 非常好:) 只是为了澄清这个误解:如果您使用标准语法而不是过时的 Chrome 语法,约束在 Firefox 中工作得很好。它应该是width: min: 640 而不是minWidth: 640。也跳过mandatory。见this answer。 @jib 是的,我看到了这个答案,(看看我对已接受答案的评论)我会更新答案,但我不确定你跳过 Chrome 语法的想法是个好主意,因为Chrome 使用 w3 的语法抛出一个错误,并且不会显示任何内容。但是,我会在几分钟后将我写的 polyfill 放入编辑中。因此,我不确定require: ["width", "height"] 何时集成到 FF 中。我将不得不尝试使用旧版本,所以我现在让我的答案。 @Kaiido 这个答案已经***年了。去年我在 FF32 中添加了 require 语法,不幸的是,在新语法正在制定中(我使用 jesup)在规范中绕道而行。 - 我同意 Chome 抛出错误是不幸的,但我建议向他们提出问题,因为我们必须集中在标准上,而不是在其他东西上。我正在尝试在跨浏览器垫片 adapter.js 中解决此问题,并且我有一个 PR 用于等待约束的 polyfill,它使规范约束适用于 Chrome 和旧版本的火狐。 更新: adapter.js 现在允许您在 Chrome 和 Firefox 中使用规范约束!【参考方案2】:

好的。好久不见。

我发现如下代码:

var vid_constraints = 
    mandatory: 
        maxHeight: 180,
        maxWidth: 320
    

其实没用。更好的方法是简单地使用

navigator.getUserMedia(audio: true, video: true, function(stream)..,function(e)...);

您只需通过 CSS 或内联 html 设置视频的大小。对于我的应用程序,这很好用,因为我只需要将视频内容复制到画布上。最后效果很好。

因此,总而言之,问题似乎出在约束选项上。如果您试图使其在多个浏览器中工作,请远离它们。

如果您需要更好地控制相机分辨率,这可能不适合您。如果您需要对 res 进行有限控制,不妨试试有条件的(即if(navigator.mozGetUserMedia)... //compatible resolutions etc ...)。

祈祷很快就会有一个标准的getUserMedia 函数被所有浏览器处理! :)

仅供参考。我分叉了一些 fiddleJS 代码并对其进行了修改以在 Chrome 和 Mozilla 中进行测试:http://jsfiddle.net/sidewaiise/Laq5txvq/

【讨论】:

似乎不再起作用了……我也遇到了同样的问题。当 chrome 客户端和 firefox 客户端聊天时,无论我尝试过哪个版本,来自 firefox 的视频始终是 4:3。我现在在firefox 35上,你的小提琴也不起作用...... 如果您的问题只是调整页面上播放的视频大小,那么调整视频播放元素的大小是正确的答案。约束访问不同的相机模式,并且由于人们拥有具有不同能力的不同相机,因此应注意不要过度限制硬件能力,以免无意中排除人的风险。但是,通过 peerConnection 发送视频是另一回事。尽管 peerConnection 会动态调整比特率,但在不需要时避免使用高分辨率和帧速率也会有所帮助。小提琴为我工作 FWIW。

以上是关于Firefox 和 Chrome 中的 getUserMedia() 视频大小不同的主要内容,如果未能解决你的问题,请参考以下文章

Chrome、Firefox 和 Explorer 中的图片、srcset 和 css

Firefox 和 Chrome 中的输入高度差异

Firefox 和 Chrome 中的绝对定位问题

Firefox 和 Chrome 中的文字转语音差异

如何修复firefox和chrome中的空间?

Firefox 和 Chrome 中的 getUserMedia() 视频大小不同