Video Sync with WebSocket and Node

Wanting to explore WebSocket, I made a demo that syncs videos for all users looking at the page (See the Code). Any user can “take control”, so that the other videos will follow the controller’s video. Writing it was a cinch with the Javascript WebSocket API in the client, and the very straightforward Node WebSocket Server powering the server.

Note it’s just a simple demo – there’s no security model here and there’s a very simple sync mechanism: When a “slave” client receives the latest duration, it adds a second to account for lag, and moves the video iff there’s a 5-second discrepancy.

How does a WebSocket client look? Well, it looks a lot simpler than a traditional Comet client. Initiate the connection with “new WebSocket”:

< view plain text >
  1. var conn;
  2.   $_("#join").onclick = function() {
  3.     conn = new WebSocket("ws://localhost:8000/test");

Upload a message to the server with send():

< view plain text >
  1. video.addEventListener("timeupdate", function() {
  2.       if (iAmControlling()) conn.send(video.currentTime);
  3.     }, true);

Receive a message from the server with conn.onmessage():

< view plain text >
  1. conn.onmessage = function (ev) {
  2.     if (matches =^pause (.+)$/)) {
  3.       video.pause();
  4.       video.currentTime = matches[1];
  5.     }
  6.     ...
  7.   }

And when it’s time to draw the curtains, close the connection with another one-liner:

< view plain text >
  1. $_("#leave").onclick = function() {
  2.       conn.close();
  3.       ...
  4.     };

The server is also rather tiny. It mostly just broadcasts (sends to all clients) any incoming message and it’s up to the clients to deal with it. Which is why I say there’s no real security model here.

As you can see in the above snippets, “video” plays an excellent cameo role here, with its equally simple API. One downside, which others have mentioned too, is the lack of styling in the default video controls. It’s great the API supports automatic controls, but it’s unfortunate there’s no CSS manipulation. In this case, the “slave” browsers should be able to see the time, but not have the ability to change the progress. I hope this changes in the future, because the API is otherwise very powerful without compromising simplicity. Until then, libraries will arise to fill the gap.

The demo works in both Chrome and Safari (and they play nice simultaneously).