I'd like to synchronize the playing of a video on multiple clients. One client will give the server a URL to a video which can be streamed and click on play then every client is supposed to start playing the video at the exact same time. And while playing it has to be ensured that the every client is still in sync. If someone suddenly stops playing everyone else has to stop too as soon as possible. (At this point the client that stopped would be behind 1 second or so.) Then when the same person starts playing again everyone else would obviously have to wait a second until the one client caught up and then start playing too.
My first try was to set up a mySQL db and let each client constantly report their current video time to it. The server then calculated if any client in the db is behind and if so, calculated for each client how long they would have to pause to let it catch up.
But that didn't really work too well. It strongly depended on your latency and I wasn't able to get it reliably working with a delay of <300ms (a really good latency was required for that).
So what could I do to improve it? Should I change my setup (javscript<->ajax<->php<->mySQL)?
How can I reliably calculate the travel time of the response the server sends a client? I mean, I can't just assume the client's system time is the same as the server's... The best thing I could come up with would be something like this:
var start = new Date().getTime()
$.post( "sync.php", "")
.done(function(data) {
var end = new Date().getTime()/1000;
var clientServerClientTravelTime = (end-start);
var estimatedServerClientTravelTime = clientServerClientTravelTime/2;
});
Any idea how I could improve this whole concept?
Btw video cannot be on my own server.
Audio-to-video synchronization (AV synchronization, also known as lip sync, or by the lack of it: lip-sync error, lip flap) refers to the relative timing of audio (sound) and video (image) parts during creation, post-production (mixing), transmission, reception and play-back processing.
The most accurate way would probably be to use sockets: this way you can signal to other systems what is required and don't need to wait for ajax polling. You won't be able to exactly compensate for latency, but could average things out by measuring the round trip with some test messages.
So the plan would be:
I used something very similar to sync 18 projectors across 3 cars for an AV display system. (https://vimeo.com/97191170). Despite Xorifelse's comments in his answer, PHP was perfectly capabale of receiving, processing and handling up to 100 sockets commands per second from a controller (jquery based application in a browser, connected by sockets), filtering out duplicates, logging them all to mySQL for a second process to poll on demand (approx 10 times per second, triggered by socket request from a Flash (Adobe Air) script and then also passed on light instructions to under-car lighting (also through sockets) or to other cars (also through sockets). In fact, the PHP/MySQL solution was far more robust than trying to pump socket instructions directly into Flash. It's very possible. Tech details for the project are here: http://labs.soapcreative.com/cars-that-feel-vivid-sydney/
I suggest to to NodeJS and sockets programming to implement. Further you can use http://www.webrtc.org
Have you tried using WebRTC, it is used for peer to peer connections, and for streaming as well. Using WebRTC you can make multy stream from one client to others, I have used it to stream videos to other people, and everyone that connects is getting the video, but I am not streaming it server does, I was only controlling the video, pause, sound, .....
You can try using it, but in your case every client can control the stream. Personally I have no tried something like that, but this way you have no issues regarding latency, pauses, and so on.
As someone else said, I would probably setup a little websocket server in NodeJS. The idea is to create a list of events, like "Play", "Pause". When a client connects, it asks the server where it should start playing (since the other client could have started before it) or if you want you can broadcast a "StartAgain" event to all the client every time someone connects. Once the video started, you can then listen to the HTML Audio/Video events, in order to detect if a client video stopped playing. In this case, you send a "Pause" event to your server, which will broadcast it to all the other clients to pause the playing too. When the video resume, you can send the "Play" event.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With