Create a room. Invite your friends. Watch in sync.
A real-time watch-party website with synchronized playback, live chat, host controls, and Google Drive video support.
π Open Watchify Β· π Mixify Β· π¨βπ» Developer Portfolio
| Feature | Description |
|---|---|
| π¬ Synced playback | Play, pause, seek and resync across viewers. |
| π Host controls | Everyone / host-only / request-remote, member management and host transfer. |
| π¬ Chat & reactions | Live chat, reactions and timeline reaction markers. |
| βοΈ Google Drive | Optional Google login to select Drive files, plus public Drive links where accessible. |
| π Automatic audio compatibility | FFmpeg-based compatible audio for Google Drive videos with unsupported soundtracks; no manual Audio Fix button. |
| π Multi-language audio | Choose from detected Hindi, English or other embedded audio tracks for supported Google Drive movies; each viewer chooses independently. |
| πΊ Video sources | YouTube, Vimeo, direct video links, uploads and HLS where supported. |
| π Private rooms | Invite codes, optional passwords, room settings and moderation. |
| πΏ Movie night extras | Queue, captions for HTML5 videos, BRB, countdown, glow, vibes, notes and recap. |
| π± Responsive UI | Watch together on desktop and mobile browsers. |
Playback depends on browser codecs, Google Drive access, network speed and available server resources. Automatic audio conversion does not guarantee support for every possible media format.
Open watchify.mixify.co.in, enter your nickname, and press Create new room. Send the invite link or room code to friends. No Watchify account is required. Google login is only needed if you choose to connect your personal Drive.
- Node.js 20+ and npm
- FFmpeg on PATH for automatic Google Drive audio conversion
- FFprobe (typically included with FFmpeg) on PATH for detecting embedded audio languages
- Optional:
yt-dlpon PATH for supported third-party public video links
-
Download/clone the repository and open PowerShell in the folder containing
package.json. -
Install dependencies once:
npm install
-
Check FFmpeg:
ffmpeg -version -
Run the app:
npm start
-
Open http://localhost:3000 on your laptop.
Press Ctrl+C to stop the server. Restart it after changing server code.
- Keep
npm startrunning on your laptop. - Connect phone and laptop to the same local network/Wi-Fi.
- Run
ipconfigon Windows and find the laptop's IPv4 Address (e.g.192.168.1.49). - On your phone open
http://YOUR_LAPTOP_IP:3000(example:http://192.168.1.49:3000). - If the connection fails, check that Windows Firewall allows Node.js on your trusted Private network and that Wi-Fi client isolation is disabled.
Do not use localhost in the phone browser: that points to the phone itself. Google OAuth on the LAN IP is a separate limitation; use the registered localhost callback on your laptop or the deployed HTTPS site for Drive sign-in.
-
In Google Cloud Console, enable Google Drive API, configure the OAuth consent screen and create a Web application OAuth client.
-
Add this exact local Authorized redirect URI:
http://localhost:3000/google-drive/callback. -
Copy
.env.exampleto.envbesideserver.js, then set:GOOGLE_CLIENT_ID=your-client-id GOOGLE_CLIENT_SECRET=your-client-secret GOOGLE_REDIRECT_URI=http://localhost:3000/google-drive/callback
-
Restart
npm start. Your credentials load from.envautomatically, so there is no need to type them again in PowerShell.
On production, register https://watchify.mixify.co.in/google-drive/callback and configure the matching host environment variables. Google drive.readonly is a restricted scope and may require Google verification for public use. Apps in Testing mode may be limited to test users.
Never commit .env, credentials or access tokens. Google Drive authorization tokens live in server memory and may require signing in again after restart.
- Google Drive audio conversion is automatic and the Audio Fix button is hidden.
- FFmpeg must be installed on the server; set
FFMPEG_PATHif it is not on PATH. - For Google Drive movies with two or more detectable audio tracks, open More (β―) β Audio language to select a language. The list comes from the movie's track metadata; when language information is missing it shows a generic track label.
- Audio-track discovery uses FFprobe (
ffprobeon PATH or theFFPROBE_PATHenvironment variable). When probing is unavailable or fails, the movie keeps playing its default soundtrack and the language selector remains hidden. - Each viewer can choose a different soundtrack. Switching tracks restarts that viewer's compatible audio at the current movie timestamp, so a brief loading pause may occur.
- This selector currently applies to Google Drive compatibility streams, not to YouTube, Vimeo or all uploaded/direct files.
- Conversion can start separate jobs per viewer.
MAX_AUDIO_JOBSdefaults to2(capped at4). - Audio and video are synchronized after starting and seeking, but network buffering or low-CPU hosting can still cause short delays.
- For most reliable playback, use H.264/AAC MP4 when possible. Larger production deployments should consider shared adaptive-bitrate transcoding rather than per-viewer FFmpeg.
- YouTube and Vimeo using their respective embeds
- Direct links: MP4, WebM, Ogg, MOV and HLS where the browser supports them
- Uploaded videos: stored temporarily for the room
- Google Drive public links: only if Google permits direct download; a playable Drive preview is not proof of direct stream access
- Google Drive account: optional OAuth connection for authorized files
- Other public websites: optional
yt-dlpwhere supported; availability varies by source
DRM-protected subscription platforms (such as Netflix, Prime Video or Disney+ Hotstar) cannot be streamed through Watchify.
- Connect the GitHub repository to a Render Web Service.
- Use build command
npm installand start commandnpm start. - Set Google OAuth values in Render β Environment, never in public files.
- Ensure FFmpeg is available in your deployment environment for automatic audio conversion. Install FFprobe as well to enable multi-language track detection.
- Connect your domain and check
/healthz(returns{"ok":true}).
Room state is in memory; uploads are temporary. End party removes that room's uploads, and abandoned rooms are cleaned up after the reconnect grace period. Redeploys/restarts end active rooms. Use one instance and configure disk, bandwidth and upload limits (MAX_MB, MAX_ROOM_MB, MAX_TOTAL_MB) for your host. Configure TRUST_PROXY only for your actual trusted proxy setup.
- Guest joining does not require registration.
- Rooms and server uploads are temporary, not permanent cloud storage.
- Deletion cannot remove files already downloaded or cached outside Watchify.
- Stream only content you have permission to use.
Made with β€οΈ by Priyanshu Sharma