Camera: fall back to plain constraints, explain a silent refusal; show voice failures above the chat

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-02 00:28:08 +02:00
co-authored by Claude Opus 5.5
parent 2700a4ec3d
commit 6368e63b0e
3 changed files with 19 additions and 5 deletions
+17 -4
View File
@@ -76,15 +76,27 @@
async function showCamera(deviceId = camera) {
error = '';
dropPreview();
const wanted: MediaTrackConstraints = { width: { ideal: 1280 }, height: { ideal: 720 }, frameRate: { ideal: fps() } };
if (deviceId) wanted.deviceId = { exact: deviceId };
else wanted.facingMode = 'user';
try {
preview = await navigator.mediaDevices.getUserMedia({
video: { deviceId: deviceId ? { exact: deviceId } : undefined, width: { ideal: 1280 }, height: { ideal: 720 }, frameRate: fps() }
});
try {
preview = await navigator.mediaDevices.getUserMedia({ video: wanted });
} catch (e) {
// A refusal or a missing camera is final; anything else may be a phone camera that
// dislikes the wishes above, so ask once more for whatever it has
if (['NotAllowedError', 'SecurityError', 'NotFoundError'].includes((e as Error).name)) throw e;
preview = await navigator.mediaDevices.getUserMedia({ video: deviceId ? { deviceId: { exact: deviceId } } : true });
}
// Names are only given out once a camera was allowed
cameras = (await navigator.mediaDevices.enumerateDevices()).filter(d => d.kind === 'videoinput');
camera = preview.getVideoTracks()[0]?.getSettings().deviceId ?? deviceId;
} catch (e) {
error = (e as Error).name === 'NotFoundError' ? 'No camera was found.' : `Could not open the camera: ${(e as Error).message}`;
const { name, message } = e as Error;
error = name === 'NotFoundError' ? 'No camera was found.'
: name === 'NotAllowedError' || name === 'SecurityError'
? 'The camera was refused. If no question appeared, access is blocked: allow the camera for this site (the icon next to the address), and for the browser app in the phone\'s settings, then try again.'
: `Could not open the camera (${name}): ${message}`;
}
}
@@ -241,6 +253,7 @@
</div>
{#if error}<p class="err">{error}</p>{/if}
{#if kind === 'camera' && error}<div class="row"><button class="btn" onclick={() => showCamera()}>Try the camera again</button></div>{/if}
{#snippet footer()}
<button class="btn" onclick={onclose}>Cancel</button>