Skip to content

fix(encode): trimmed multi-wave ladders die on an empty filter graph - #236

Merged
johan-bell merged 1 commit into
mainfrom
fix-trim-multiwave-filter
Sep 4, 2026
Merged

fix(encode): trimmed multi-wave ladders die on an empty filter graph#236
johan-bell merged 1 commit into
mainfrom
fix-trim-multiwave-filter

Conversation

@johan-bell

Copy link
Copy Markdown
Collaborator

A trimmed encode of more than three re-encoded rungs fails every time, on its second wave, with:

[AVFilterGraph @ 0x...] No filters specified in the graph description
FFmpeg exited with code 234

Why

buildVideoArgs empties the audio groups for every wave after the first — audio rides with wave 1, by design:

const audioGroups = wave && !wave.includeAudio ? [] : encodeConfig.audioGroups!;

Everything downstream already respects that. The -map [aoutN] loop doesn't run, no audio codec options are emitted, and -var_stream_map gets no a:N entries — buildVideoArgs even carries a comment explaining that a wave without audio names an agroup that isn't in the run, and that the merge restores the AUDIO attribute afterwards.

The one thing that didn't respect it was the trim filter graph, which was pushed whenever trimming was set. Built from no groups it came out as the empty string, and ffmpeg refuses an empty graph.

Why dropping the argument is the fix

The graph exists solely to produce [aoutN] labels for -map [aoutN] to consume. A wave without audio maps none, so there is no consumer: an empty graph is a parse error, and a populated one would be worse — a -filter_complex output that nothing maps is itself an ffmpeg error. The argument is meaningless without the maps it feeds, so the correct amount of it is none.

The video side is untouched: each wave's own select=concatdec_select still rides in the video graph, so wave 2's video is cut sample-accurately exactly as before. Audio keeps being written once, by wave 1.

The same guard is applied in buildAudioArgs, where it is unreachable today — the controller requires at least one audio group for an audio job, and audio jobs do not run in waves — but the code is identical and shouldn't rely on a guarantee made in another file.

Reproduced

Two real sessions from the same machine, differing in one field:

Session trimSegments re-encoded rungs Result
Test english Video Encoder 2 6 failed, exit 234
Worrying about everything… 0 6 completed

Both split into two waves (MAX_HARDWARE_SESSIONS = 3), both have four audio groups. Only the trimmed one hits the empty graph.

Why the suite missed it

ladder-waves.spec.ts covers includeAudio, ffmpeg.service.spec.ts covers trimSegments, and nothing covered them together — which is the only combination that breaks. The new tests drive the real planLadderWaves output rather than a hand-written wave, and assert on the wave the planner actually produces: no empty argv entry, one filter graph rather than two, no [aout labels — plus one test holding the first wave unchanged, so the guard can't quietly swallow the audio graph everywhere.

… wave

Audio rides with the first wave of a split ladder, so later waves have no
audio groups — they map no audio and name none in var_stream_map. The trim
filter graph was built and pushed anyway, and from no groups it came out
empty, which ffmpeg refuses:

  [AVFilterGraph] No filters specified in the graph description
  FFmpeg exited with code 234

So every trimmed encode of more than MAX_HARDWARE_SESSIONS re-encoded
rungs failed on its second wave. The graph exists to feed `-map [aoutN]`;
a wave that maps no audio has no consumer for it, so none is emitted.

The video graph keeps its own select=concatdec_select per wave, so the
trim stays sample-accurate.
@johan-bell
johan-bell merged commit 62522e5 into main Sep 4, 2026
9 checks passed
@johan-bell
johan-bell deleted the fix-trim-multiwave-filter branch September 4, 2026 11:30
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