Plugin: static FFmpeg on Windows/macOS so OBS updates can't break loading - #94
Merged
Merged
Conversation
…ding Windows/macOS builds linked the FFmpeg from the hand-pinned obs-deps bundle, and FFmpeg library names are major-versioned (avcodec-61.dll, libavcodec.61.dylib) — so the moment an OBS update ships a newer FFmpeg the plugin stops loading. OBS 32.2.1 users hit exactly that as LoadLibrary error 126 (#91, #93); Linux hit the same class in #65 and already linked a minimal static FFmpeg. - New .github/actions/static-ffmpeg composite action builds a minimal decode-only static FFmpeg per platform (H.264/HEVC decode plus VAAPI / D3D11VA+DXVA2 / VideoToolbox), cached between runs. All six plugin jobs (PR CI and release) link it, so PRs exercise exactly what releases ship, and one plugin release keeps working across OBS updates. - "Verify FFmpeg linked statically" steps (dumpbin /dependents, otool -L, readelf -d) fail any build whose module regains an avcodec/avutil runtime dependency. Also fixes the existing Linux guard: its `! grep` line was non-fatal under the runner's bash -e, so it could never actually fail the step. - CMakeLists: link bcrypt/ole32/user32 (Windows) and the CoreFoundation/CoreMedia/VideoToolbox frameworks (macOS) that the static FFmpeg's RNG, DXVA2 setup and VideoToolbox hwaccel resolve against; no-ops for shared-FFmpeg local builds. - OBS_REF/DEPS_TAG now pin only libobs and Qt6, whose library names and ABI stay stable across OBS releases — they no longer need to track the FFmpeg inside whatever OBS version users run. Fixes #91 Fixes #93 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AeWct1Rvpqi4ptgogiwsCL
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
Fixes #91
Fixes #93
Both issues are the same failure:
LoadLibrary failed for 'lenslink.dll' … error 126on OBS 32.2.1. The Windows (and macOS) builds linked the FFmpeg from the obs-deps bundle pinned at build time, and FFmpeg library names are major-versioned (avcodec-61.dll,libavcodec.61.dylib) — so the moment an OBS update ships a newer FFmpeg, the plugin's imports no longer resolve and it stops loading. Error 126 nameslenslink.dllbut the missing module is actually the transitive FFmpeg DLL. Linux hit the same class in #65 and already links a minimal static FFmpeg; this PR ports that fix so one plugin release keeps working across OBS updates instead of needing a rebuild per OBS FFmpeg bump..github/actions/static-ffmpegcomposite action builds a minimal decode-only static FFmpeg per platform — H.264/HEVC decode plus the platform's GPU decode API (VAAPI / D3D11VA+DXVA2 / VideoToolbox), cached between runs. All six plugin jobs (PR CI and release, three OSes) link it, so PR CI exercises exactly what releases ship.dumpbin /dependents,otool -L,readelf -d) fail any build whose module regains an avcodec/avutil runtime dependency. This also fixes the existing Linux guard: its! grepline was non-fatal under the runner'sbash -e(a!-negated command that isn't last never fails the step), so it could never actually catch a regression.CMakeLists.txtlinks the system pieces the static FFmpeg resolves against —bcrypt/ole32/user32on Windows, CoreFoundation/CoreMedia/VideoToolbox frameworks on macOS; no-ops for local shared-FFmpeg builds, which are unchanged.OBS_REF/DEPS_TAGnow pin only libobs and Qt6, whose library names and ABI stay stable across OBS releases — they no longer have to track the FFmpeg inside whatever OBS version users run.Merging auto-cuts the patch release whose Windows build resolves the two reports.
How it was tested
Build/CI change — no live-stream behavior touched (the decoder code is unchanged; it's the same FFmpeg sources now linked statically, as Linux releases already ship). Verified in the Linux container: built the action's exact static FFmpeg 7.1 and linked the plugin with the release flags —
-Wall -Wextra -Werrorclean, frontend UI enabled,readelfshows nolibavcodec/libavutilNEEDED entries with libva still linked, ~1,500 decoder symbols embedded and none dynamically exported (3.4 MB module). The regular shared-FFmpeg dev build also stays clean.actionlintpasses on both workflows. The Windows (MSVC-toolchain FFmpeg under MSYS2) and macOS (universal + lipo) paths can only compile on this PR's CI — that run is the real test for them.🤖 Generated with Claude Code
https://claude.ai/code/session_01AeWct1Rvpqi4ptgogiwsCL
Generated by Claude Code