css 如何从视频中提取帧?

kx7yvsdv  于 2023-01-18  发布在  其他
关注(0)|答案(3)|浏览(172)

你好,我有下面的JS代码,从文件输入创建一个视频:

<canvas  id="prevImgCanvas">Your browser does not support the HTML5 canvas tag.</canvas> 

<input id="videoage" type="file" name="video" class="chooseNail" accept="video/*" style="display:none;" onchange="loadSnippetThumb(event)">
<label for="videoage" id="labelvideo" >Choose Video</label>

var loadSnippetThumb = function(event) {                
    var c = document.getElementById("prevImgCanvas");
    var context = c.getContext('2d');
    var url = URL.createObjectURL(event.target.files[0]);
    var video = document.getElementById('video222');
    video.src = url;
    video.autoPlay = true;

}

这将创建一个在屏幕上播放的视频,用户已选择使用文件输入上传。我不希望视频显示在屏幕上,我只希望能够挑选视频的随机帧并将其显示在画布上。我该如何做到这一点?谢谢。

rryofs0p

rryofs0p1#

seekedloadeddata事件上添加侦听器,并在loadeddata事件中设置currentTime,以获得正确的video.duration。此时将调用seeked事件并绘制您的视频帧:

var video = document.createElement("video");

var canvas = document.getElementById("prevImgCanvas");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

video.addEventListener('loadeddata', function() {
  reloadRandomFrame();
}, false);

video.addEventListener('seeked', function() {
  var context = canvas.getContext('2d');
  context.drawImage(video, 0, 0, canvas.width, canvas.height);
}, false);

var playSelectedFile = function(event) {
  var file = this.files[0];
  var fileURL = URL.createObjectURL(file);
  video.src = fileURL;
}

var input = document.querySelector('input');
input.addEventListener('change', playSelectedFile, false);

function reloadRandomFrame() {
  if (!isNaN(video.duration)) {
    var rand = Math.round(Math.random() * video.duration * 1000) + 1;
    video.currentTime = rand / 1000;
  }
}
<input type="file" accept="video/*" />
<input type="submit" onClick="reloadRandomFrame()" value="load random frame" /><br/>
<canvas id="prevImgCanvas">Your browser does not support the HTML5 canvas tag.</canvas>

JSFiddle here中的相同代码

1mrurvl1

1mrurvl12#

我正在创建一个先进的缩略图生成器,并决定给它一个在HTML/浏览器第一。
我需要检查的第一件事是我是否可以从视频中捕获/提取一帧,因为此功能将是应用程序的支柱。
我已经检查了类似的问题,但这一个似乎是最简单/孤立的一个,所以我张贴在这里。
我用不言自明的代码构建了一个非常简单的测试用例。

let elements = {
    fileInput      : document.querySelector("#fileInput"),
    timeBar        : document.querySelector("#timeBar"),
    video          : document.createElement("video"),
    frameCanvas    : document.querySelector("#frameCanvas"),
    downloadButton : document.querySelector("#downloadButton"),
};

events: {

    elements.fileInput.addEventListener("input", () => {
        loadVideoFromFile(elements.video, elements.fileInput, () => {
            elements.frameCanvas.width  = elements.video.videoWidth;
            elements.frameCanvas.height = elements.video.videoHeight;
            elements.timeBar.max   = elements.video.duration;
            elements.timeBar.value = 0;
            elements.timeBar.dispatchEvent(new Event("change"));
        });
    });

    elements.timeBar.addEventListener("change", () => {
        if (isVideoLoaded()) {
            captureFrameFromVideo(
                elements.video,
                elements.frameCanvas,
                elements.timeBar.value
            );
        }
    });

    elements.downloadButton.addEventListener("click", () => {
        if (isVideoLoaded()) {
            let filename = fileInput.files[0].name.split(".");
            filename.pop();
            filename = filename.join(".");
            filename = filename + "_t" + elements.video.currentTime + ".png";
            let dataURL = elements.frameCanvas.toDataURL();
            download(dataURL, filename);
        }
    });

}

functions: {

    function isVideoLoaded() {
        return elements.fileInput.files.length
               && !isNaN(elements.video.duration);
    }

    function loadVideoFromFile(video, fileInput, callback = null) {
        if (elements.fileInput.files.length) {
            var file = fileInput.files[0];
            var fileURL = URL.createObjectURL(file);
            if (callback) {
                video.addEventListener("loadeddata", callback, {once:true});
            }
            video.src = fileURL;
        }
    }

    function captureFrameFromVideo(video, canvas, time = null) {
        video.addEventListener("seeked", () => {
            var context = canvas.getContext("2d");
            context.drawImage(video, 0, 0, canvas.width, canvas.height);
        }, {once:true});
        if (time) {
            video.currentTime = time;
        } else if (video.currentTime == 0) {
            video.currentTime = 0.1;
        }
    }

    function download(data, filename = "download") {
        var a = document.createElement("a");
        a.href = data;
        a.download = filename;
        document.body.appendChild(a);
        a.addEventListener("click", () => a.remove(), {once:true});
        a.click();
    }

}
body {
    background-color: hsl(0, 0%, 90%);
}
canvas {
    background-color: white;
    box-shadow: 0 1px 2px hsla(0, 0%, 0%, 0.2);
}
<input type="file" accept="video/*" id="fileInput" />
<br><br>
<input type="range" id="timeBar" step="1" min="0" max="100" value="0" />
<br><br>
<canvas id="frameCanvas"></canvas>
<br><br>
<button type="button" id="downloadButton">Download Image</button>

注意:下载按钮在代码片段中似乎不起作用(因为iframe),你可以手动下载(右键单击图像并另存为)。

rdrgkggo

rdrgkggo3#

对我有效的是:

  • 将文件载入视频
  • 添加截图按钮
  • 点击屏幕截图按钮,进入画布,绘制视频
  • 使用canvas.toBlob获取blob
  • 显示图像或帧(只是为了看图像)
<!DOCTYPE html> 
<html> 
<body> 

<video width="400" controls>
  <source src="https://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4">
  Your browser does not support HTML video.
</video>
<br>
<button type="button" id="screenshot-vid-recording">
Take screenshot
</button>
<br><br>
<script>
var screenshotButton = document.getElementById("screenshot-vid-recording");
screenshotButton.addEventListener("click", onCapture);
var canvas = document.createElement("canvas")

function onCapture() {
  var video = document.querySelector("video");
  console.log(new Date(), "capture", video.videoWidth, video.videoHeight)
  canvas.width = video.videoWidth;
  canvas.height = video.videoHeight;
  canvas
    .getContext("2d")
    .drawImage(video, 0, 0, video.videoWidth, video.videoHeight);

  canvas.toBlob(async (blob) => {
    {
      const a = document.createElement('a') // Create "a" element
      const url = URL.createObjectURL(blob) // Create an object URL from blob
     var img = new Image();
     img.src = url;
     document.body.appendChild(img);      
    };
  });
}

</script>

</body> 
</html>

要验证它,请转到https://www.w3schools.com/html/tryit.asp?filename=tryhtml5_video并用我的代码替换代码。按下run,播放视频并截取屏幕

这里是下载图像的另一个片段https://gist.github.com/jrichardsz/05eae330397bfb117d5f3cc60545d984#file-image-or-frame-from-video-tag-html-javascript-download-image-html

相关问题