Pradumya Gaurav, backend engineer

Node.js, queues and LLMs, from Bengaluru.

Email me

Notes ·

Keeping two screens in step: from 350 ms apart to 6 ms

How Pawse keeps two people watching the same movie in sync over a slow network, without streaming the video.

Pawse is a small app I built so my partner and I can watch a movie together from different cities. The usual way is “3, 2, 1, play” over a call, and ten minutes later one of you is a few seconds ahead. Tools that re-stream the video lag, and they break on anything with DRM.

Pawse does not stream the movie. Each person plays their own copy, and the two players only send each other tiny control events: play, pause, seek, and where they are in the video. The hard part is making those two players agree.

Why “send play” is not enough

If I press play and send “play at 12:04”, my partner receives it after the network delay. If the relay takes 150 ms each way, their player is already behind. Over time the gap does not stay still either: two devices never keep time at exactly the same speed, so the drift grows.

On the old relay, with 150 ms of simulated delay each way, the two players sat about 350 ms apart.

What the engine does

  1. Agree on the time. Each player measures the round trip to the other and works out how far its clock is from the host’s. Now “12:04 at time T” means the same moment on both sides.
  2. Ignore tiny gaps. Below 20 ms nobody can tell, and correcting it would only cause jitter.
  3. Nudge, do not jump. For gaps under 400 ms, the follower speeds up or slows down by up to 8% until it catches up. A few percent faster for a few seconds is hard to notice; a jump is not.
  4. Seek only when it is far off. Above 400 ms, it jumps to the right spot.

The same small module runs in the web player and in the Chrome extension that syncs YouTube, so both behave the same.

The numbers

Measured with a script, 3 runs on the same machine, 150 ms of simulated delay each way:

The app shows the live gap as a small badge, like “IN SYNC 12MS”, so you can see it working instead of trusting it.

What I took from it

Measure the problem before fixing it. The measuring script came first. Without the 350 ms baseline, I would not have known which fix mattered.

Small corrections beat big ones. Changing speed by a few percent is invisible. Seeking every time is not.

It is a side project, but it is the same work I do for clients: two systems that have to agree on the state of something, over a network that will not always cooperate.

Pawse is live at pawsetv.vercel.app, and the code is open on GitHub.

All notes