在JS中从视频中提取帧 [英] Extract frames from video in JS

查看:3068
本文介绍了在JS中从视频中提取帧的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试构建一个从JavaScript中提取视频帧的函数。这里是我提出的代码。该函数接收源和回调。从那里开始,我创建了一个带有源的视频,我想在画布中以设定的间隔绘制视频帧。

I'm trying to build a function that extracts frames from a video in JavaScript. Here the code I came up with. The function receives a source and a callback. From there, I create a video with the source and I want to draw frames of the video in the canvas with a set interval.

不幸的是,返回的帧都是透明的图片。

Unfortunately, the frames returned are all transparent images.

我尝试了一些不同的东西,但我无法让它发挥作用。有人可以帮忙吗?
谢谢。

I tried a few different things, but I can't make it work. Can someone help? Thanks.

const extractFramesFromVideo = function(src, callback) {
  var video = document.createElement('video');
  video.src = src;

  video.addEventListener('loadeddata', function() {
    var canvas = document.createElement('canvas');
    var context = canvas.getContext('2d');
    canvas.setAttribute('width', video.videoWidth);
    canvas.setAttribute('height', video.videoHeight);

    var frames = [];
    var fps = 1; // Frames per seconds to
    var interval = 1 / fps; // Frame interval
    var maxDuration = 10; // 10 seconds max duration
    var currentTime = 0; // Start at 0

    while (currentTime < maxDuration) {
      video.currentTime = currentTime; 
      context.drawImage(video, 0, 0, video.videoWidth, video.videoHeight);
      var base64ImageData = canvas.toDataURL();
      frames.push(base64ImageData);

      currentTime += interval;

      if (currentTime >= maxDuration) {
        console.log(frames);
        callback(frames);
      }
    }
  });
}

export default extractFramesFromVideo;


推荐答案

调整代码后等待寻找事件,并修复一些零碎,似乎工作正常:

After tweaking your code to wait for the seeked event, and fixing a few bits and pieces, it seems to work fine:

async function extractFramesFromVideo(videoUrl, fps=25) {
  return new Promise(async (resolve) => {

    // fully download it first (no buffering):
    let videoBlob = await fetch(videoUrl).then(r => r.blob());
    let videoObjectUrl = URL.createObjectURL(videoBlob);
    let video = document.createElement("video");

    let seekResolve;
    video.addEventListener('seeked', async function() {
      if(seekResolve) seekResolve();
    });

    video.addEventListener('loadeddata', async function() {
      let canvas = document.createElement('canvas');
      let context = canvas.getContext('2d');
      let [w, h] = [video.videoWidth, video.videoHeight]
      canvas.width =  w;
      canvas.height = h;

      let frames = [];
      let interval = 1 / fps;
      let currentTime = 0;
      let duration = video.duration;

      while(currentTime < duration) {
        video.currentTime = currentTime;
        await new Promise(r => seekResolve=r);

        context.drawImage(video, 0, 0, w, h);
        let base64ImageData = canvas.toDataURL();
        frames.push(base64ImageData);

        currentTime += interval;
      }
      resolve(frames);
    });

    // set video src *after* listening to events in case it loads so fast
    // that the events occur before we were listening.
    video.src = videoObjectUrl; 

  });
}

用法:

let frames = await extractFramesFromVideo("https://example.com/video.webm");

这篇关于在JS中从视频中提取帧的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆