fix(camera): strict built-in filter both sides
Both the Python AVCapture path and the Swift CameraPreviewLayer
now enforce the same two-step filter :
1. deviceType == .builtInWideAngleCamera
2. localizedName must NOT contain 'iPhone', 'GSM', 'Desk View',
or 'Continuity'
The second clause matters because under some macOS configurations
(Continuity Camera promoted to widescreen, iPhone mirroring),
externally tethered phone cameras can advertise themselves with
the same primary deviceType.
Swift side also logs via NSLog so the picked device shows up in
Console.app even when stdout is buffered.
This commit is contained in:
@@ -69,11 +69,22 @@ def enumerate_devices() -> list[dict]:
|
||||
return out
|
||||
|
||||
|
||||
_BANNED_NAME_TOKENS = ("iphone", "gsm", "desk view", "continuity")
|
||||
|
||||
|
||||
def find_builtin_device() -> Optional[dict]:
|
||||
"""Selectionne le BuiltInWideAngleCamera (webcam Mac integree)."""
|
||||
"""Selectionne la webcam Mac integree :
|
||||
- deviceType doit etre BuiltInWideAngleCamera
|
||||
- le nom ne doit contenir aucun de _BANNED_NAME_TOKENS
|
||||
Evite les pieges Continuity/iPhone/Desk View qui peuvent matcher
|
||||
BuiltInWideAngleCamera dans certaines configs."""
|
||||
for info in enumerate_devices():
|
||||
if "BuiltInWideAngleCamera" in info["type"]:
|
||||
return info
|
||||
if "BuiltInWideAngleCamera" not in info["type"]:
|
||||
continue
|
||||
name_l = info["name"].lower()
|
||||
if any(tok in name_l for tok in _BANNED_NAME_TOKENS):
|
||||
continue
|
||||
return info
|
||||
return None
|
||||
|
||||
|
||||
|
||||
@@ -17,14 +17,36 @@ final class CameraPreviewLayer {
|
||||
}
|
||||
|
||||
func start() -> Bool {
|
||||
// On enumere TOUS les types puis on filtre durement : nom ne
|
||||
// contient ni 'iPhone', ni 'GSM', ni 'Desk View', ni
|
||||
// 'Continuity' (cas Continuity Camera 13+) et deviceType ==
|
||||
// builtInWideAngleCamera. Ca evite tous les pieges.
|
||||
let discovery = AVCaptureDevice.DiscoverySession(
|
||||
deviceTypes: [.builtInWideAngleCamera],
|
||||
deviceTypes: [.builtInWideAngleCamera,
|
||||
.continuityCamera,
|
||||
.external,
|
||||
.deskViewCamera],
|
||||
mediaType: .video,
|
||||
position: .unspecified)
|
||||
guard let device = discovery.devices.first else {
|
||||
print("No built-in camera found")
|
||||
NSLog("AV-Live-Body: %d cameras detected", discovery.devices.count)
|
||||
for d in discovery.devices {
|
||||
NSLog("AV-Live-Body: - %@ type=%@",
|
||||
d.localizedName, d.deviceType.rawValue)
|
||||
}
|
||||
let banned = ["iPhone", "GSM", "Desk View", "Continuity"]
|
||||
let device = discovery.devices.first { d in
|
||||
guard d.deviceType == .builtInWideAngleCamera else { return false }
|
||||
let name = d.localizedName
|
||||
for b in banned where name.localizedCaseInsensitiveContains(b) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
guard let device = device else {
|
||||
NSLog("AV-Live-Body: no Mac built-in camera found")
|
||||
return false
|
||||
}
|
||||
NSLog("AV-Live-Body: picked '%@'", device.localizedName)
|
||||
do {
|
||||
let input = try AVCaptureDeviceInput(device: device)
|
||||
guard session.canAddInput(input) else {
|
||||
@@ -40,7 +62,6 @@ final class CameraPreviewLayer {
|
||||
DispatchQueue.global(qos: .userInitiated).async { [weak self] in
|
||||
self?.session.startRunning()
|
||||
}
|
||||
print("CameraPreviewLayer running on '\(device.localizedName)'")
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user