Skip to content

FFmpeg 8.1 writes only a header for a file destination fed a mid-stream resolution change #398

Description

@rainmanjam

Found by switching the acceptance jobs from Ubuntu's FFmpeg 6.1.1 to the pinned 8.1 build the other CI jobs already use. The switch was reverted from #397; this issue is the finding.

The bisect

Commit acceptance-failover
b02d083 — before the switch success
198b867 — before the switch success
138fe97the switch FAILURE
f681628 — after FAILURE

Two green before, two red after, and nothing else changed in between. Every other suite passed on all four.

The failure

FAIL  the mismatch destination produced 18154ms of media and its file holds 293 bytes
      it WAS being delivered to, so this is not the closed-hub case. A file
      destination truncates and reopens when it restarts -- read the restart
      count above; if that is still 0 the truncation came from outside this step.
the mismatch recording declares:  -- for content that is 1280x720@60 for half its length

Summary
  26 passed, 1 failed

293 bytes is an EBML header and nothing after it. ffprobe reports no stream at all — the trailing declares: line is empty where it should print width,height,r_frame_rate.

The destination in question is the failover suite's mismatch destination: the one deliberately fed content whose parameters change halfway through, 1280x720@60 for half its length. out_time says 18154ms of media was produced, so delivery was happening; the muxer wrote a header and then nothing reached the file.

Why this probably matters to real users

Users run 8.1.2 — the Dockerfile pins FFMPEG_VERSION=8.1.2-r0. CI's 6.1.1 is the version nobody runs, which is exactly why the pin exists elsewhere in ci.yml:

Ubuntu's own package is 6.1.1, and the Docker image ships 8.1.2. Testing against 6.1.1 meant CI never exercised the FFmpeg users actually get, and the two differ in ways that matter.

So the plausible reading is that a file destination fed a mid-stream resolution change produces an empty recording on the FFmpeg version users actually have, and CI has never been able to see it. The pin did what it was added to do on its first run.

The alternative reading is that the suite's expectations are tuned to 6.1.1's tolerance for a parameter change mid-Matroska. Both are worth knowing and neither is established yet.

What has NOT been established

  • Whether 8.1 refuses the parameter change, or accepts it and fails to flush.
  • Whether this reproduces outside CI, on a real failover between mismatched sources.
  • Whether other file destinations are affected, or only the mismatch case.
  • Whether the Docker acceptance suites — which DO run 8.1.2 — already cover this and pass, which would narrow it considerably.

That last one is the cheapest next step.

Also blocked on this

Moving the acceptance jobs to the cached, pinned 8.1 build is worth doing on its own merits and cannot land until this is understood:

  • It removes an uncached third-party fetch that has hit the 6-minute step ceiling four times — acceptance-postprod, acceptance-pull, acceptance-mqtt, acceptance-audio — each stalled mid-acquisition against azure.archive.ubuntu.com. Acquire::Retries=3 was added to bound it and did not, for the reason the unit job already records: "a retry re-asks a host that is refusing. The cache stops asking."
  • The acceptance suites are the ones pushing real multitrack audio end to end, so they are the jobs that most need the version users run.

The reasoning is left at the step in ci.yml so the next person to notice finds out it was tried.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions