Skip to content

fix(coordinator): restart the whole transcoder subprocess on any config change#34

Merged
ntt0601zcoder merged 1 commit into
mainfrom
fix/transcoder-live-reconfig
Jun 18, 2026
Merged

fix(coordinator): restart the whole transcoder subprocess on any config change#34
ntt0601zcoder merged 1 commit into
mainfrom
fix/transcoder-live-reconfig

Conversation

@ntt0601zcoder

Copy link
Copy Markdown
Owner

Summary

Changing a transcoder config on a running stream (audio sample-rate/bitrate, global GOP/fps, decoder, or a per-profile video update / add / remove) failed with HTTP 500coordinator: reload profiles: ... per-profile start is not supported; the subprocess owns all renditions. Only a full stream restart applied the change.

Root cause

The native transcoder runs one subprocess that owns every rendition (a single decode fans out to all encoders) — there is no per-profile lifecycle. But Coordinator.Update routed any non-topology transcoder change through a per-profile reload that called StartProfile / StopProfile, which the subprocess rejects with ErrNotImplemented. The package doc already stated the intended behaviour ("a ladder change restarts the whole subprocess"), but the wiring contradicted it.

Fix

  • Route any transcoder change that needs the subprocess to reloadTranscoderFull (rebuilds buffers + transcoder + publisher + DVR), the documented path. Inputs are applied before the reload so a combined input+transcoder change is not skipped.
  • Retire the dead per-profile API: reloadProfiles, abrMetaFromUpdated, reloadDVRIfBufferChanged, and transcoder.StartProfile / StopProfile / ErrNotImplemented.

Tests

  • Rewrote the 3 per-profile update tests to the full-reload contract.
  • Added TestUpdate_AudioChanged_FullReload (regression for the reported bug).
  • go build, go vet, gofumpt, golangci-lint run ./... → clean; go test ./... passes (only the pre-existing MediaMTX docker integration test is unrelated/flaky).

Trade-off

A transcoder config change is now a clean full reload (brief output re-init for all protocols) instead of the impossible per-profile reload — the same effect as POST /streams/{code}/restart. A lighter subprocess-only restart is possible later but has init-segment/discontinuity subtleties.

…ig change

The native transcoder subprocess owns every rendition — there is no
per-profile lifecycle. But Update routed non-topology transcoder changes
(audio, global, decoder, or a per-profile video update / add / remove)
through a per-profile reload that called StartProfile / StopProfile, which
the subprocess rejects. Every such live update failed with a 500
("per-profile start is not supported"); only a full stream restart applied
the change.

Route any transcoder change that needs the subprocess to the full reload
(reloadTranscoderFull) — the path the package already documented — and
retire the dead per-profile API (reloadProfiles, StartProfile / StopProfile,
ErrNotImplemented). Inputs are now applied before the reload so a combined
input+transcoder change is not skipped. Tests updated to the full-reload
contract, with an audio-change regression added.
@ntt0601zcoder ntt0601zcoder merged commit 3f5a89a into main Jun 18, 2026
4 checks passed
@ntt0601zcoder ntt0601zcoder deleted the fix/transcoder-live-reconfig branch June 18, 2026 06:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant