Commit Graph
8 Commits
Author SHA1 Message Date
rootandClaude Opus 4.8 73f85d48a0 feat(fanout): toggle the daemon's debug narration from the panel
FanoutConfig::desired maps a new fanout_debug setting to the daemon's debug_cats
config key: "" (off, the default), "all", or a comma-separated category list
kept to the daemon's known categories (unknown names dropped, so a typo turns
debug off rather than writing a file the daemon second-guesses). The daemon
applies it on its next config poll, so an operator can turn debug on for a
misbehaving node and off again without a restart that would drop every viewer.

The PHPUnit suite could not be run here — no PHP on this box has the
dom/mbstring/xml/xmlwriter extensions phpunit.phar needs — so the three tests
added to FanoutConfigTest are unrun; the debugCats() mapping was instead
verified directly by reflection (off/all/list/unknown all map as asserted).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-18 07:40:43 +00:00
rootandClaude Opus 5 c0db42b7c4 fix(fanout): size the daemon's ring from what it must hold, with no fixed 40 s floor
The panel wrote prebuffer_max_sec = max(40, client_prebuffer,
restreamer_prebuffer, hls_window x seg_time). The ring is the daemon's
memory, and the flat 40 kept every watched channel at 40 s however far the
operator lowered Client Prebuffer or the HLS window: no panel setting could
shrink it, and a hand edit of config.json is overwritten by the next sync.

The ring now covers the HLS window and every prebuffer a viewer can ask for
(client, restreamer, the daemon default), each with one segment of headroom
on top — a join asking for as much as the ring holds starts in the block the
next keyframe prunes, and a viewer slower than one GOP there is dropped. It is
never under two segments, and still capped at the daemon's 120. At the
defaults (30 s prebuffer, 6 x 6 s HLS) that is 36 s instead of 40; with a
10 s prebuffer and a 3-segment window it is 18 s.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BbYsGKhirq9eRK8e6wsCHR
2026-09-13 08:40:38 +00:00
rootandClaude Opus 5 0603e5d2ab feat(fanout): add the fanout_supervise setting
Whether live streams on each server are handed to the xc_fanout daemon's
encoder supervisor instead of getting a per-stream PHP watchdog
(console.php monitor). On by default: the supervisor does everything the
PHP monitor did, from one process per node instead of one per channel,
and the PHP monitor stays the fallback for a daemon that cannot be
reached.

Touches the places every fanout_* setting lives: migration 018 for
upgrades, database.sql for fresh installs (277/277 columns and values
still aligned), the FanoutConfig mapping that writes `supervise` into the
daemon's config.json (applied live by the daemon, no restart), the
settings UI, the checkbox whitelist in SettingsService, all seven language
files, and the unit test. The source-backend tooltip now says what the
backend means for the panel's own streams as well.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012QL93N6dzGkmKoQgA4oh16
2026-09-11 09:20:03 +00:00
rootandClaude Opus 5 589f4f7ee2 Revert PR #1 (feat/daemon-monitor): panel-side encoder supervision
Reverts the five commits PR #1 brought in and the two test follow-ups made
after it merged:

  a1d454fe Enhance assertions in FanoutConfigTest
  19607a91 Update StreamProcessBuildLiveTest.php
  b3714269 fix(fanout): stop, force and rogue-kill must account for the daemon
  cea545fe feat(fanout): reconcile supervised streams back into the panel
  8e24a242 feat(fanout): make encoder supervision a real, settable option
  8244ece1 feat(fanout): health policy, source forcing and supervision reconcile
  56c0619e feat(fanout): hand live encoders to the daemon to supervise

Only those. The upstream commits that reached main through the same merge
(the GeoIP refactor, release 2.5.0, the update guard, the mass-page fix)
stay: reverting the merge commit itself would have taken them out too.

The panel side of supervision is re-done in the commits that follow,
together with the xc_fanout native remuxer (xc_fanout 0.13.0): every live
stream handed to the daemon's monitor, copy-only streams run on
`xc_fanout remux` instead of ffmpeg, the ffmpeg command as an explicit
fallback.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012QL93N6dzGkmKoQgA4oh16
2026-09-11 09:19:54 +00:00
obscuremindandGitHub a1d454fefe Enhance assertions in FanoutConfigTest
Updated assertions in testSuperviseDefaultsOff to include messages for clarity.
2026-09-10 22:15:15 +01:00
obscuremindandClaude Opus 5 8e24a2427a feat(fanout): make encoder supervision a real, settable option
Production-readiness pass on the panel side of daemon encoder supervision.

Until now the feature was gated on a setting that did not exist as a
column, so it could only be enabled by hand-editing the database and the
daemon never learned about it at all.

* Migration 018 adds `fanout_supervise`, off for every existing install.
* Admin -> Settings gains the toggle, alongside the other fanout tuning.
* SettingsService saves it (it is a checkbox, so it has to be in the
  boolean list or it can never be turned back off).
* FanoutConfig writes it into the daemon's config file as `supervise`,
  which is how the node learns it may supervise at all. Both halves must
  be on for anything to change, and either one off is a full rollback.
* StreamProcess reads `fanout_supervise` rather than the placeholder
  name, matching the panel's `fanout_*` convention.

Also: the recorded command file now says WHO ran the stream. `_.fanout`
when the daemon owns the process (the bare command it was handed) and
`_.ffmpeg` when this node ran it itself (with the redirect-and-background
tail). Two names rather than one because the first question in any
incident is which path the stream took, and a single filename cannot
answer it; the stale one is removed so a stream that switched paths does
not leave a lie behind.

FanoutConfigTest covers the new key both ways, including that a settings
array predating it reads as off -- that absence is the upgrade path for
every existing install.

Verified: php -l clean on every changed file.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-10 21:34:50 +01:00
rootandClaude Opus 5 553aed89ff feat(fanout): expose the daemon's source backend as a panel setting
xc_fanout 0.12.0 can convert a non-mp2t source to MPEG-TS in-process instead of
spawning an ffmpeg child per stream. For the common IPTV case — HLS whose
segments are already MPEG-TS — that child was doing little more than
concatenating bytes the daemon can concatenate itself, at ~27 MB RSS apiece,
plus a process spawn and a probe window on every on-demand join and reconnect.

The daemon reads which path to take from `source_backend` in its config.json;
this adds the panel setting that writes it.

  auto (default) — convert natively where the daemon's reader can, ffmpeg for
                   everything it declines
  ffmpeg         — always spawn ffmpeg; the pre-0.12 behaviour and the
                   kill-switch if a native pull ever misbehaves
  native         — native only, no fallback. Diagnostic: it answers "what is
                   actually eligible on this node", and a declined source there
                   is a dead channel rather than a slightly more expensive one.

auto is the default because the fallback makes it strictly safer than
ffmpeg-always: anything the native reader will not take (fMP4/CMAF HLS, RTMP,
SRT, RTSP, AES-128 encrypted sources, anything it cannot positively identify)
runs exactly the pipeline it ran before.

A `<select>`, not a numeric input, so it is deliberately kept out of the
numeric-coercion list in settings.php that would otherwise mangle the string.
An unrecognised value maps to auto rather than being written through — the
daemon clamps unknown values itself, but a config file we write should not carry
a backend that does not exist, and a typo must never take channels off air.

Touches the six places every fanout_* setting lives: migration 017 for upgrades,
database.sql for fresh installs (column, INSERT list and VALUES — 276/276 still
aligned), the FanoutConfig mapping, the settings UI, all seven language files,
and the unit test. SettingsService needs no change: its whitelist is only for
checkboxes, and verifyPostTable already maps a posted field to its column.

Verified against the real daemon end to end: the panel writing "ffmpeg" boots
xc_fanout with backend=ffmpeg, and changing it to "auto" is picked up live on
the next config poll. Read-modify-write still preserves daemon keys the panel
does not manage.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PGCQcWGMg1Wn8RdCxYoioN
2026-09-09 19:39:17 +00:00
Divarion_D 10716fd9ec feat(fanout): expose xc_fanout tuning knobs in settings (DB + UI)
The panel only owned two derived fanout config keys (hls_target_sec ←
seg_time, prebuffer_max_sec derived); the daemon's other tuning knobs lived
only in its config.json and could not be set from the panel. Promote them to
real settings so admins control the whole config — the unconditional
fanout_sync (previous commit) then keeps config.json in step.

Adds 9 settings columns (fanout_hls_window, fanout_grace_sec,
fanout_write_timeout_sec, fanout_chunk_bytes, fanout_max_gop_bytes,
fanout_source_insecure, fanout_default_prebuffer_sec,
fanout_idle_buffer_grace_sec, fanout_idle_buffer_ratio) with defaults and
ranges mirroring the daemon schema (XC_VM_Fanout internal/config/config.go):
migration 014 + install SQL, inputs on the admin Settings page (numeric plus
one switchery checkbox), and the source_insecure toggle in the settings
boolean-normalization list.

FanoutConfig::desired() now writes all 11 keys, clamped to the daemon's own
ranges so a bad panel value can't push it into a pathological state;
hls_window comes from the setting (not the daemon snapshot) and feeds the
prebuffer_max_sec derivation. prebuffer_max_sec / hls_target_sec stay derived.

Adds FanoutConfigTest (mapping, clamps, derived ring, idempotency,
unknown-key preservation). Full suite green.
2026-09-01 16:03:39 +03:00