-
-
Notifications
You must be signed in to change notification settings - Fork 227
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to select the correct camera with autofocus? #529
Comments
I had to write a few workarounds to get it how I want, but i don't use the autostart anymore either with: note that with the first one you have to cleanup your streams before changing to the device, or the camera won't work. |
I had the same issue. My solution was to enumerate all the devices and find the one with the shortest The process involved:
This is my code for querying the capabilities of the devices: export type MediaTrackCapabilitiesMap = { [key: string]: MediaTrackCapabilities[] };
interface FocusDistance {
min: number,
max: number,
step: number
}
async function getCameraWithClosestFocus(): Promise<string | undefined> {
const capabilities = await getCapabilities();
let minFocusDistance = Number.MAX_SAFE_INTEGER;
let bestDeviceId: string | undefined;
Object.entries(capabilities).forEach(([id, values]) => {
const focusDistance = getFocusDistance(values);
if (focusDistance && focusDistance.min < minFocusDistance) {
minFocusDistance = focusDistance.min;
bestDeviceId = id;
}
});
return bestDeviceId;
}
async function getCameras(): Promise<MediaDeviceInfo[] | undefined> {
if (!navigator.mediaDevices.enumerateDevices) {
return undefined;
}
const devices = await navigator.mediaDevices.enumerateDevices();
return devices.filter((x) => x.kind === "videoinput");
}
function getCapability<T>(value: MediaTrackCapabilities, key: string): T | undefined {
if (key in value) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access
return (value as unknown as any)[key] as T | undefined;
}
return undefined;
}
function getCapabilities(value: string): Promise<MediaTrackCapabilities[] | undefined>;
function getCapabilities(value: MediaDeviceInfo): Promise<MediaTrackCapabilities[]>;
function getCapabilities(): Promise<MediaTrackCapabilitiesMap>;
async function getCapabilities(value: MediaDeviceInfo | string | undefined = undefined): Promise<MediaTrackCapabilitiesMap | MediaTrackCapabilities[] | undefined> {
if (!value) {
const devices = await getCameras();
const resp: MediaTrackCapabilitiesMap = {};
if (devices?.length) {
for (const device of devices) {
const capabilities = await getCapabilities(device);
resp[device.deviceId] = capabilities;
}
}
return resp;
} else {
// Single device
const device = typeof value === "string" ? (await getCameras())?.find((x) => x.deviceId === value) : value;
if (!device) {
return undefined;
}
const media = await navigator.mediaDevices.getUserMedia({ video: device });
const tracks = media.getTracks();
const capabilities = tracks.map((track) => track.getCapabilities());
tracks.forEach((track) => track.stop());
return capabilities;
}
}
function getFocusDistance(value: MediaTrackCapabilities[]): FocusDistance | undefined {
return value
.map((x) => {
return getCapability<{ min: number, max: number, step: number }>(x, "focusDistance");
})
.find((x): x is FocusDistance => x !== undefined)
;
}
function getHasAutoFocus(value: MediaTrackCapabilities[]): boolean {
return value.some((x) => {
const focusMode = getCapability<string[]>(x, "focusMode");
return focusMode?.includes("auto") || false;
});
}
export {
getCameraWithClosestFocus,
getCameras,
getCapabilities,
}; |
@oobayly your solution looks good. Thanks man. I just have one more question: |
When we use ngx-scanner with the smartphone, we have several cameras, i.e.:
When we use "camera2 2, facing back", it does not work to scan small QR codes because the autofocus is not active.
But when we use "camera2 0, facing back", it works to scan small QR codes because the autofocus is active.
How we can find out which camera to take to have autofocus?
Do we have other possiblities to find out more informations about all available devices to select automatically the correct one?
Thanks very much.
Best regards
Mike
The text was updated successfully, but these errors were encountered: