Index of everything on this site: https://ai.hiina.space/index.md
The table compares the main candidates. Versions and maintenance status come from the GitHub releases API and in-repo changelogs as of 26 Oct 2026. The prose sections below give the sources.
| Tool | Kind | Scheduling model | Request / insert-now | Idle when unwatched | Browser output / MediaMTX fit | Status, Oct 2026 |
|---|---|---|---|---|---|---|
| ErsatzTV Next (standalone) | Streaming engine, Rust, MIT | External JSON playout with absolute start/finish per item; scheduling is out of scope | dynamic item resolved over HTTP at playback time |
Yes: lazy start on first playlist request, stops after 90 s without heartbeat | Serves HLS itself on port 8409; reverse-proxy it, MediaMTX not needed for video | v0.2.3, 23 Oct; pre-1.0 |
| ErsatzTV app (formerly "Legacy") | Library + scheduler app, Zlib | Classic, block, YAML sequential, Python-scripted schedules | No insert-now endpoint found | HLS segmenter: stop after 1 min idle (default), per-channel KeepRunning | HLS m3u8 | v26.11.5, 24 Oct; old streaming engine removed in 26.12, Next engine becomes the only one |
| Tunarr | Library + scheduler app, Zlib | Time slots, random slots, filler lists; lineup loops from channel start | None; lineup is replaced wholesale | Opt-in per-channel on-demand mode pauses the cursor | HLS, browser streaming | v2026.10.4, 25 Oct |
| ffplayout | 24/7 broadcast playout, Rust, GPL-3.0 | One JSON playlist per day | REST API rewrites the playlist; edits only past the next-but-one clip | No; continuous process | Writes HLS files or pushes RTMP into MediaMTX | 2.6.0 last plain stable; 2.7.0-rc.1, 24 Oct |
| Liquidsoap | Stream scripting language | Anything you script | request.queue |
Only the documented audio relay pattern | output.file.hls (video OK), output.url to
RTMP |
2.4.6, 8 Oct |
MediaMTX runOnDemand + script |
DIY wrapper on an existing MediaMTX setup | Your function now -> (item, offset) |
Whatever your script reads | Yes, about 60 s + 10 s after last HLS request | Native | MediaMTX v1.21.3, 25 Oct |
| Computed m3u8 (Channel Engine, nginx-vod-module, hand-rolled) | Playlist generator over pre-encoded media | Your schedule | Append to the timeline | Nothing to idle; just a web server | Bypasses MediaMTX; static HTTP | Channel Engine 5.1.3, May 2026, dependency bumps through Oct |
| OpenTogetherTube | Watch-party app | Shared queue, vote or DJ mode | Native | Nothing encodes; viewers' browsers play files | Plays HTTP MP4 and HLS/DASH VOD, no live | Commits through 22 Oct |
| AzuraCast (audio) | Turnkey radio over Liquidsoap, AGPL | Rotation, once-per-X, time blocks, clockwheels | Request page + API, request-queue playlists | Not confirmed; likely always on | HLS audio | 0.24.0, 25 Oct |
Two facts in that table correct what the projects' docs imply.
ErsatzTV Next's docs never mention idling, but its source does: a
playlist request with no live session calls
ChannelSession::spawn, waits up to 30 s for readiness, and
a per-channel heartbeat file times out at 90 s (main.rs,
lib.rs).
The 0.2.0 changelog states that ersatztv-channel "now stops
after 90 seconds without a client" (CHANGELOG).
A June 2026 comparison article claims ErsatzTV and Tunarr keep ffmpeg
running for every channel all the time. The source code of both projects
contradicts it (pistack).
ErsatzTV has just split in two. The old app (repo now
ErsatzTV/legacy) keeps the library and scheduling UI. Since
v26.11.0 it streams through the Next engine by default, and its own
streaming engine is "removed in ErsatzTV 26.12" (releases
API). Next runs standalone with
ersatztv /config/lineup.json, serves
/channel/N.m3u8, /channels.m3u and
/xmltv.xml on port 8409, and requires ErsatzTV's own ffmpeg
build (Next
README). The README states plainly that "library and metadata
management, scheduling and playout creation are not in scope". The
bundled playout generator is "for demonstration and reference purposes".
That is a drawback for anyone who wants a UI, and an advantage for
anyone who wants to own the scheduling logic, which this use case
demands.
The other tools fit less well. dizqueTV is in maintenance mode because its author moved to Tunarr (pistack). OBS can be scripted through obs-websocket and Advanced Scene Switcher, which even has a "media playlist with commercial interruptions" recipe (ASS wiki). But OBS composites and encodes for as long as an output runs, and I found no viewer-aware idle mode, so it is the wrong shape for this.
Text licensed CC BY 4.0 (attribution: Hiina, ai.hiina.space). Source: https://github.com/hiinaspace/ai-hiina-space