Skip to content

fix(export): let an MP4 export be cancelled mid-render - #1044

Merged
EtienneLescot merged 3 commits into
mainfrom
fix/1014-mp4-export-cancel
Oct 6, 2026
Merged

EtienneLescot merged 3 commits into
mainfrom
fix/1014-mp4-export-cancel

Conversation

@EtienneLescot

@EtienneLescot EtienneLescot commented Oct 6, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • MP4 export now honours Cancel like GIF. The native walk checks a shared ExportControl before every frame on Windows, macOS and Linux. The MP4 is staged beside the destination and renamed over it only once complete, so a cancel leaves no partial file and an existing destination untouched.
  • The muxer is torn down by RAII guards on every exit. On Windows it otherwise kept the partial file open and undeletable, and leaked the encoder's surface pool.
  • The addon gains createMp4ExportControl / cancelMp4Export. The main process runs MP4 exports through the per-window export jobs (renamed from the GIF-only registry), and the cancel action is now cancelExport for both formats.
  • An addon built before this change still exports MP4: it refuses the cancel, and the dialog goes back to the progress.
  • Inherited from GIF: a killed export leaves a dot-prefixed .partial.mp4 beside the destination, and a destination locked by another program fails at the end of the render instead of the start.

Related issue

Closes #1014

Type of change

  • Bug fix

Release impact

  • Patch

Desktop impact

  • Windows
  • macOS
  • Linux

Testing

  • cargo test -p openscreen-compositor --lib, plus --test export_timing with generated media: the new GPU test cancels mid-render, stops at the next frame, returns ExportCancelled, keeps the destination and leaves no partial file.
  • cargo check -p openscreen-compositor -p compositor-view-napi --all-targets on Windows; macOS and Linux compile in CI.
  • Both tsc configs, targeted vitest (dialog, client, service, export jobs, new bridge test), Biome, docs check.
  • Not done: the in-app cancel with a rebuilt addon. A manual checklist line is added for it.

🤖 Generated with Claude Code

…ed file

run_composited_multi now takes the GIF export's control (renamed ExportControl,
shared by both formats) and checks it before every frame on all three
platforms. The MP4 is muxed into a staged file beside the destination and
renamed over it once complete: a cancel leaves no partial and an existing file
intact.

RAII guards close the muxer on every exit. On Windows the leaked handle made
the partial MP4 undeletable.

The addon adds create_mp4_export_control / cancel_mp4_export and an optional
control on export_multi; a cancelled export rejects with MP4_EXPORT_CANCELLED.
Every export now carries an ID and runs as a job of its window, MP4 like GIF,
so the dialog's Cancel reaches the native control. The registry and the
cancel action (cancelExport) are no longer GIF-specific.

An addon built before MP4 cancellation still exports: it refuses the cancel,
and the dialog goes back to showing the progress instead of a frozen spinner.
@coderabbitai

coderabbitai Bot commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: c7f1700b-e212-451e-bb75-e694922b5fee
📥 Commits

Reviewing files that changed from the base of the PR and between 2ac20cf and bce8d29.

📒 Files selected for processing (22)
  • crates/compositor-view-napi/src/lib.rs
  • crates/compositor/src/export_control.rs
  • crates/compositor/src/gif_export.rs
  • crates/compositor/src/lib.rs
  • crates/compositor/src/pipeline_linux.rs
  • crates/compositor/src/pipeline_macos.rs
  • crates/compositor/src/pipeline_windows.rs
  • crates/compositor/tests/export_timing.rs
  • electron/ipc/exportJobs.test.ts
  • electron/ipc/exportJobs.ts
  • electron/ipc/nativeBridge.export.test.ts
  • electron/ipc/nativeBridge.ts
  • electron/native-bridge/services/compositorViewService.test.ts
  • electron/native-bridge/services/compositorViewService.ts
  • electron/native/compositor-view/addon.d.ts
  • src/components/ai-edition/ExportDialog.cancel.test.tsx
  • src/components/ai-edition/ExportDialog.tsx
  • src/native/compositorViewClient.test.ts
  • src/native/compositorViewClient.ts
  • src/native/contracts.ts
  • technical-documentation/architecture/export-pipeline.md
  • technical-documentation/testing/manual-e2e-checklist.md

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 4 remain after this review.


📝 Walkthrough

Walkthrough

MP4 exports can now be cancelled through the shared export-job path used by GIF exports. The platform pipelines check cancellation during frame processing and write to staged files before publishing output. The export dialog, native bridge, and IPC layer pass export IDs and cancellation requests through the stack.

Changes

Shared MP4 and GIF export cancellation

Layer / File(s) Summary
Shared controls and staged export pipelines
crates/compositor/src/export_control.rs, crates/compositor/src/gif_export.rs, crates/compositor/src/pipeline_*.rs, crates/compositor/src/lib.rs, crates/compositor/tests/export_timing.rs, technical-documentation/architecture/export-pipeline.md
GIF-specific cancellation and staging APIs become format-neutral. The Linux, macOS, and Windows MP4 pipelines check cancellation during frame processing and publish staged output after completion. Tests cover cancellation and staged MP4 filenames; the architecture documentation describes the MP4 flow.
Native MP4 control API
electron/native/compositor-view/addon.d.ts, crates/compositor-view-napi/src/lib.rs, electron/native-bridge/services/compositorViewService.ts, electron/native-bridge/services/compositorViewService.test.ts
The addon exposes MP4 control creation and cancellation, and MP4 exports accept an optional control. The service starts cancellable jobs when the addon supports the control methods, with a non-cancellable fallback.
Export IDs and IPC job routing
src/native/contracts.ts, src/native/compositorViewClient.ts, electron/ipc/exportJobs.ts, electron/ipc/exportJobs.test.ts, electron/ipc/nativeBridge.ts, electron/ipc/nativeBridge.export.test.ts, src/native/compositorViewClient.test.ts
MP4 requests carry an optional export ID, and cancellation uses the shared cancelExport action. The IPC bridge routes identified exports through shared jobs, validates IDs, and maps MP4 and GIF cancellation errors to a common response.
Export dialog cancellation flow
src/components/ai-edition/ExportDialog.tsx, src/components/ai-edition/ExportDialog.cancel.test.tsx, technical-documentation/testing/manual-e2e-checklist.md
The dialog assigns IDs to MP4 and GIF jobs and uses the shared cancellation action. Tests cover MP4 cancellation and cancellation refusal. The manual checklist adds an MP4 cancellation scenario.

Priority: ➖ Normal

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

Change: Bug fix · Severity of issue fixed: Medium

Sequence Diagram(s)

sequenceDiagram
  participant ExportDialog
  participant compositorViewClient
  participant nativeBridge
  participant ExportJobs
  participant CompositorViewService
  participant NAPI
  participant run_composited_multi_cancellable
  ExportDialog->>compositorViewClient: Start MP4 export with exportId
  compositorViewClient->>nativeBridge: Send exportMulti request
  nativeBridge->>ExportJobs: Register export job
  ExportJobs->>CompositorViewService: Start export job
  CompositorViewService->>NAPI: Call exportMulti with ExportControl
  NAPI->>run_composited_multi_cancellable: Render with shared control
  ExportDialog->>compositorViewClient: Send cancelExport with exportId
  compositorViewClient->>nativeBridge: Send cancelExport request
  nativeBridge->>ExportJobs: Cancel matching job
  ExportJobs->>CompositorViewService: Invoke job cancellation
  CompositorViewService->>NAPI: Call cancelMp4Export
  NAPI->>run_composited_multi_cancellable: Observe cancellation during frame processing
Loading

Merge Risk: ⚪ Minimal · up to bce8d

No actionable issue is established from the supplied evidence. The in-app MP4 cancellation scenario should still be checked with a rebuilt addon as planned.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 46.43% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 56 functions across 20 files. (2 skipped:… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely identifies the main change: enabling cancellation during MP4 export.
Description check ✅ Passed The description covers the summary, related issue, change type, release impact, desktop impact, and testing. It also states that the in-app cancellation test was not done. The missing screenshot or vi…
Linked Issues check ✅ Passed Issue #1014 requires MP4 export cancellation during rendering. The PR summary reports cancellation checks between frames on Windows, macOS, and Linux, and connects the dialog’s Cancel action through t…
Out of Scope Changes check ✅ Passed The shared control, export-job, bridge, and dialog changes support cancellation for MP4 and preserve the existing GIF cancellation path. The related regression tests and documentation also support iss…
Full details: Docstring Coverage

Explanation

Docstring coverage is 46.43% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 56 functions across 20 files. (2 skipped: 2 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🛠️ Fix failing CI checks 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Warning

Some tools did not complete. Review the errors below.

🔧 Clippy (1.98.1)

Clippy execution failed


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.

@EtienneLescot
EtienneLescot merged commit eecb7e1 into main Oct 6, 2026
19 of 20 checks passed
@EtienneLescot
EtienneLescot deleted the fix/1014-mp4-export-cancel branch October 6, 2026 19:57
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.

[Bug]: MP4 export cannot be cancelled — Cancel is disabled while rendering

1 participant