Skip to content

fix(screen_recorder): record the screen, not the webcam, on macOS - #484

Open
hubooy wants to merge 1 commit into
calesthio:mainfrom
hubooy:fix/macos-screen-capture-device
Open

fix(screen_recorder): record the screen, not the webcam, on macOS#484
hubooy wants to merge 1 commit into
calesthio:mainfrom
hubooy:fix/macos-screen-capture-device

Conversation

@hubooy

@hubooy hubooy commented Aug 8, 2026

Copy link
Copy Markdown

Summary

On macOS, screen_recorder records the webcam instead of the screen on any Mac that has a camera.

avfoundation enumerates cameras before screens, so device 0 is the built-in camera. _build_mac_cmd passed screen_index straight through to -i, so the default screen_index=0 selects the camera. There is no error — the recording simply contains the operator's face instead of their screen, and the caller has no signal that anything went wrong.

This reads as a privacy issue as much as a correctness one: the tool opens the camera and records the person while they believe they are capturing a screen.

It is unambiguously unintended:

  • screen_capture_selector.py:4-5 advertises this tool as "no webcam", and lists "No webcam overlay (picture-in-picture)" as one of its limitations (:185), routing webcam work to cap_recorder instead.
  • The screen_index schema documents it as "Monitor index for multi-monitor setups (0 = primary)" — a monitor index, not a device index.
  • _build_windows_cmd and _build_linux_cmd do not take screen_index at all (gdigrab grabs the desktop; x11grab uses $DISPLAY). The mac branch was the only one leaking a platform's device numbering into a cross-platform parameter.
  • region cropping on macOS happens in post using screen geometry, which cannot work against a 1280x720 camera frame.

Related issue

None — filing the fix directly.

Changes

  • Add _detect_screen_device_mac(), which parses ffmpeg -f avfoundation -list_devices and maps a monitor index to its real avfoundation device index.
  • _build_mac_cmd uses the resolved device, falling back to the raw screen_index when detection fails, so behavior is never worse than today.

Testing

  • python -m pytest tests/contracts/ -q — 630 passed, 7 skipped.

  • Device mapping verified on macOS 15 (Darwin 25.5.0). ffmpeg -f avfoundation -list_devices true -i "" on this machine lists:

    [0] FaceTime HD Camera
    [1] iPhone Camera
    [2] iPhone Desk View Camera
    [3] Capture screen 0
    

    So the default screen_index=0 selected the FaceTime camera — three camera devices are enumerated before the only screen. _detect_screen_device_mac(0) returns 3, the actual screen.

  • Fallback path: _detect_screen_device_mac(1) and (9) return None on this single-monitor machine, so _build_mac_cmd falls back to the raw index — i.e. today's behavior — instead of failing.

  • Not verified: I did not capture a recording as part of this PR, and I have no Windows or Linux machine to check; those two branches are untouched by the diff.

Checklist

  • The change is focused on a single logical concern.
  • I ran the relevant tests locally (make test-contracts / make test) where applicable.
  • I updated docs/README if behavior or usage changed. — no doc change needed; the fix makes the code match the documented screen_index semantics.
  • No unrelated files (build artifacts, local config) are included in the diff.

🤖 Generated with Claude Code

https://claude.ai/code/session_01GYThSL15CujvBwD1wuUmr9

avfoundation enumerates cameras before screens, so passing screen_index
straight through to -i selects device 0 — the built-in camera on any Mac
that has one. The tool then silently records the user's face while the
caller believes it is capturing the screen, with no error to reveal it.

That is a privacy problem as much as a correctness one:
screen_capture_selector advertises this tool as "no webcam" (and routes
webcam overlay work to cap_recorder), and screen_index is documented as a
monitor index, not a device index. The Windows and Linux branches do not
take screen_index at all, so the mac branch was the only one leaking a
platform device numbering into a cross-platform parameter.

Map the monitor index to its real avfoundation device index by parsing
-list_devices, falling back to the raw index when detection fails.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GYThSL15CujvBwD1wuUmr9
@hubooy
hubooy requested a review from calesthio as a code owner August 8, 2026 18:05
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