从画布拍摄间隔照片

Capture photos in interval from canvas

本文关键字:照片 布拍摄      更新时间:2023-09-26

我有一个脚本,允许我在画布中显示网络摄像头并在一定间隔内"下载"特定帧。当时间参数很大(每 30 秒捕获 2 分钟)时,我遇到了问题。它平稳运行了大约 15 分钟,然后崩溃(Firefox 关闭并出现内存不足错误)。此外,重新启动 Firefox 后,有时会在 3-4 分钟内拍摄许多 0 字节照片,然后再次开始工作。我正在实验室中放置的旧 2 GB RAM 机器上运行它,有没有办法减少内存使用量?

这是一段带有参数和函数realizarCapturas的代码。我可以添加其余代码,但我认为要优化的部分应该是这个。

  var frecuenciaComienzoCaptura = 1; // how long till next capture
  var frecuenciaCaptura = 3; //seconds between photos
  var duracion = 5; // amount of photos to capture
  function realizarCapturas(){
    var i = 1;
    var interval = setInterval(function(){
      if(i <= duracion){
        context.drawImage(video, 0, 0, 640, 480);
        var imagen = document.getElementById("imagen");
        imagen.href = canvas.toDataURL("image/png");
        var now = new Date();
        var filename = formatNumber(now.getHours()) + "-" + formatNumber(now.getMinutes()) + "-" + formatNumber(now.getSeconds());
        imagen.download = filename + ".png"; // Make sure the browser downloads the image
        imagen.click(); // Trigger the click
        i = i+1;
      }else{
        clearInterval(interval);
      }
    }, frecuenciaCaptura * 1000);
  }

  setInterval(function(){
    realizarCapturas();
  }, frecuenciaComienzoCaptura * 1000 * 60 * 60);
  realizarCapturas(); 

}, false);

通常永远不要使用 setInterval,因为它可能是调用堆栈溢出的来源,这在代码中很难检测到。

您的问题是您没有清除正在生成的所有间隔,因此每 3 秒创建一个新的间隔事件。最终,运行少量代码所需的时间将比您创建的所有间隔事件所能管理的时间长,因此每个间隔将继续将其事件推送到调用堆栈,但在堆栈上放置更多间隔最终导致崩溃之前,不会有机会运行。setInterval 也不保证事件之间的时间是准确的。

请改用setTimeout。这样,您只会根据需要生成事件,而不必保留句柄来关闭事件。

下面是您编写的代码,以便您永远不会有调用堆栈溢出。

var frecuenciaComienzoCaptura = 1 * 1000* 60 * 60; // how long till next capture
var frecuenciaCaptura = 3 * 1000; //seconds between photos
var duracion = 5; // amount of photos to capture
var counter = 0;
// the capture function
var captura = function () {    
    counter = counter + 1;
    if(counter < duracion){  // do we need more images?
        // only create timer events as needed.
        setTimeout(captura, frecuenciaCaptura); //set time till next image
    }
    context.drawImage(video, 0, 0, 640, 480);
    var imagen = document.getElementById("imagen");
    imagen.href = canvas.toDataURL("image/png");
    var now = new Date();
    var filename = formatNumber(now.getHours()) + "-" + formatNumber(now.getMinutes()) + "-" + formatNumber(now.getSeconds());
    imagen.download = filename + ".png"; // Make sure the browser downloads the image
    imagen.click(); // Trigger the click
}
function realizarCapturas() {
    // request next batch of captures by only creating one timer event as we need
    setTimeout(realizarCapturas,frecuenciaComienzoCaptura);
    counter = 0; // reset counter
    captura(); // capture timages
}
// start captures.
realizarCapturas();