macOS Continuity Camera is detected by getUserMedia but delivers zero video frames in Obsidian

Steps to reproduce

  1. On macOS, enable Continuity Camera and make an iPhone available as a camera.
  2. In an Obsidian desktop community plugin, enumerate video input devices and request the iPhone camera with the standard Web Media API:
const devices = await navigator.mediaDevices.enumerateDevices();
const camera = devices.find(
  (device) =>
    device.kind === "videoinput" &&
    device.label.toLowerCase().includes("iphone")
);

const stream = await navigator.mediaDevices.getUserMedia({
  video: camera
    ? { deviceId: { exact: camera.deviceId } }
    : true,
  audio: false,
});
  1. Assign the stream to an autoplay, muted, playsinline <video> element.
  2. Inspect the video track and video element after several seconds.

Did you follow the troubleshooting guide? [Y/N]

Yes. The issue was reproduced after restarting Obsidian with the same vault and plugin. The same iPhone camera works in Google Chrome on the same Mac.

Expected result

The iPhone Continuity Camera should deliver video frames to the <video> element. The element should report non-zero videoWidth and videoHeight, and the track should become unmuted.

Actual result

Obsidian successfully enumerates the iPhone camera and getUserMedia() resolves without throwing. The returned video track reports:

  • readyState: "live"
  • muted: true
  • a valid camera label
  • valid settings (for example 640 × 480 at 30 fps)

However, no video frames are delivered:

  • video.videoWidth === 0
  • video.videoHeight === 0
  • play() remains pending or the element waits indefinitely for frame-producing events
  • the track never emits usable frames

The same device produces frames correctly in Google Chrome on the same machine.

Environment

  • macOS: 26.5.1 (build 25F80)
  • Architecture: Apple Silicon / arm64
  • Obsidian application version: 1.13.4
  • Obsidian installer version: 1.12.7
  • Electron: 39.8.3
  • Chromium: 142.0.7444.265
  • Camera type: iPhone Continuity Camera

Additional information

Investigation

The original Obsidian application contains NSCameraUsageDescription and NSMicrophoneUsageDescription. However, neither the Obsidian host application Info.plist nor Obsidian Helper (Plugin).app contains:

<key>NSCameraUseContinuityCameraDeviceType</key>
<true/>

For comparison, the Google Chrome camera helper on the same Mac contains this declaration.

Chromium added the declaration to its helper Info.plist after macOS emitted the warning: “Add NSCameraUseContinuityCameraDeviceType to your Info.plist to use AVCaptureDeviceTypeContinuityCamera.”

Chromium change:
https://chromium.googlesource.com/chromium/src/+/403c431c537f159073189420b4e33ec14db989b5^!/

Apple documentation:

A/B verification

To test the packaging hypothesis:

  1. I created a local copy of Obsidian without changing the vault, plugin, or plugin code.
  2. I added NSCameraUseContinuityCameraDeviceType = true to the copied application Info.plist files, including its Electron helper applications.
  3. I ad-hoc signed the copied application.
  4. I launched the copy and repeated the same getUserMedia() flow.

After adding the declaration, the same iPhone immediately delivered real video frames in Obsidian and the camera preview became visible. The unmodified Obsidian application continued to reproduce the zero-frame behavior.

Suggested fix

Please add:

<key>NSCameraUseContinuityCameraDeviceType</key>
<true/>

to the macOS Obsidian application and the Electron helper application(s) responsible for video capture, especially Obsidian Helper (Plugin).app.

This should allow desktop community plugins using standard Web Media APIs to receive frames from iPhone Continuity Camera without requiring a native helper process.

Related forum topics