HTML5 video and canvas

2019-09-14 15:12发布

问题:

I have a video and I need to capture 3 images from it, at different time. Time is not random, I have to take images at specified time (13:10:02, 13:10:03, 13:10:04). The images should be displayed on the page when I access the page, not when I click a button or something like that. Until now I tried with an example that I found on the internet, but on this example, the image is displayed after a button was clicked, and I don't know how to give a specified time.

<video controls>
    <source src="http://www.jplayer.org/video/m4v/Big_Buck_Bunny_Trailer.m4v" type="video/mp4"></source>
    <source src="http://www.jplayer.org/video/m4v/Big_Buck_Bunny_Trailer.m4v" type="video/mp4"></source>
</video>
<canvas id="canvas" width="640" height="480"></canvas>
<button id="snap" onclick="snap()">Snap Photo</button>

<script>
    var video=document.querySelector('video');
    var canvas=document.querySelector('canvas');
    var context=canvas.getContext('2d');
    var w,h,ratio;
    //add loadedmetadata which will helps to identify video attributes......
    video.addEventListener('loadedmetadata',function()
    {
        ratio=video.videoWidth/video.videoHeight;
        w=video.videoWidth-100;
        h=parseInt(w/ratio,10);
        canvas.width=w;
        canvas.height=h;
    },false);
    ///define a function

    function snap()
    {
        context.fillRect(0,0,w,h);
        context.drawImage(video,0,0,w,h);
    }
</script>

回答1:

You can set the time, for which frame you want to draw to canvas, by setting the currentTime on the video object.
Then you need to wait for video to finish seeking, draw the video onto canvas an move to the next frame.
Of course you need to wait for the video to load before you start drawing its frames.

var images = [ // defined canvases and times for frames
    {
        canvas: '#canvas1',
        time: 10.0 // in seconds
    },
    {
        canvas: '#canvas2',
        time: 19.0
    },
    {
        canvas: '#canvas3',
        time: 26.0
    },
];

function drawFrame(video, time, canvas, callback)
{
    var context = canvas.getContext("2d");
    video.addEventListener("seeked", function(e) {
        e.target.removeEventListener(e.type, arguments.callee); // remove the handler or else it will draw another frame on the same canvas, when the next seek happens
        context.fillRect(0, 0, canvas.width, canvas.height);
        context.drawImage(video, 0, 0, canvas.width, canvas.height);
        callback();
    });
    video.currentTime = time;
}
function draw(video, images, i)
{
    if (i >= images.length)
        return;
    drawFrame(video, images[i].time, images[i].canvas, function() {
        draw(video, images, i+1);
    });
}
var video = document.createElement('video');
video.addEventListener('loadedmetadata', function() // when the metadata is loaded set the canvases size and start drawing frames
{
    var ratio = video.videoWidth / video.videoHeight;
    var w = video.videoWidth - 100; // set the width of the images to 100 px less than the video
    var h = w / ratio; // fix the height accordingly
    for (var i=0; i<images.length; i++)
    {
        images[i].canvas = document.querySelector(images[i].canvas);

        images[i].canvas.width = w;
        images[i].canvas.height = h;
    }

    draw(video, images, 0);
});
video.src = "http://www.jplayer.org/video/m4v/Big_Buck_Bunny_Trailer.m4v";

JSFiddle