I am getting frames from canvas
through canvas.getDataURL()
.
However, now I have an array of png images, but I want a video file.
How do I do this?
var canvas = document.getElementById("mycanvaselementforvideocapturing");
var pngimages = [];
...
setInterval(function(){pngimages.push(canvas.toDataURL())}, 1000);
For a full browser support way, you'll have to send your image batch to the server then use some server-side program to do the encoding.
FFmpeg might be able to do it.
But in newest browsers the
canvas.captureStream
method, has been implemented. It will convert your canvas drawings to a webm video stream, recordable with aMediaRecorder
. All of this is still not stabilized though, and will only be available in latest version of browsers, probably with some flags set in user's preferences (e.g chrome needs the "Experimental Web Platforms" one).And since you asked for a way to add audio to this video, note that you can use
cStream.addTrack(anAudioStream.getAudioTracks()[0]);
before callingnew MediaRecorder(cStream)
, but this will currently only work in chrome, FF seems to have a bug in MediaRecorder which makes it record only the stream with the tracks it was defined to... A workaround for FF is to callnew MediaStream([videoTrack, audioTrack]);
[big thanks to @jib for letting me know how to actually use it...]
Edit:
video.onend
-->video.onended
The
MediaRecorder
+canvas.captureStream
approach in Kaiido's answer is definitely the way to go at the moment - unfortunately as of writing it's only supported in Chrome and Firefox.Another approach that will work when browsers adopt webp encoding support (only Chrome has it, currently) is this:
It uses the whammy library to join a bunch of webp images into a webm video. In browsers that support webp encoding you can write
canvas.toDataURL("image/webp")
to get a webp dataURL from a canvas. This is the relevant bug report for Firefox webp support.One cross-browser approach as of writing seems to be to use libwebp.js to convert the png dataURLs output by
canvas.toDataURL()
into webp images, and then feeding those into the whammy encoder to get your final webm video. Unfortunately the png-->webp encoding process is very slow (several minutes for a few seconds of video on my laptop).Edit: I've discovered that with the
MediaRecorder
/captureStream
approach, you can end up with low-quality output videos compared to the whammy approach. So unless there's some way to control the quality of the captured stream, thewhammy
approach seems like the best approach, with the other two as fall-backs. See this question for more details. Use this snippet to detect whether a browser supportswebp
encoding (and thus supports the whammy approach):