eda2fac35f950f63f6fdafa3cfd4bca18d028271
PR Gates / Docs update reminder (pull_request) Successful in 22s
Build ErsatzTV Image / Delimiter ban (release path) (pull_request) Successful in 38s
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 12s
PR Gates / Fix proofs (Proves trailers) (pull_request) Successful in 12s
PR Gates / decisions lifecycle (pull_request) Successful in 30s
Review verdict / Set review-verdict status (pull_request_target) Successful in 36s
PR Gates / Script lint and tests (ruff + pytest) (pull_request) Successful in 4m28s
review-verdict/h10 Review-verdict: MERGEABLE @ eda2fac (base: main)
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 8m33s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 6m7s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Skipped
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (pull_request) Successful in 5m46s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 9s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 6s
#780 and #784 were green separately and red together: the gate landed with a base that predated `scripts/check-doc-narrative.py`, so nothing ever ran ruff over it. On merged main the shipped invocation is RED, which would have surfaced as a mystery lint failure on whichever PR opened next. Two findings, both in #784's files: - `RUF100` on `# noqa: BLE001` twice — `BLE` is not in this repo's `select`, so those directives suppress nothing. Enabling `BLE` instead was measured and rejected: it fires 6 more times in `decisions_validate.py`, whose broad catches are deliberate, and that is a ruleset decision for its own PR rather than a side effect of unbreaking main. The non-enabled code is dropped; the `S110` on the first site stays (S IS selected), and both explanatory comments stay. - `scripts/tests/test_check_doc_narrative.py` was not ruff-formatted. Formatted; suite still 807 passed, 2 skipped. The general shape, for the next time two PRs touch disjoint files: a gate whose population is "everything tracked" is only as green as its base. #813's CI could not have caught this and neither could #811's. Refs: #780, #784
fix(754,757): declare graphicsElementIds + padToNearestMinute, and pin every MCP tool to its OpenAPI contract (#760)
fix(754,757): declare graphicsElementIds + padToNearestMinute, and pin every MCP tool to its OpenAPI contract (#760)
feat(779): test the deny path at the production config value, and derive full-replace field lists (#808)
ErsatzTV
ErsatzTV lets you transform your media library into a personalized, live TV experience - complete with EPG, channel scheduling, and seamless streaming to all your devices. Rediscover your content, your way.
How It Works
- Install ErsatzTV: Download and set up the server on your system.
- Add Your Media: Connect your media libraries and collections.
- Create Channels: Design and schedule your own live channels.
- Stream Anywhere: Watch on any device with IPTV and EPG support.
Key Features
- Custom channels: Create and schedule your own live TV channels.
- IPTV & EPG: Stream with IPTV and Electronic Program Guide support.
- Hardware Transcoding: High-performance streaming with hardware acceleration (NVENC, QSV, VAAPI, AMF, VideoToolbox)
- Media Server Integration: Connect Plex, Jellyfin, Emby and more.
- Music & Subtitles: Mix music videos and enjoy subtitle support.
- Open Source: Free, open, and community-driven project.
Documentation
Documentation is available at ersatztv.org.
License
This project is inspired by pseudotv-plex and the dizquetv fork and is released under the zlib license.
