40

I wanted to make a short intro for a video podcast. Being a geeky web developer and not already having access to or knowledge of animation tools, I thought I might take a stab at doing the intro using various html5 techniques. The problem is, how do I turn that into a video clip I can easily drop into iMovie?

If I have to, I think this can be accomplished if I only use canvas by exporting a png every frame using getImageData. The only drawback is that I'm limited to just canvas. I was hoping to use the whole range of new html5/css3/svg techniques. I don't need this functionality to work for general web use, just for myself, so I'd be happy for anything that requires installation etc. to make it work.

If I have to, I guess I can probably use a video screen capture tool, but I was hoping for a complete open source chain.

In the end, I expect I'll be creating a series of pngs and using ffmpeg to put them together, I was just hoping to figure out a great way of doing this in an automated, open source way.

Update I just wanted to clarify that what I'm basically trying to do is use HTML5 instead of something like flash, but I'm not trying to serve it to other people on the internet, I want to convert it to video, and it never needs to leave my computer, which is actually a mac, not a Linux server. If flash can do it, why not html, right? That seems to be what people are trying to claim. The problem is, I can take a SWF and convert it to standard video, but how do you do that with javascript or CSS3 animations? Obviously a screen capture tool can sort of do the job, but those are usually low frame rate, and can't be run programmatically to my knowledge.

The closest sort of thing I can think of that isn't a screenshot tool would be something like webkit2png, only instead of a single png, it would take 60 pngs per second. At some point, I might actually try to implement exactly that, but I wanted to see if anyone else had something good.

Example So I actually just did an intro using the built in iMovie title cards. This is a good example of roughly the sort of thing I would like to do. Should actually be fairly straightforward with a little CSS3 animation work. What I have isn't bad, but I would like to use custom graphics, with better font/layout control.

Russell Leggett
  • 8,795
  • 3
  • 31
  • 45

5 Answers5

10

There is a tutorial with the code using both javascript and PHP to create a video from your canvas animation. The program save frame by frame of your canvas animation like in a movie, and then you can convert this stack of frames to a specific video format with the codec of your choice.

Code from the linked page.

(function () {
    var canvas = document.getElementById('c'),
        c = canvas.getContext('2d'),
        w = canvas.width, h = canvas.height,
        p = [], clr, n = 200;

    clr = [ 'red', 'green', 'blue', 'yellow', 'purple' ];

    for (var i = 0; i < n; i++) {
        // generate particle with random initial velocity, radius, and color
        p.push({
            x: w/2,
            y: h/2,
            vx: Math.random()*12-6,
            vy: Math.random()*12-6,
            r: Math.random()*4+3,
            clr: Math.floor(Math.random()*clr.length)
        });
    }

    function frame() {
        // cover the canvas with 50% opacity (creates fading trails)
        c.fillStyle = 'rgba(0,0,0,0.5)';
        c.fillRect(0, 0, w, h);

        for (var i = 0; i < n; i++) {
            // reduce velocity to 99%
            p[i].vx *= 0.99;
            p[i].vy *= 0.99;

            // adjust position by the current velocity
            p[i].x += p[i].vx;
            p[i].y += p[i].vy;

            // detect collisions with the edges
            if (p[i].x < p[i].r || p[i].x > w-p[i].r) {
                // reverse velocity (direction)
                p[i].vx = -p[i].vx;
                // adjust position again (in case it already passed the edge)
                p[i].x += p[i].vx;
            }
            // see above
            if (p[i].y < p[i].r || p[i].y > h-p[i].r) {
                p[i].vy = -p[i].vy;
                p[i].y += p[i].vy;
            }

            // draw the circle at the new postion
            c.fillStyle = clr[p[i].clr]; // set color
            c.beginPath();
            c.arc(p[i].x, p[i].y, p[i].r, 0, Math.PI*2, false);
            c.fill();
        }
    }

    // execute frame() every 30 ms
    setInterval(frame, 30);
}());
karlcow
  • 6,977
  • 4
  • 38
  • 72
  • 3
    I listed this as a possibility in my question, but I would really like something that includes the entire range of options. This would not, for example, capture CSS3 animations or SVG. – Russell Leggett Feb 05 '11 at 14:15
  • then you want a dump of your window context as images. Which might be more complex. – karlcow Feb 05 '11 at 15:37
  • webkit2png takes only one shot. It is unlikely a multiple webkit2png captures will solve the issue. It would be possible to have a loop I guess, where there is a delay in between the initial rendering and the capture but then it would become cumbersome to have something making sense. The images would not be completely synchronized. I wonder if webkit2png is hackable to have it pushing out multiple images. – karlcow Feb 05 '11 at 15:55
  • asking around to browsers implementers. It seems that the security context would forbid it. But I'm still digging for information. – karlcow Feb 06 '11 at 16:57
  • I highly doubt that I could get anything to work from within the actual stock browser in javascript, but without spending hours to figure it out, I'm wondering if I could make something native like webkit2png just output 30fps, or would that be impossible mid css-transform. What might also work really well would be injecting a function into the browser object model takeScreenshot(), that I could use during a javascript based animation like stop motion. The javascript animation wouldn't have to work in real time. – Russell Leggett Feb 08 '11 at 13:59
  • The code listed in this comment merely displays an example animation. The code that does the movie creation work entails serializing the canvas image data and HTTP POSTing each frame to a PHP service that stores them as PNGs. The exercise of turning these PNGs into a movie is for the reader. – asciimo Oct 18 '17 at 23:29
3

So far the best thing I've found so far that won't require me to write c code is using Titanium for desktop. It features a takeScreenshot function available from javascript code. The takeScreenshot function gets a screenshot of the entire desktop, but it should be easy to automate cropping that down. With a plethora of javascript animation libraries out there, I should be able to hack in ways of getting a screenshot at every frame, even if it can't happen in real-time.

While I won't be able to use CSS animations, this is probably the most flexible solution anyway, given that anything I can do with CSS animations I can do with javascript, and I'll have more control over frame rate, etc.

Additionally, this should allow me to use all things the browser is capable of, combining html/css/js/svg/canvas.

Russell Leggett
  • 8,795
  • 3
  • 31
  • 45
  • 1
    Hi @russel , It's been a while now and I was wondering if you have come up with a more advanced view on your problem. – Abhinav Feb 22 '15 at 14:50
  • See I am also trying to achieve something similar to this. Mine I need to run on server though. I have been researching a lot of options lately. I am just done with using JavaFX with imageJ to achieve it. But it is difficult to scale up this process. So if you can share anything useful, it will be highly appreciated. TIA – Abhinav Feb 22 '15 at 14:52
  • I've moved on at this point. I would say the easiest thing to try (if you want to try going down this road) would be using phantomjs. without too much trouble, you should be able to use the render method (http://phantomjs.org/api/webpage/method/render.html). Not sure how efficient it would be to create a complete animation that way :) – Russell Leggett Feb 28 '15 at 04:10
2

Well Techsmith Snagit captures in AVI, or their premium application camtasia ( generates a Flash video and a web page launcher) would work. Why not simply create a Powerpoint slide of the features you want to touch on and use a HTML set of pages of actual demos you want to illustrate in depth. This is the approach I am taking.

Hans
  • 21
  • 1
  • I'm not doing a podcast about html, I just trying to make a short animation using html that can be included in video - but the video is not a demo of html. I don't want it to look like a screencast - I just want it to look like a slick video. – Russell Leggett Jan 10 '11 at 03:36
2

I had worked on a tool that does something similar to your requirements. It basically uses cutycapt (or any other tool to convert HTML with CSS into image) and takes series of screenshot depending on the frame rate required.

For that to work, the animations should be purely CSS animations and the tool interpolates the intermediate frame's CSS properties by parsing the CSS.

https://github.com/bpsagar/css2video

I'm not sure if the tool is complete, let me know if you are interested.

Sagar Chakravarthy
  • 1,206
  • 1
  • 9
  • 4
1

You are right in my opinion the best way to do it is to create images from the canvas's data and then compile all those images into a video via a module (fluent-ffmpeg for example, which is a node js package). It's pretty easy but be careful of the FPS (frame rate) if you create those images as fast as you can you may change the fps of your video, for example if you use recursively requestAnimationFrame() you will be at 60fps. So, instead of reading a html5 video you should set the time each 1/30s (for example if you want a 30fps video) and create a image from the currentTime until the end of the video. And if you have not only one canvas, if you apply animations on your video via multiple canvas you could create a new empty canvas and draw all canvas's data on it to create only one image instead of one image for each canvas.

Aruna Herath
  • 6,241
  • 1
  • 40
  • 59
rhanb
  • 11
  • 3