Skip to content

fix(ffmpeg): point macOS at evermeet's ffprobe archive, not its ffmpeg one - #786

Open
m4bard wants to merge 1 commit into
Listenarrs:canaryfrom
m4bard:fix/777-macos-ffprobe-url
Open

fix(ffmpeg): point macOS at evermeet's ffprobe archive, not its ffmpeg one#786
m4bard wants to merge 1 commit into
Listenarrs:canaryfrom
m4bard:fix/777-macos-ffprobe-url

Conversation

@m4bard

@m4bard m4bard commented Jul 30, 2026

Copy link
Copy Markdown

Summary

Fixes #777. The bundled ffprobe install can never succeed on macOS. The platform default points at evermeet's ffmpeg archive, and evermeet ships one binary per archive, so the download succeeds and the extractor then finds no ffprobe entry to install. Metadata import stays broken on every Mac.

evermeet publishes ffprobe as its own archive at the same version, so pointing macOS there fixes the install without touching any other platform.

Changes

Fixed

  • macOS now downloads https://evermeet.cx/ffmpeg/ffprobe-6.0.zip rather than ffmpeg-6.0.zip. The version is the same, so this changes which artifact is fetched and nothing about how it is handled.

Added

  • An internal GetDownloadUrl(OSPlatform, Architecture) overload, so the mapping for every platform can be asserted from a test host running on any one of them. The public no-argument method behaves as it did and now delegates to it.
  • FfprobePlatformDefaultsTests, covering the macOS regression and two invariants that hold for every platform.

Testing

Checked against the live archives before changing anything:

$ curl -sSL https://evermeet.cx/ffmpeg/ffmpeg-6.0.zip -o ffmpeg-6.0.zip   # what macOS fetches today
$ unzip -l ffmpeg-6.0.zip
 78829164  2023-02-27 21:33   ffmpeg          <- one entry, no ffprobe

$ curl -sSL https://evermeet.cx/ffmpeg/ffprobe-6.0.zip -o ffprobe-6.0.zip
$ unzip -l ffprobe-6.0.zip
 78744828  2023-02-27 21:33   ffprobe

$ file ffprobe
ffprobe: Mach-O 64-bit x86_64 executable

x86_64 is the right architecture to want here, since the project publishes osx-x64 only. On macOS it is therefore always an x64 process, running natively on Intel and under Rosetta on Apple Silicon.

12 new unit tests. The full backend suite passes locally on .NET 10, 1201 tests.

Two of the new tests assert invariants rather than a specific string, because a URL constant by itself is not worth a test:

  • the filename has to name ffprobe on macOS, which is the regression fixed here.
  • the URL has to end in a suffix the extractor dispatches on. FfprobeArchiveExtractor picks zip or tar handling from the URL suffix, so a URL outside .zip, .tar.xz, .tar.gz and .tgz downloads cleanly and then extracts nothing. That is worth guarding for this fix specifically. evermeet has a getrelease/ffprobe/zip endpoint that redirects to the current release, which looks like the tidier thing to point at and would fail quietly, because the URL ends in /zip. Naming the file avoids it.

Notes

This is the narrow fix. Two related things I left out rather than fold in.

macOS stays on ffprobe 6.0. evermeet's current release is 8.1.2 and there is a versioned .zip URL for it, but I cannot execute a Mach-O binary on the Linux machine I tested from, so I cannot show that a version bump leaves the fields FfprobeMetadataMapper reads unchanged. That wants its own change and its own evidence.

GetChecksum() still returns null, so this download stays unverified, as the Linux and Windows ones are. That is the wider half of #777: the platform defaults are unpinned and unverified, and macOS is where it happens to be fatal rather than merely risky. The durable answer is the second option in that issue, switching the defaults to the github: provider path with a pinned release and a checksum, which covers all three platforms at once. FfmpegService already has that machinery, including Provider, ReleaseOverride, Arch, ChecksumUrl, FfprobeGithubAssetDiscoverer and abort-on-mismatch, so what is left is choosing a source to pin to and deciding whether you want that behaviour change for existing Linux and Windows users. I am happy to build it if you do.

One thing worth knowing in the meantime: the github: provider is not gated on the platform default being null and overrides it whenever discovery succeeds. A Mac user can unblock themselves today by setting Ffmpeg.Provider, without waiting for a release.

…g one

The bundled ffprobe install can never succeed on macOS. FfprobePlatformDefaults
returns evermeet's ffmpeg archive, and evermeet ships one binary per archive, so
the download succeeds and FfprobeArchiveExtractor then finds no ffprobe entry to
install. Metadata import is broken on every Mac as a result.

evermeet publishes ffprobe as its own archive at the same version, so this points
macOS at ffprobe-6.0.zip instead of ffmpeg-6.0.zip. Same version, same host, same
extraction path; only the artifact changes.

Verified against the live archives: ffmpeg-6.0.zip holds a single entry, ffmpeg,
with no ffprobe anywhere in it, while ffprobe-6.0.zip holds a single ffprobe that
file reports as a Mach-O 64-bit x86_64 executable. x86_64 is what is wanted here,
since the project publishes osx-x64 only and is therefore always an x64 process on
macOS, natively on Intel and under Rosetta on Apple Silicon.

Adds an internal GetDownloadUrl(OSPlatform, Architecture) overload so the mapping
for every platform can be asserted from a test host on any one of them, and tests
covering the macOS regression plus two invariants that hold everywhere: the macOS
filename has to name ffprobe, and every URL has to end in a suffix the extractor
dispatches on. The second one matters because evermeet's getrelease endpoint
redirects to the current release and ends in /zip, so it looks like the tidier
target and would extract nothing.

macOS stays on 6.0 and GetChecksum() still returns null. Both are deliberate: a
version bump needs evidence I cannot produce without a Mac, and pinning with
checksums is the wider half of Listenarrs#777 and applies to all three platforms.

Refs Listenarrs#777
@m4bard

m4bard commented Jul 31, 2026

Copy link
Copy Markdown
Author

Ran this on an actual Mac rather than inferring it from the archive contents, since "the binary is the right architecture" and "the binary runs and produces the fields we read" are different claims and only the second one matters here.

Apple Silicon, macOS 26.6. That is the interesting case: the project ships osx-x64 only, so on M-series hardware this is an x64 process under Rosetta, which is how most Macs will hit it.

The two archives, fetched fresh:

ffmpeg-6.0.zip (current default) ffprobe-6.0.zip (this PR)
entries ffmpeg ffprobe
ffprobe present 0 1
bytes 24,461,336 24,414,249
sha256 9a810d22…addacc aefcbe2c…6b9926

The extracted binary reports as Mach-O 64-bit executable x86_64, lipo -archs agrees, and it runs:

ffprobe version 6.0-tessus  https://evermeet.cx/ffmpeg/

Then the command the service issues, against a one-second tagged m4b:

ffprobe -v quiet -print_format json -show_format -show_streams
format_name   mov,mp4,m4a,...      codec_name    aac
duration      1.000000             sample_rate   22050
bit_rate      818                  channels      1
title         "A Test Book"        artist        "A Test Author"

Every field FfprobeMetadataMapper reads comes back populated, on the platform where metadata import is currently broken.

Two details worth recording. The test file was built with the ffmpeg binary out of the current archive, so that download is not useless, it is simply the wrong one for a service that only ever wants ffprobe. And the extracted binary needed xattr -d com.apple.quarantine before it would run, which is Gatekeeper behaviour for anything unzipped from a download rather than anything specific to this archive. Worth knowing if the install path ever grows a smoke test that tries to execute what it just fetched.

One thing this does raise, though it is not a reason to change anything here. evermeet publishes x86_64 only, so both the current default and this PR put a translated binary on Apple Silicon. The durable-source option from #777 would additionally fix that: jellyfin-ffmpeg's current release carries portable_mac64-gpl.tar.xz and portable_macarm64-gpl.tar.xz side by side, so macOS could run a native ffprobe instead of one under Rosetta.

There is a wrinkle if anyone picks that up. RuntimeInformation.OSArchitecture reports X64 inside a translated process, so an architecture branch cannot tell an Intel Mac from an Apple Silicon one running the osx-x64 build. Distinguishing them needs sysctl.proc_translated. FfprobePlatformDefaults already branches on architecture for Linux and not for macOS, so the machinery is half there, and this PR deliberately leaves that alone.

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.

macOS: ffprobe never installs — metadata import broken on every Mac

1 participant