A real-time synchronization server for watching YouTube videos together with friends. Built with Express, Socket.IO, and YouTube Data API v3.
- π₯ Real-time video synchronization (play, pause, seek)
- π¬ Live chat functionality
- π₯ Multi-user room support
- π YouTube video search integration
- π― Host-based room management
- π Automatic host transfer on disconnect
- Node.js - Runtime environment
- Express - Web framework
- Socket.IO - Real-time bidirectional communication
- YouTube Data API v3 - Video search functionality
- CORS - Cross-origin resource sharing
- Node.js (v16 or higher)
- npm or yarn
- YouTube Data API Key (Get one here)
- Clone the repository:
git clone <repository-url>
cd server- Install dependencies:
npm install- Create a
.envfile in the server directory:
PORT=5000
YOUTUBE_API_KEY=your_youtube_api_key_here- Go to Google Cloud Console
- Create a new project or select existing one
- Enable "YouTube Data API v3"
- Go to "Credentials" β "Create Credentials" β "API Key"
- Copy the API key to your
.envfile
npm run devnpm startThe server will start on http://localhost:5000 (or your specified PORT).
GET /api/search?q=search_query&maxResults=10Query Parameters:
q(required) - Search query stringmaxResults(optional) - Number of results (default: 8, max: 50)
Response:
{
"items": [
{
"id": { "videoId": "video_id" },
"snippet": {
"title": "Video Title",
"description": "Video Description",
"channelTitle": "Channel Name",
"thumbnails": { ... }
}
}
]
}GET /api/pingResponse:
{ "ok": true }| Event | Payload | Description |
|---|---|---|
create_room |
- | Create a new room and become host |
join_room |
{ roomId, username } |
Join an existing room |
change_video |
{ videoId, startTime } |
Change the current video |
play |
{ time } |
Play video at specified time |
pause |
{ time } |
Pause video at specified time |
seek |
{ time } |
Seek to specified time |
request_sync |
- | Request current playback state |
sync_state |
{ toSocket, state } |
Send playback state to specific user |
chat_message |
{ text } |
Send a chat message |
set_username |
{ username } |
Update username |
| Event | Payload | Description |
|---|---|---|
change_video |
{ videoId, startTime, by } |
Video was changed by user |
play |
{ time, by } |
Video was played by user |
pause |
{ time, by } |
Video was paused by user |
seek |
{ time, by } |
Video was seeked by user |
sync_state |
{ videoId, currentTime, isPlaying } |
Current playback state |
you_are_host |
- | You are now the room host |
member_update |
{ members } |
Member count updated |
chat_message |
{ type, user, text, timestamp } |
New chat message |
request_sync_from_host |
{ toSocket } |
Host should send sync state |
{
roomId: {
host: socketId, // Current host socket ID
members: Set([socketId]) // Set of all member socket IDs
}
}- When the host disconnects, the first remaining member becomes the new host
- If all members leave, the room is automatically deleted
- New host receives
you_are_hostevent
The server includes error handling for:
- Missing YouTube API key (warning only, search won't work)
- Invalid room IDs when joining
- YouTube API errors
- Socket connection errors
| Variable | Required | Default | Description |
|---|---|---|---|
PORT |
No | 5000 | Server port |
YOUTUBE_API_KEY |
Yes | - | YouTube Data API v3 key |
server/
βββ index.js # Main server file
βββ package.json # Dependencies
βββ .env # Environment variables
βββ README.md # This file
{
"express": "^4.18.0",
"socket.io": "^4.6.0",
"node-fetch": "^3.3.0",
"cors": "^2.8.5",
"dotenv": "^16.0.0"
}- Verify your API key is correct in
.env - Check if YouTube Data API v3 is enabled in Google Cloud Console
- Ensure you haven't exceeded your API quota
- The server allows all origins by default
- Modify CORS settings in
index.jsif needed for production
- Check if port 5000 is available
- Verify firewall settings
- Ensure frontend is using correct SERVER_URL
- Set environment variables on your hosting platform
- Use a process manager like PM2:
npm install -g pm2
pm2 start index.js --name watch-together-server- Set up reverse proxy with nginx if needed
- Enable HTTPS for secure connections
- Configure CORS for your specific domain
- Store API keys in environment variables
- Implement rate limiting for production
- Add authentication for private rooms
- Validate all user inputs
- Use HTTPS in production
- Implement room password protection (future enhancement)
MIT
For issues and questions, please open an issue on GitHub.