You have several problems to solve to achieve this.
Getting the raw pixels of the GIF.
<canvas>
is probably the best way to do this, but I don't think it will play nicely with an animated GIF. You could certainly read a series of images.
Converting the frames into a video stream.
While there are JavaScript implementations of MPEG audio codecs, I'm not aware of a video codec in pure JS. You could take a look at the ffmpeg source and try porting it.
In addition to implementing the video compression codec itself (such as MPEG-1, -2, H.264, and so on), you'd also have to write to a container format of some kind (For example, a MPEG PS.)
Handling binary data.
The output of any video codec is binary data, and JavaScript by its nature doesn't deal well with raw binary data. Recent browsers have added typed arrays exactly to address this shortcoming in a memory-efficient manner.
Delivering the video file to the user.
I know this sounds silly since all of the above would technically happen on the user's computer, but they happen in the browser sandbox. You now have to get the data out of the browser and into a file that the user can save to their file system.
Someone else suggested using a data:
URI (base64-encoded data), but this is a terrible idea from a memory standpoint, especially since you'll be dealing with video data, which is relatively large. At this point, you'll have your video stream in a typed array. Create a new Blob
from the typed array and pass that Blob
to window.URL.createObjectURL
. This way, the data needn't be duplicated in memory; instead, the browser will "download" from the typed array to the file system.
Of course, all of this assumes that the user's machine will have enough memory (RAM). Unlike normal video compression implementations, you can't stream the output data to disk; you have to keep the entire file in memory. You'll likely run out of memory faster than you'd think.
So while this may be theoretically possible, it's not a good idea. If it works, it will be very slow and freeze the browser while it encodes the video (since JS and the browser UI share the same, single thread). I suppose you could bring web workers in to the mix to get around that, though.
At this point in time, you'll pretty much have to roll your own server-side solution or use some kind of service that will do the heavy lifting for you.
Alternatively, you may be able to leverage Google's NaCl (native client) in Chrome to actually do the video encoding. NaCl allows you to run native (C/C++) code in the browser.
It looks like there's a ffmpeg port, and there are APIs to do file I/O.
Obviously, this does only work in Chrome. Firefox, Safari, and IE won't support NaCl.