Skip to content

fix(win): ship the compositor addon beside its ffmpeg DLLs - #303

Merged
EtienneLescot merged 1 commit into
mainfrom
fix/win-compositor-dll-colocation
Aug 8, 2026
Merged

fix(win): ship the compositor addon beside its ffmpeg DLLs#303
EtienneLescot merged 1 commit into
mainfrom
fix/win-compositor-dll-colocation

Conversation

@EtienneLescot

@EtienneLescotEtienneLescot commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator

Fixes the Store build of 1.9.0, which is live and broken: the editor opens with a permanently blank preview while audio keeps playing. The NSIS build of the same commit is fine.

Why the symptom points at exactly one thing

Audio comes from the renderer; every preview frame comes from the native compositor addon. Sound with no picture is what an addon that failed to load produces — CompositorViewService falls back to a silent no-op, which the code's own comment describes as "the editor silently ran without a compositor".

Root cause

The addon dlopens avcodec/avformat/avutil at require() time. It shipped from app.asar.unpacked/electron/native/compositor-view/build/, one directory away from electron/native/bin/win32-x64/*.dll, and the gap was bridged at runtime by ensureFfmpegSharedDllsOnPath prepending the DLL directory to PATH.

That works for NSIS. It does not work under MSIX, which resolves an addon's dependent DLLs through the package graph and ignores PATH.

Measured, not inferred

I registered the shipped 1.9.0 appx as a loose package (Add-AppxPackage -Register, real package identity) and ran the loader's own logic inside it via Invoke-CommandInDesktopPackage:

resourcesPath : …\app\resources ← correct
dllDir existsSync : true ← the probe finds it
avcodec existsSync : true
addon existsSync : true
require BEFORE PATH : FAILED: The specified module could not be found.
require AFTER PATH : FAILED: The specified module could not be found. ← PATH set, still fails

That rules out the alternative explanation — it is not a wrong path, not a missing file, not an ACL problem. PATH is correctly set and simply not consulted.

Then, with the DLLs copied beside the addon in the same package, nothing else changed:

require BEFORE PATH : LOADED OK ← loads with no PATH at all

The fix

Ship the addon from electron/native/bin/win32-x64/, beside the DLLs, via extraResources — and stop routing it through files into the asar.

Node loads .node files with LOAD_WITH_ALTERED_SEARCH_PATH, so the addon's own directory is searched for its dependencies. This removes the PATH mechanism rather than repairing it, and works on every Windows packaging format.

macOS has always done this (build-macos-compositor-addon.mjs installs into bin/darwin-<arch>/ and vendors its dylibs there). Windows was the outlier.

No loader change is needed: buildCandidatePaths already probes bin/<tag>/compositor_view.node first.

Regression guard

before-pack.cjs now refuses to package unless the addon and each of avcodec, avformat, avutil are in that directory — on Windows as it already did on macOS and Linux.

One requirement per library rather than a count over a combined regex. That is the trap LINUX_REQUIRED already documents: three copies of avcodec-60/61/62.dll left by an earlier fetch would satisfy atLeast: 3 while avformat and avutil were missing. Verified it catches exactly that case:

=== 3 copies of avcodec, nothing else:
Missing:
- the avformat DLL the compositor links
- the avutil DLL the compositor links

All four paths exercised: missing directory, missing addon, missing DLLs, complete payload. compositorViewService tests still green (21).

Testing before the Store update

The loose-registration route above reproduces the failure and will verify the fix on a real MSIX identity, without signing or a Store submission — so the 1.9.1 package can be validated locally before it goes anywhere near Partner Center.

Summary by CodeRabbit

  • Bug Fixes

    • Improved Windows packaging so the compositor addon and required media libraries are bundled together, preventing loading failures in packaged formats.
    • Added validation to ensure required Windows native components are present and up to date.
  • Documentation

    • Updated build and packaging guidance for native compositor components on Windows and macOS.

The 1.9.0 Store build loads no compositor at all: the editor opens with a
permanently blank preview while audio keeps playing. Audio comes from the
renderer, every frame comes from the addon, so the symptom is exactly what an
addon that failed to load produces — the service falls back to a silent no-op.
The addon dlopens avcodec/avformat/avutil at require() time. It shipped from
app.asar.unpacked, one directory away from electron/native/bin/win32-x64/*.dll,
and the gap was bridged at runtime by ensureFfmpegSharedDllsOnPath prepending
the DLL directory to PATH. That works for NSIS and does not work under MSIX,
which resolves an addon's dependent DLLs through the package graph and ignores
PATH. Measured inside a registered package, with the directory verifiably
present and correctly prepended:
dllDir existsSync : true
require BEFORE PATH : FAILED: The specified module could not be found.
require AFTER PATH : FAILED: The specified module could not be found.
and with the addon beside those same DLLs, no PATH involved:
require BEFORE PATH : LOADED OK
Node loads .node files with LOAD_WITH_ALTERED_SEARCH_PATH, so the addon's own
directory is searched for its dependencies. Colocating removes the PATH
mechanism rather than repairing it, and works on every Windows packaging
format. macOS has always done this; Windows was the outlier.
No loader change: buildCandidatePaths already probes bin/<tag> first.
before-pack now refuses to package unless the addon and each of avcodec,
avformat and avutil are in that directory, on Windows as it already did on
macOS and Linux. One requirement per library rather than a count over a
combined regex — the trap LINUX_REQUIRED already documents, where several
versioned copies of one library satisfy the count while another is missing.
@coderabbitai

coderabbitaiBot commented Aug 8, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Windows packaging now places compositor_view.node beside its FFmpeg DLLs through extraResources. Build and diagnostic scripts validate the colocated payload and addon freshness. Documentation records the required layout and MSIX loading behavior.

Changes

Windows native payload packaging

Layer / File(s)Summary
Native payload layout
scripts/build-windows-compositor-addon.mjs, electron-builder.json5, technical-documentation/engineering/build-and-packaging.md
The build script copies compositor_view.node beside the Windows FFmpeg DLLs. Windows packaging uses extraResources for the colocated payload. Documentation describes the layout and MSIX loading behavior.
Packaging-time payload validation
scripts/before-pack.cjs
Windows packaging and standalone diagnostics verify the compositor addon, required FFmpeg DLLs, and addon freshness in electron/native/bin/win32-x64.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
participant BuildScript as build-windows-compositor-addon.mjs
participant NativeDir as electron/native/bin/win32-x64
participant ElectronBuilder as electron-builder
participant BeforePack as scripts/before-pack.cjs
BuildScript->>NativeDir: Copy compositor_view.node beside FFmpeg DLLs
ElectronBuilder->>NativeDir: Package colocated payload through extraResources
BeforePack->>NativeDir: Validate addon and required FFmpeg DLLs
BeforePack->>BeforePack: Check addon freshness and report result
Loading

Possibly related PRs

Suggested reviewers:claude

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check nameStatusExplanation
Title check✅ PassedThe title clearly summarizes the primary Windows packaging fix: shipping the compositor addon beside its FFmpeg DLLs.
Description check✅ PassedThe description clearly explains the issue, root cause, fix, regression guard, and testing, but omits several template headings and checkbox metadata.
Docstring Coverage✅ PassedNo functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/win-compositor-dll-colocation

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@technical-documentation/engineering/build-and-packaging.md`:
- Around line 49-57: Add the text language identifier to both diagnostic
Markdown code fences in the documentation, including the fence containing the
dllDir/require output and the subsequent fence containing the LOADED OK output;
leave their contents unchanged.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 18555bd7-279f-4f6e-aada-af3c7ac7a3db

📥 Commits

Reviewing files that changed from the base of the PR and between aacdefb and 84c3430.

📒 Files selected for processing (4)
  • electron-builder.json5
  • scripts/before-pack.cjs
  • scripts/build-windows-compositor-addon.mjs
  • technical-documentation/engineering/build-and-packaging.md

Comment on lines +49 to +57
```
dllDir existsSync : true
require BEFORE PATH : FAILED: The specified module could not be found.
require AFTER PATH : FAILED: The specified module could not be found.
```

and with the addon sitting beside those same DLLs, no `PATH` involved:

```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Specify a language for both diagnostic code fences.

The configured markdown linter reports MD040 for lines 49 and 57. Add text to both opening fences.

Proposed fix
-```+```text
dllDir existsSync : true
require BEFORE PATH : FAILED: The specified module could not be found.
require AFTER PATH : FAILED: The specified module could not be found.

and with the addon sitting beside those same DLLs, no PATH involved:

- +text
require BEFORE PATH : LOADED OK

</details>
<!-- suggestion_start -->
<details>
<summary>📝 Committable suggestion</summary>
> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
```suggestion
🧰 Tools
🪛 markdownlint-cli2 (0.23.2)

[warning] 49-49: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 57-57: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@technical-documentation/engineering/build-and-packaging.md` around lines 49 -
57, Add the text language identifier to both diagnostic Markdown code fences in
the documentation, including the fence containing the dllDir/require output and
the subsequent fence containing the LOADED OK output; leave their contents
unchanged.

Source: Linters/SAST tools

@EtienneLescot
EtienneLescot merged commit 4e7a85b into mainAug 8, 2026
17 checks passed
@EtienneLescot
EtienneLescot deleted the fix/win-compositor-dll-colocation branch August 8, 2026 12:13
Sign up for freeto 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

@EtienneLescot