Turn local video files into a 24/7 YouTube Live stream — playlists, looping, auto-detected encoding (up to 4K), and a real-time control dashboard. Built with Node.js + FFmpeg.
A self-hosted web app that streams desktop videos to your YouTube channel over RTMP. It probes your machine's FFmpeg capabilities, auto-detects the best encoding settings for each source video, and gives you a live dashboard with metrics, logs, and pre-stream warnings. Ideal for 24/7 looping channels (music, ambience, radio).
- Multi-stream — create and run several streams at once
- Playlists & looping — sequence videos and loop forever (great for 24/7 channels)
- Adaptive resolution — 720p / 1080p / 1440p / 4K (2160p), auto-detected and overridable
- Auto-analysis —
ffprobereads each video and recommends encoder, bitrate, fps, and resolution - Hardware encoding — auto-detects NVENC / QSV / AMF, falls back to libx264
- Real-time dashboard — live bitrate / fps / speed metrics and logs over WebSocket
- Pre-stream warnings — silent video, upscaling, CPU-bound 4K, aspect-ratio mismatch, and more
- Upload estimate — shows the recommended minimum upload bandwidth for your bitrate
- Resilient — ingest handshake detection and auto-reconnect with backoff
- Scheduled auto-stop — end the stream automatically at a set time of day or after a duration (changeable while live)
- Cross-platform — Windows, macOS, Linux
Auto-detected settings with resolution-aware bitrate presets and live pre-stream warnings:
The interesting engineering, for the curious:
- FFmpeg capability probing at startup — runs real encode tests to discover which encoders and AAC options actually work on the host, then adapts. No hard-coded assumptions across machines.
- Source-aware recommendations —
ffprobe→ resolution tier + YouTube-range bitrate + frame rate, applied automatically unless you override a field. - Dynamic scale/pad filter — letterbox/pillarbox to any target resolution while preserving the source aspect ratio.
- CPU-decode + GPU-encode pipeline — offloads the heavy encode to the hardware encoder while keeping a portable filter chain.
- Live warnings engine — cross-checks the chosen settings against the probed source to flag risky/suboptimal setups before you go live.
- Crash-safe persistence — atomic writes of stream configs and a graceful shutdown that stops active FFmpeg processes.
Browser (SPA) ──HTTP──▶ Express REST API ──▶ StreamManager ──spawn──▶ FFmpeg ──RTMP──▶ YouTube
▲ │
└──────────────────── WebSocket ◀─────────────┘ (live metrics, logs, status)
server.js— Express REST API, static UI, WebSocket broadcast, filesystem/probe endpointsStreamManager.js— stream lifecycle, FFmpeg command building, retry/handshake logic, persistencecapabilities.js— one-time FFmpeg capability detectionpublic/— vanilla-JS single-page dashboard (no framework)
- Node.js v14 or later
- FFmpeg on your system PATH (
ffmpeg -version) - A hardware encoder (NVENC / QSV / AMF) is recommended for real-time 4K
- Live streaming enabled on your YouTube channel
npm install
npm start
# then open http://localhost:3000Windows users can also just double-click start.bat. For a step-by-step walkthrough see QUICKSTART.md.
Installing FFmpeg
Windows
- Download a build from https://www.gyan.dev/ffmpeg/builds/ (
ffmpeg-release-full.zip) - Extract it to
C:\ffmpeg(so you haveC:\ffmpeg\bin\ffmpeg.exe) - Add
C:\ffmpeg\binto your systemPathenvironment variable - Open a new terminal and verify with
ffmpeg -version
macOS
brew install ffmpegLinux
sudo apt update && sudo apt install ffmpeg- In YouTube Studio → Go Live → Stream, copy your RTMP URL and Stream Key.
- In the app, click + New, name the stream, and paste the RTMP URL and Stream Key.
- Click Select Video and pick a file — the app auto-analyzes it and fills in the recommended settings.
- Adjust resolution / encoder / bitrate if you like (warnings guide you), then click ▶ Start.
The web UI is a thin client over a REST API + WebSocket, so you can script it too:
GET /api/streams # list streams
GET /api/streams/:id # stream detail
POST /api/streams # create { name, rtmpUrl, streamKey, playlist, loop }
PUT /api/streams/:id # update { name, rtmpUrl, streamKey, encoder, bitrate, fps, width, height, loop,
# autoStopMode ('off'|'clock'|'duration'), autoStopTime 'HH:MM', autoStopMinutes }
PUT /api/streams/:id/playlist # set playlist { playlist: [paths] }
POST /api/streams/:id/start # start
POST /api/streams/:id/stop # stop
DELETE /api/streams/:id # delete
POST /api/probe # ffprobe a file + recommended settings { path }
GET /api/videos?path=... # list videos in a directory
GET /api/directories?path=... # list subdirectories
GET /api/capabilities # detected FFmpeg version / encoders / filters- Videos are read from the server's filesystem (the machine running the app) — there is no upload. It's designed to be self-hosted by the person who owns the videos.
- No built-in authentication — run it locally or behind your own access control / tunnel.
- Real-time 4K is CPU/GPU intensive; a hardware encoder is strongly recommended (libx264/CPU may not keep up).
- "FFmpeg not found" — make sure
ffmpeg -versionworks in a fresh terminal; the app also auto-detectsC:\ffmpeg\bin\ffmpeg.exe. - Stream won't start — check the RTMP URL and Stream Key, confirm the stream is enabled in YouTube Studio, and check your connection.
- Stuttering / falling behind — watch the Speed metric; if it drops below
1.0xyour encoder can't keep up. Lower the resolution/bitrate or use a hardware encoder.
MIT © Atakan Sarıkoç — see LICENSE.
Made with ❤️ by Atakan Sarıkoç

