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”:

javascript
< 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():

javascript
< 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():

javascript
< view plain text >
  1. conn.onmessage = function (ev) {
  2.     if (matches = ev.data.match(/^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:

javascript
< 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).

11 thoughts on Video Sync with WebSocket and Node

Comments are closed.

  1. Hi Michael,

    Love the idea of collaborating on video editing in real-time using real-time push. I’m working on a real-time push service called Kwwika so I thought I’d take your example and update it to use the Kwwika JavaScript API.

    You can see the example here: http://kwwika.com/Standalone/Demos/JavaScript/video-sync-gist-446051/video-client.html

    And I’ve also added my updates to GitHub: http://gist.github.com/446051

    It’s shown me a few things:

    1) the connection events (connection, close) provided by WebSocket are actually really handy. With the Kwwika API we don’t presently to track user connections on a per application basis (we have global users support) so we potentially need to look into that as it is very handy.

    2) the video “timeupdate” event fires very frequently so it might be worth an application developer considering sending events for this on a less frequent basis.

    3) The video quite frequently was black screening for me although the audio continued to play. Is this due to the video I chose to use or did you also see this?

    I’d be interested to get your feedback on the Kwwika API if you have any thoughts.

    Thanks,

    Phil

  2. Hey Phil,

    Great to see you forked it!

    1) Glad it’s useful. Funny they turned out to be useful as I only added it as an after-thought to demonstrate those calls…but I guess it served its purpose then. WebSocket doesn’t have support in all the browsers yet, but it can degrade nicely to more traditional Comet techniques. 2) Agree – if I was doing a production-ready app, I’d probably just sync the time every 5-10 seconds, as long as the video’s in play mode (and I’d use system clocks to try and account for lag and keep everyone in sync). 3) I didn’t find that, but then I only tested on a single machine.

  3. Pingback: The Secret to Quick Node Hacks is

  4. Hello

    Iam trying to see the demo of this article on my Ubuntu 10.10 PC I get this error when i run “node video-server.js” from node-websocket-server/test directory

    node.js:134 throw e; // process.nextTick error, or ‘error’ event on first tick ^ Error: Cannot find module ‘../lib/ws/’ at Function._resolveFilename (module.js:317:11) at Function._load (module.js:262:25) at require (module.js:346:19) at Object. (/home/kishore/node-websocket-server/test/video-server.js:2:10) at Module._compile (module.js:402:26) at Object..js (module.js:408:10) at Module.load (module.js:334:31) at Function._load (module.js:293:12) at Array. (module.js:421:10) at EventEmitter._tickCallback (node.js:126:26)

    could you help out please?

  5. Hi Kishore,

    Node moves fast, so the demo may already be out of date. But it looks like node-websocket-server isn’t installed. At the time I made this demo, NPM was just getting started, so I didn’t use it, but that would probably help now.

  6. Thanks Mahemoff

    I was able to fix this with NPM as you suggested. Is multiple video syncing possible with this kind of architechture. or could you suggest some pointers/ways to implement a multiple window multiple video sync scenario.?

  7. Glad it worked.

    Sure, it would be pretty easy to extend this to multi videos, e.g. just pass around a video ID with each command. (PS Remember this is all very hacky and there’s no security model.)

  8. hai MAHEMOFF, I am using web socket server for video sync. When I try to connect with the chrome browser(windows xp), am getting the following error in terminal

    WS: 789017081 draft75 connection WS: 789017081 stateChange: 1 -> 3 WS: 789017081 stateChange: 3 -> 4 WS: 789017081 write: Manager: Attached: (1) WS: 789017081 end WS: 789017081 stateChange: 4 -> 5 WS: 789017081 socket closed WS: 789017081 stateChange: 5 -> 6 Manager: Detached: (0)

    please help…. Thanks

  9. I have one question. What path do you put the server.js? As I don’t understand following: var ws = require(‘../lib/ws’);

  10. Pingback: Play YouTube video in sync across multiple clients - feed99