Skip to content

Screen recording: record with wf-recorder on Apple Silicon; keep the webcam overlay through dictation - #285

Open
DanteCpp wants to merge 2 commits into
maralcbr:mainfrom
DanteCpp:fix/asahi-screenrecording
Open

DanteCpp wants to merge 2 commits into
maralcbr:mainfrom
DanteCpp:fix/asahi-screenrecording

Conversation

@DanteCpp

@DanteCpp DanteCpp commented Oct 16, 2026 •

Copy link
Copy Markdown

Problem

On Apple Silicon, Alt + Print screen recording silently never starts. gpu-screen-recorder can't capture there. I tested each target omarchy-capture-screenrecording uses on an M1 Max (Asahi, Hyprland):

Target Result
monitor (-w eDP-1) display "eDP-1" not found, expected one of: "screen"
-w screen no usable output found
region kms server error: drmSetClientCap DRM_CLIENT_CAP_UNIVERSAL_PLANES failed: Operation not supported

The script only marks a recording active once the recorder has created the output file, so the bar indicator never appears, there's nothing to stop and nothing is saved. Without OMARCHY_SCREENRECORD_DEBUG no error is shown. The package-parity change (c751f51) replaced the interim wf-recorder with gpu-screen-recorder, but the script never had an Apple Silicon path.

Two more problems showed up with webcam recordings:

  • Dictation froze the camera. voxtype's pause_media pauses MPRIS players while it listens, and the system-wide mpv-mpris plugin makes the webcam overlay's mpv one.
  • mpv segfaulted every time the overlay closed (crash notification on each stop). It rendered frames straight from the camera's mmap'd V4L2 buffer, which is unmapped while the renderer still reads it. Backtraces were in pl_tex_upload, both under Vulkan (libvulkan_asahi) and under OpenGL (memcpy in gallium).

Changes

1. Webcam overlay (913df83): mpv starts with --load-scripts=no (no MPRIS, so dictation leaves it alone), and the filter chain gains format=yuv420p, which copies each frame out of the V4L2 buffer. This touches every platform. The MPRIS fix applies wherever voxtype runs; the copy costs very little at 720p30.

2. wf-recorder on Apple Silicon (4e40f7d):

  • omarchy-capture-screenrecording uses wf-recorder when omarchy-hw-apple-silicon succeeds. It captures through Hyprland's screencopy protocol and encodes with x264 veryfast on the CPU.
  • Hardware encoding isn't available: Honeykrisp has no VK_KHR_video_encode, the M1 video encoder has no Linux driver, and the only Vulkan encoders that run (ProRes/FFV1 compute) were slower than real time at 3456x2160 with ~60 MB/s output.
  • The same targets work (monitor -o, region -g), and the -s size cap becomes a scale filter. Desktop + microphone are mixed into one track through a temporary null sink, which is unloaded on stop, because wf-recorder takes a single PulseAudio source.
  • Stopping waits up to 15 s, not 5 s, for wf-recorder to flush frames still being encoded on the CPU.
  • The script, the bar indicator (ScreenRecording.qml) and the menu's Stop Screenrecording entry all match ^(gpu-screen-recorder|wf-recorder).
  • The recording-file pointer moved from /tmp to $XDG_RUNTIME_DIR, next to the region file, so a test can't overwrite a live recording's pointer.
  • wf-recorder joins omarchy-base-asahi.packages (gpu-screen-recorder stays for parity). Migration 1792147276.sh installs it on Macs set up earlier; it's self-gating and listed in asahi_migration_disposition.
  • The package-parity docs and the manual are updated.
  • x86 and other non-Apple machines are unchanged: same gpu-screen-recorder invocation.

Testing

  • New test/shell.d/screenrecording-apple-silicon-test.sh (10 checks): wf-recorder arguments for monitor, region, size cap and each audio mode; gpu-screen-recorder off Apple Silicon; the shared detection pattern in script, menu and bar; the overlay flags; the migration. It stubs pgrep/pkill, so it can't touch a real recording.
  • screenrecording-test.sh, asahi-packages-test.sh and migrate-asahi-test.sh pass. ./test/cli passes.
  • In ./test/shell, everything else passes except tests that fail the same way on unmodified main on this machine (missing node, and the boot/snapshot/GRUB suites).
  • On hardware (MacBook Pro M1 Max, Asahi):
    • Fullscreen + desktop + mic + webcam produces a 3456x2160 H.264 + AAC file with the overlay visible.
    • On stop, the recorder, overlay and audio mix are all cleaned up, with no mpv core dumps.
    • Started and stopped through Hyprland exec, as the keybinding does. The menu entry and the bar indicator's click weren't exercised by hand; the test checks they use the same pattern.
    • During a webcam recording mpv is no longer on the session bus as an MPRIS player.

🤖 Generated with Claude Code

DanteCpp and others added 2 commits October 16, 2026 12:56
voxtype pauses MPRIS players while it listens (pause_media), and the
system-wide mpv-mpris plugin made the webcam overlay one, so the camera
froze in the recording whenever dictation started. The overlay now starts
mpv with --load-scripts=no.

On Apple Silicon the overlay also segfaulted every time it closed: frames
were rendered straight from the camera's mmap'd V4L2 buffer, which is
unmapped while the renderer still reads it. A format=yuv420p step copies
each frame out first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
gpu-screen-recorder can't capture on Apple Silicon: its KMS backend can't
map the Apple display controller to a GPU (DRM_CLIENT_CAP_UNIVERSAL_PLANES
is unsupported, eDP-1 is "not found"), so a recording silently never
started and there was nothing to stop. omarchy-capture-screenrecording now
records with wf-recorder there, through Hyprland's screencopy protocol,
encoding with x264 on the CPU since Asahi has no hardware video encoder.

- Same capture targets (monitor, region) and the same -s size cap, as a
  scale filter; desktop + microphone are mixed through a temporary null
  sink, since wf-recorder records one PulseAudio source.
- The script, the bar indicator and the menu's Stop entry match either
  recorder.
- The recording-file pointer moves to $XDG_RUNTIME_DIR, so tests can't
  overwrite a live recording's.
- wf-recorder joins the Asahi package set, and a migration installs it on
  Macs set up before this change.

Other machines keep gpu-screen-recorder unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
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.

1 participant