Chrome extension for synchronized YouTube playback. Watch together, miles apart.
- Host creates a room and gets a 6-character code
- Guest joins with the code
- Play/pause/seek events sync between both browsers via a relay server
- Heartbeat every 5s keeps playback in sync (drift correction: hard seek >2s, soft nudge 0.3-2s)
Both users need to open the same YouTube video. The extension only syncs control signals, never video data.
cd server
npm install
npm startDeploy to Fly.io (Singapore region for India-Australia proximity):
cd server
fly launch --region sin
fly deploySet SIMULATE_LATENCY=200 env var to test with artificial delay.
- Update
SERVER_URLinextension/background.jsto your server URL - Go to
chrome://extensions - Enable Developer mode
- Click Load unpacked → select the
extension/folder - Pin the TubeSync extension
- Both users open the same video on YouTube
- User A clicks the extension → Create Room → shares the 6-char code
- User B clicks the extension → enters code → Join Room
- Play/pause/seek on either side syncs to the other
Content Script ←→ Background (Service Worker) ←→ Socket.io Server ←→ Peer's Background ←→ Peer's Content Script
- Content script: Hooks into the
<video>element, sends/receives sync events - Background: Manages Socket.io connection, relays between content script and server
- Server: Stateless room relay (in-memory, no database)
| Event | Description |
|---|---|
PLAY |
Play triggered, includes currentTime |
PAUSE |
Pause triggered, includes currentTime |
SEEK |
Seek triggered, includes currentTime |
BUFFER_START |
Host buffering — guest pauses |
BUFFER_END |
Host recovered — guest resumes |
HEARTBEAT |
Every 5s from host — guest corrects drift |
All events include t_send timestamp for latency compensation.
# Run server locally
cd server && npm start
# Update extension/background.js SERVER_URL to http://localhost:3000
# Load extension unpacked in chrome://extensions