StreamSched (stream-scheduler) is a high-performance, self-hosted web application designed to schedule and relay IPTV streams. It bridges any M3U or Xtream Codes provider to an SRS (Simple Realtime Server) instance via FFmpeg, providing a resilient, multi-slot streaming architecture with a premium user experience.
- ποΈ Modular Architecture β Newly refactored logic split into dedicated service engines (
relay-engine,m3u-parser,auto-scheduler) for enhanced stability and maintainability. - π‘οΈ Resilient Relays β FFmpeg processes are spawned detached from the Node.js parent. They survive server crashes and full service restarts; the engine automatically re-connects to existing processes on boot for zero-gap monitoring.
- β‘ High-Performance Parsing β M3U handling has been optimized with stream-based I/O and non-blocking JSON persistence, drastically reducing memory overhead for large playlists.
- π Intelligent Auto-Scheduler β Automatically fetches and schedules sports events via API. Features full time-zone awareness (DST-safe) and smart channel matching.
- π Auto-Recovery β Built-in watchdog that detects unexpected FFmpeg exits or stream stalls and automatically re-spawns the relay after a 3-second buffer.
- π¨ Premium UI / UX β A modern, glassmorphic "framed" interface built with vanilla JS/CSS. Features Inter typography, real-time SSE updates, and a responsive mobile-first layout.
- π‘ Stream Monitoring β Integrated Activity Log with real-time SSE event streaming, detailed per-slot FFmpeg logging (configurable), and in-browser HLS previews.
- π Secured by Design β Session-based authentication with Bcrypt password hashing and persistent data storage in standard JSON formats.
- Node.js v18 or later.
- FFmpeg β Local binary in
bin/or installed on your system PATH. - SRS (Simple Realtime Server) β To receive RTMP and serve HLS/WebRTC.
Clone the repository and install the lightweight dependencies:
npm installPlace your FFmpeg binary in a folder named bin/ at the project root, or ensure ffmpeg is available in your system environment variables. StreamSched automatically detects your OS and resolves the correct path.
Run the setup utility to initialize your credentials and ports:
node setup.jsStart the server:
node server.jsThe application will be accessible at http://localhost:3000 (or your configured port).
StreamSched is built on a modular monolithic pattern. While it remains a single-file server deployment for simplicity, the core logic is divided into specialized engines:
Manages the lifecycle of FFmpeg processes. It supports up to 5 simultaneous relay slots (stream01βstream05).
- Detached Spawning: Uses
spawnwithdetached: trueto decouple FFmpeg from the Node.js event loop. - PID Persistence: PIDs are saved to disk, allowing the server to re-acquire control of running streams after a restart.
- Force-Replacement: Intelligently kills existing relays when a prioritized or forced stream is launched on an occupied slot.
An optimized parser designed for speed and low memory usage.
- Streamed Persistence: Uses
fs.createWriteStreamto flush large channel caches without blocking. - Dual-Layer Cache: Keeps an in-memory searchable index while persisting the raw data to JSON for instant startup loads.
The "brain" of the application for automated event coverage.
- API Integration: Queries streaming APIs daily.
- Fuzzy Matching: Matches API event names against your M3U channel list to find the best broadcast source.
- Paste your M3U or Xtream Codes URL β supported formats:
- Direct
.m3u/.m3u8file URL - Xtream Codes:
http://server/get.php?username=X&password=Y&type=m3u_plus
- Direct
- Click Get to fetch and cache the channel list.
- Optionally enable Auto-refresh to re-fetch daily at a time of your choosing.
- Type in the Channel Search box to filter your channel list.
- Click or tap any channel to open the scheduling modal:
- Now β relays immediately; see slot selection behavior below.
- Once β pick a specific date and time.
- Recurring β choose Daily / Weekly / Monthly, set a time, and (for weekly/monthly) pick a day.
- Optionally select a Relay Slot to pin the stream to a specific slot (defaults to Auto; hidden when Max Streams is set to 1).
- After clicking Add to Schedules, the search input and results are cleared automatically.
- Each active relay appears as a card showing channel logo, stream name, start time, and slot (slot hidden when Max Streams is 1).
- π Preview β shows a live HLS video preview directly in the dashboard via hls.js.
- β Stop β terminates the FFmpeg relay for that slot.
- If FFmpeg exits unexpectedly, the relay auto-restarts after 3 seconds and is logged to the Activity Log.
- Run Now β trigger any schedule immediately.
- Edit β update name, time, relay slot, or recurrence.
- Delete β remove a schedule immediately (no confirmation).
- Recurring schedules show a frequency badge (
DAILY/WEEKLY/MONTHLY) and a compact time tag (e.g.8:00 PM,Mon Β· 8:00 PM,1st Β· 8:00 PM). - Once schedules remove themselves after firing.
- Shows the last 100 auto-scheduler events, M3U refresh events, relay errors, and auto-restart events.
- Updates in real time via Server-Sent Events (SSE).
The Auto-Scheduler queries a sports API on a daily schedule and automatically creates stream entries when a match is found.
- Set a Search String (e.g.
Blue Jays) to match against API results. - Set an API Endpoint β defaults to the college baseball scoreboard.
- Set a Check Time β the time of day the scheduler will run (Eastern timezone).
- Set a Default Relay Slot β optionally pin auto-created schedules to a specific relay slot.
- Optionally enable Refresh M3U before running to ensure channels are up to date.
- Toggle Auto-Scheduler on to activate.
Matched events are scheduled 10 minutes before their listed start time. Game times are sourced exclusively from the API (UTC, converted to Eastern Time via America/New_York) to ensure correct DST handling year-round.
StreamSched supports up to 5 simultaneous FFmpeg relay slots. Configure how many are available in Settings β Max Streams (1β5, default 2). Each slot (stream01βstream05) maps to an RTMP stream pushed to SRS.
- Max Streams = 1 β
stream01is always used; if occupied, the current stream is stopped and replaced automatically. - Max Streams > 1 β a slot picker appears listing Auto and each individual slot with its current state (Free or the name of the stream playing). Choosing an occupied slot stops it first.
- Debug Logging β A single toggle that controls all optional logging.
- FFmpeg Logs: Writes warnings/errors to
logs/ffmpeg-<slot>.log. - Log Max File Size: Truncates files if they exceed your set limit (1β100 MB).
To run StreamSched as a background Windows service that starts with the system, use NSSM:
nssm install StreamSched node server.jsThen in the NSSM GUI:
- Set Startup directory to the
StreamSchedfolder. - Ensure the service name is
StreamSched(this is required for the application's internal restart feature).
All data is stored in the data/ directory for easy portability:
| File | Contents |
|---|---|
config.json |
Port, username, hashed password, session secret |
schedules.json |
All saved schedules and recurrence rules |
history.json |
Playback log (last 10 entries) |
settings.json |
SRS URLs, max slots, M3U refresh settings |
auto_scheduler.json |
Auto-scheduler config and truncated activity log |
m3u_cache.json |
Cached channel list from last M3U fetch |
relays.json |
Persisted relay state (PIDs, start times, logos) |
- The app binds to
0.0.0.0and is accessible to all devices on your LAN. - Use a strong password, especially if your LAN is shared.
- For internet access, place behind a reverse proxy (Nginx, Caddy) with HTTPS.
- Passwords are stored securely using Bcrypt hashing.
Published under the MIT License. Created with a focus on simplicity, reliability, and performance.