自Firefox 49以来,MJPEG Stream在First Frame上冻结

时间:2016-12-22 21:03:00

标签: javascript css firefox html5-canvas

从Firefox 49开始,来自IP摄像机的MJPEG流使用内部服务冻结第一帧。这不会发生在Chrome中。我找不到可能导致此错误的FF 49更改日志中的任何更改。请记住,此代码不是我的,并且非常陈旧,但它仍可在Chrome中运行。 我认为可能导致错误的代码片段:

String.Join()

请记住,这个程序很大,我只是采用了我认为可能导致错误的片段。它适用于49之前的所有Firefox版本,目前在Chrome上

1 个答案:

答案 0 :(得分:0)

您依赖的是chrome bug

根据specs

  

...当CanvasImageSource对象表示HTMLOrSVGImageElement中的动画图像时,用户代理必须使用动画的默认图像(当不支持动画或禁用动画时,将使用格式定义的图像),或者,如果没有这样的图像,则在为CanvasRenderingContext2D API渲染图像时动画的第一帧。

MJPEG流是这些动画图像的一部分,因此UAs必须仅返回第一帧。 Chrome最近遵循了这部分规格,但用于GIF图片。

因此,通过在每次重绘时在请求中添加随机参数,仍然有强制完全重新加载MJPEG流的解决方法,但是你将失去MJPEG格式的所有优点并且会产生大量繁重的请求。

var url = 'http://webcam.st-malo.com/axis-cgi/mjpg/video.cgi?resolution=352x288';

var img = new Image();
img.onload = drawAndReload;
// check if there are already parameters in the passed url
var paramHead = url.indexOf('?') > 0 ? '&' : '?';
img.src = url;
var ctx = c.getContext('2d');

function drawAndReload(){
  if(c.width !== this.naturalWidth){
    c.width = this.naturalWidth;
    c.height = this.naturalHeight;
    }
  ctx.drawImage(this, 0, 0);
  // reset the image
  this.src = ''; // should not be necessary
  this.src = url + paramHead + Math.random(); // force no-cache
  }
<canvas id="c"></canvas>

一个真正的解决方案是将您的MJPEG流转换为视频流服务器端,然后使用MediaSource API获取块并将其显示在HTMLVideoElement中,您将能够在其上绘制画布没有限制。