Monday, April 21st, 2008

JSONVid: Pure JavaScript Video Player

Category: Examples, JavaScript, JSON, Library

>Jacob Seidelin went on a ( crazy :) ) mission to create a pure JavaScript video player that didn’t use Flash:

My first thought was to read binary video files using a technique like the Andy Na posted about here, figuring that there must be some really simple to parse video formats around, but I soon changed directions and decided to make up a whole new video format. Enter.. JSONVid. Using a player like mplayer, it is easy to export all frames in a movie clip to individual jpeg files, and using whichever language you prefer it is also fairly trivial to collect these files, base64 encode the bunch of them and throw them all together in a nice JSON file (I used this PHP script).

The format uses good ole data: URLs, which are finally supported in IE with version 8:

[json]

{
frm : “JSVID”, // format id tag
ver : 1, // version number of format
width : 320, // width of video
height : 240, // height of video
rate : 15, // framerate (frames per second)
frames : 495, // number of frames in file
data : {
video : [ // here comes 495 data:uris containing base64 encoded jpeg image frames
"data:image/jpeg;base64,/9j/4AAQSkZJRgABAgEASABIAAD/7gAOQWRv ... ",
"data:image/jpeg;base64,/9j/4AAQSkZJRgABAgEASABIAAD/7gAOQWRv ... ",
...
]
}
}
[/json]

Then he created the player:

First strategy was to create an Image object for each frame and render it on a canvas element using drawImage(). That worked fine and performance was nice (although Opera used a lot of CPU), but I figured I’d try just using a regular image tag and just change the src property to another data:uri each frame. The change was barely noticeably in Firefox and Safari and it ran a bit better in Opera, so I lost the canvas and stuck with plain old images.

Now, it seems that Firefox will eat up all the memory in the world if you keep throwing new data:uris at the same image tag, which led to another change, so for each frame a new Image object was created and saved for later and as the video played, the previous frame Image was replaced by the new Image object. That seemed to work, but introduced an annoying delay as all these Image objects were created before playing, so I ended up moving the Image creation to actual render cycle where it simply checks if the frame Image has already been created, and if not, creates it.

You can now get going with HTML such as:

  1. <html>
  2. <head>
  3. <script src="jsvideo.js" type="text/javascript"></script>
  4. </head>
  5. <body>
  6. <div videosrc="myvideo.jsvid" videoautoplay="true"></div>
  7. </body>
  8. </html>

There are a couple of tests to play with. It was also pointed out that maybe an animated gif/png would be a choice (without controls), and of course, Flash is still the best choice here, until we get video support in most browsers.

Related Content:

Posted by Dion Almaer at 9:15 am
11 Comments

+++--
3.6 rating from 84 votes

11 Comments »

Comments feed TrackBack URI

Is the video really missing sound? Video without sound is a bit of a let down. Until then Flash is the best option.

However, the iPhone does not support Flash. Can anyone with an iPhone confirm how well this example works? I’d be interested to know.

Comment by tastypopsicle — April 21, 2008

I won’t deny that it’s interesting but it’s hardly practical is it?

Comment by Jamie — April 21, 2008

Just a thought, why not use the CSS sprites technique and put it all in one image and change the background position? Might help with performance. Not as though this has many real world uses anyways, but a cool experiment.

Comment by posure — April 21, 2008

Don’t most browsers (modulo IE) support Motion JPEG?

Comment by RichB — April 21, 2008

Base64-encoded data of course isn’t the most efficient format size-wise, maybe gzip would help – but either way, a pretty fun little demo. I think this (or someone else’s related experiment) was shown here several months back.

Comment by Schill — April 21, 2008

Maybe fun to do, but I’ll stick to realtime effects generated as BMP images ( or Canvas ) as I’ve been for the last 4 years.

Comment by p01 — April 21, 2008

Nice. There’s a lot you can do in Javascript but it doesn’t mean you should :P

Good experiment though and yes, I will be purchasing a copy of Office Space soon!

Comment by danielskinner — April 21, 2008

How do the overall movies sizes tend to compare with SWF, DIVX, etc?

Comment by pwnedd — April 21, 2008

Yeah, this seems like a re-implementation of motionJPEG. The data rate on that’s gotta be pretty high. Maybe with some diffing and keyframes you could take it down a peg… but then you’re writing a codec too.

I think it would be most useful for the video format and codec decisions in HTML 5 to be settled. Afterwards, I’m looking forward to programmatic access to playback and status.

Comment by tack — April 21, 2008

…so why not just use Flash?

Comment by musicfreak — April 24, 2008

Interesting page, and articles on it … Ruby developer

Comment by gabi78krk — October 8, 2009

Leave a comment

You must be logged in to post a comment.