A web application that allows LAN party guests to add YouTube videos and Jellyfin music to a shared playback queue. The host machine (identified by IP address) automatically plays the content in sequence.
- Utilizes node.js (
npmandnodecommands) - Install easily using Docker
- Windows
.exeprovided in the Releases section
- ๐ต Automatic playback - Host machine plays videos and music in order
- ๐ถ Jellyfin integration - Stream music from your Jellyfin server with search and random song
- ๐ซ Embed validation - Blocks non-embeddable YouTube videos at submission time
- โญ๏ธ Auto-skip - Automatically skips videos that fail to start within 10 seconds
- โ Clear error messages - Displays YouTube error codes with explanations
- ๐ IP-based authentication - Only the host can control playback
- ๐ฑ Responsive design - Works on mobile devices
Add YouTube videos to your LAN Jukebox directly from the YouTube website:
- Chrome/Edge Extension: lan-jukebox-extension
- Firefox Extension: lan-jukebox-extension-firefox
Windows:
ipconfig
Linux:
ip addr show
Mac:
ifconfig | grep "inet"
๐ก Tip: Instead of using IP addresses, you can use your computer's hostname! Most systems support .local mDNS names (e.g., my-computer.local). The server will display this address when it starts.
Pull and run the pre-built image directly from Docker Hub:
-
Download and create config.json
curl -o config.json https://raw.githubusercontent.com/maribotto/lan-jukebox/main/config.example.jsonThen edit
config.jsonand replace the IP with your host machine's IP address. -
Pull and run
docker pull maribotto/lan-jukebox:latest docker run -d -p 3000:3000 -v $(pwd)/config.json:/app/config.json:ro maribotto/lan-jukebox:latest
-
Create config.json
cp config.example.json config.jsonThen edit
config.jsonand replace the IP with your host machine's IP address. -
Start the container
docker compose up -d -
Open in browser
- Host:
http://localhost:3000 - Guests:
http://YOUR-HOST-IP:3000
- Host:
-
Stop the container
docker compose down
-
Create config.json
If you cloned the repository:
cp config.example.json config.jsonOr download directly:
curl -o config.json https://raw.githubusercontent.com/maribotto/lan-jukebox/main/config.example.jsonThen edit
config.jsonand replace the IP with your host machine's IP address. -
Build image
docker build -t lan-jukebox . -
Run container
docker run -d \ -p 3000:3000 \ -v $(pwd)/config.json:/app/config.json:ro \ --name lan-jukebox \ lan-jukebox -
Stop
docker stop lan-jukebox docker rm lan-jukebox
-
Install dependencies
npm install -
Create config.json
cp config.example.json config.jsonThen edit
config.jsonwith your host machine's IP address. -
Start the server
node server.js
- On host machine: The player initializes automatically when items are in the queue
- Anyone can: Add YouTube links or Jellyfin songs to the queue
- Host can: Skip videos, pause/play, and control playback
- Jellyfin: Connect to your Jellyfin server to search or add random songs
- Backend: Node.js, Express
- Frontend: Vanilla JavaScript, YouTube IFrame API, HTML5 Audio
- Integrations: YouTube oEmbed API, Jellyfin API
- Container: Docker
GET /api/status- Returns whether requester is host or guestPOST /api/add- Add video/item to queue (all users)POST /api/next- Get next video (host only)POST /api/delete- Remove video from queue (host only)GET /api/queue- Get current queue and currently playing item (all users)POST /api/jellyfin/proxy- Proxy requests to Jellyfin server (CORS bypass)GET /api/jellyfin/image-proxy- Proxy Jellyfin album art images
config.json:
{
"hostIp": "192.168.50.200",
"port": 3000
}
hostIp: IP address or hostname of the host machine that controls playback (e.g.,"192.168.1.100"or"my-computer.local")port(optional): Port number for the server. Default:3000trustProxy(optional): Set totruewhen using a reverse proxy like Caddy or Nginx. Default:falserequireLogin(optional): Set totrueto require authentication. Default:falseusername(optional): Username for login. Only used ifrequireLoginistruepasswordHash(optional): Bcrypt hash of the password. Only used ifrequireLoginistruesessionSecret(optional): Secret key for session encryption. Auto-generated if not provided
Enable login authentication to protect your jukebox when exposed to the internet:
1. Generate a password hash:
Choose one of the following methods:
Method A: Using Node.js (if installed)
node generate-password.js yourSecurePassword123Method B: Using standalone executable (Windows/Linux/macOS)
If you're using the .exe version or don't have Node.js installed, use the standalone password generator:
- Windows:
generate-password.exe yourSecurePassword123 - Linux/macOS:
./generate-password yourSecurePassword123
The executables are included in the releases or can be built with:
npm run build:password-genMethod C: Online bcrypt generator
Visit: https://bcrypt-generator.com/
- Enter your password
- Use cost factor: 10
- Copy the generated hash
Method D: Using Python
pip install bcrypt
python -c "import bcrypt; print(bcrypt.hashpw(b'yourPassword', bcrypt.gensalt(rounds=10)).decode())"2. Update config.json:
{
"hostIp": "192.168.1.100",
"trustProxy": false,
"requireLogin": true,
"username": "admin",
"passwordHash": "$2b$10$...",
"sessionSecret": "your-random-secret-key"
}
3. Default credentials (for testing):
- Username:
admin - Password:
admin - Hash in
config.example.json
Warning
Always change the default password in production! Use generate-password.js to create a secure password hash.
To expose the jukebox to the internet with HTTPS:
-
Install Caddy on your server
https://caddyserver.com/docs/install -
Update config.json
{ "hostIp": "YOUR_PUBLIC_IP_OR_DOMAIN", "trustProxy": true, "requireLogin": true, "username": "admin", "passwordHash": "$2b$10$...", "sessionSecret": "your-random-secret-key" }Use
generate-password.jsto create your password hash -
Create Caddyfile (see
Caddyfile.example)yourdomain.com { reverse_proxy localhost:3000 } -
Start Caddy
caddy run
Caddy automatically:
- Obtains SSL certificates from Let's Encrypt
- Redirects HTTP to HTTPS
- Forwards client IP addresses to the app
Warning
Only enable trustProxy: true when using a reverse proxy. Enabling it without a proxy is a security risk as clients can spoof their IP addresses.
Videos won't play:
- Verify you're on the host machine (IP matches config.json)
- Click the "START PLAYER" button
- Check browser console (F12) for errors
- See Video Restrictions for common reasons videos fail
"Video embedding not allowed" or Error 101/150:
- Video owner has disabled embedding, or video is age-restricted/region-locked
- Try finding an alternative version (lyric video, cover, or re-upload)
- Application attempts to block these during submission, but some slip through
- Full details: Video Restrictions
Videos auto-skip after 10 seconds:
- This is normal behavior for videos that fail to start playback
- Usually caused by age restrictions, embedding restrictions, or Premium content
- Check the error code displayed on screen (see Error Codes Reference)
Container won't start:
- Check if port 3000 is available:
lsof -i :3000 - Verify config.json exists and is valid JSON
- Ensure public/ folder is in the correct location
Authentication not working:
- Verify
requireLogin: truein config.json - Check password hash was generated correctly with bcrypt cost factor 10
- Clear browser cookies and try logging in again
- Check server logs for authentication errors
Due to YouTube's embedding limitations, some videos cannot be played in the jukebox. The application validates videos before adding them to the queue, but certain restrictions cannot be detected in advance.
The following types of videos will fail to play or auto-skip:
- ๐ Age-restricted content - Requires YouTube login (not possible in embedded player)
- ๐ต Music videos with restrictions - Many music videos are blocked by record labels (VEVO, UMG, etc.)
- ๐ YouTube Premium/Music exclusive content - Requires paid subscription
- ๐ซ Embedding disabled by owner - Video owner has explicitly disabled embedding
- ๐ Region-locked content - Videos restricted to certain countries
- ๐ Private or unlisted videos - Not accessible through embed player
- โ Deleted or removed videos - No longer available
- At submission: Videos that are clearly non-embeddable are rejected with an error message
- At playback: If a video fails to start within 10 seconds, it automatically skips to the next video
- On error: YouTube error codes are displayed with explanations (e.g., Error 101: Embedding disabled)
- โ Use official music uploads from artists' channels rather than topic channels
- โ Test videos first by checking if they can be embedded on other websites
- โ Avoid "Auto-Generated" topic videos - these are often restricted
- โ Use lyric videos or covers as alternatives to official music videos
- โ Check for "Made for Kids" restrictions - these may have limited embedding
Common YouTube player error codes:
- Error 2: Invalid video ID or malformed URL
- Error 5: HTML5 player error (browser compatibility)
- Error 100: Video not found, private, or deleted
- Error 101: Embedding disabled or age-restricted
- Error 150: Embedding disabled or region-locked
Free to use for LAN parties and other fun projects!
