[removed] Extract video frames reliably

前端 未结 2 1491
死守一世寂寞
死守一世寂寞 2020-11-27 13:01

I\'m working on a client-side project which lets a user supply a video file and apply basic manipulations to it. I\'m trying to extract the frames from the video reliably.

2条回答
  •  离开以前
    2020-11-27 13:55

    Mostly taken from this great answer by GameAlchemist :

    Since browsers doesn't respect videos' framerates, but instead "use of some tricks to make a match between the frame-rate of the movie and the refresh-rate of the screen", your assumption that every 30th of a second, a new frame will be painted is quite inaccurate.
    However, the timeupdate event should fire when the currentTime has changed, and we can assume that a new frame was painted.

    So, I would do it like so :

    document.querySelector('input').addEventListener('change', extractFrames, false);
    
    function extractFrames() {
      var video = document.createElement('video');
      var array = [];
      var canvas = document.createElement('canvas');
      var ctx = canvas.getContext('2d');
      var pro = document.querySelector('#progress');
    
      function initCanvas(e) {
        canvas.width = this.videoWidth;
        canvas.height = this.videoHeight;
      }
    
      function drawFrame(e) {
        this.pause();
        ctx.drawImage(this, 0, 0);
        /* 
        this will save as a Blob, less memory consumptive than toDataURL
        a polyfill can be found at
        https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob#Polyfill
        */
        canvas.toBlob(saveFrame, 'image/jpeg');
        pro.innerHTML = ((this.currentTime / this.duration) * 100).toFixed(2) + ' %';
        if (this.currentTime < this.duration) {
          this.play();
        }
      }
    
      function saveFrame(blob) {
        array.push(blob);
      }
    
      function revokeURL(e) {
        URL.revokeObjectURL(this.src);
      }
      
      function onend(e) {
        var img;
        // do whatever with the frames
        for (var i = 0; i < array.length; i++) {
          img = new Image();
          img.onload = revokeURL;
          img.src = URL.createObjectURL(array[i]);
          document.body.appendChild(img);
        }
        // we don't need the video's objectURL anymore
        URL.revokeObjectURL(this.src);
      }
      
      video.muted = true;
    
      video.addEventListener('loadedmetadata', initCanvas, false);
      video.addEventListener('timeupdate', drawFrame, false);
      video.addEventListener('ended', onend, false);
    
      video.src = URL.createObjectURL(this.files[0]);
      video.play();
    }
    
    

提交回复
热议问题