Caméra
Accéder à la caméra depuis votre page avec les API web standard.
Autoriser la caméra
Section intitulée « Autoriser la caméra »La caméra ne passe pas par window.mairies : votre page utilise l’API web standard navigator.mediaDevices.getUserMedia, comme dans un navigateur.
Deux autorisations sont nécessaires, dans cet ordre :
- La case « Caméra » cochée dans la section « WebApp avancée » de la carte lien. L’application accorde alors l’accès vidéo à votre origine, et à elle seule.
- L’accord de l’utilisateur, demandé par le système du téléphone la première fois que l’application utilise la caméra. S’il a déjà répondu, sa réponse s’applique sans nouvelle question ; il peut la modifier dans les réglages du téléphone.
Quand la case est cochée, mairies.commands contient 'camera'. Vous pouvez vous en servir pour décider d’afficher votre bouton de scan :
const cameraAllowed = Boolean(window.mairies?.commands.includes('camera'));Demander le flux vidéo
Section intitulée « Demander le flux vidéo »const video = document.querySelector('#scanner');
async function startCamera() { const stream = await navigator.mediaDevices.getUserMedia({ video: { facingMode: 'environment' }, // caméra arrière audio: false, // le micro n’est jamais accordé }); video.srcObject = stream; video.setAttribute('playsinline', ''); // aperçu dans la page sur iPhone video.muted = true; await video.play(); return stream;}Points à respecter :
- Vidéo seule. Toute demande qui inclut le micro (
audio: true, ou caméra et micro ensemble) est refusée en bloc. playsinlinesur l’élément<video>: sans cet attribut, l’iPhone peut afficher l’aperçu en plein écran au lieu de l’intégrer à la page.- Arrêtez le flux dès que vous n’en avez plus besoin, pour libérer la caméra et éteindre le voyant :
function stopCamera(stream) { stream.getTracks().forEach((track) => track.stop()); video.srcObject = null;}La demande peut venir de la page principale ou d’une iframe de la même origine que le lien ; une iframe d’une autre origine est refusée.
Torche pendant un flux caméra
Section intitulée « Torche pendant un flux caméra »Quand votre page filme, la caméra est occupée par la vue web, et la lampe se pilote différemment selon la plateforme.
-
Android :
mairies.torch.on(),off()ettoggle()échouent avecUNAVAILABLE, etisAvailable()renvoiefalse. Utilisez la contrainte web standard sur la piste vidéo :const [track] = stream.getVideoTracks();const capabilities = track.getCapabilities?.() ?? {};if (capabilities.torch) {await track.applyConstraints({ advanced: [{ torch: true }] });} -
iPhone :
mairies.torch.on()peut fonctionner pendant la capture ; en cas d’échec, l’erreur estUNAVAILABLE. La contrainte webtorchn’est pas prise en charge par Safari.
Stratégie recommandée : tentez mairies.torch.on(), puis, en cas d’UNAVAILABLE, essayez applyConstraints.
async function setTorchDuringScan(stream, on) { try { const result = await window.mairies.torch[on ? 'on' : 'off'](); return result.on; } catch (error) { if (error.code !== 'UNAVAILABLE') throw error; const [track] = stream.getVideoTracks(); if (!track.getCapabilities?.().torch) return false; // aucune solution await track.applyConstraints({ advanced: [{ torch: on }] }); return on; }}Refus et erreurs
Section intitulée « Refus et erreurs »getUserMedia est rejetée avec les erreurs standard du web. Les plus courantes :
error.name |
Cause probable |
|---|---|
NotAllowedError |
Case « Caméra » non cochée, demande depuis une autre origine, micro demandé, ou refus de l’utilisateur. |
NotFoundError |
Aucune caméra ne correspond à la demande. |
NotReadableError |
Caméra déjà utilisée par une autre application. |
try { stream = await startCamera();} catch (error) { if (error.name === 'NotAllowedError') { // Proposer une saisie manuelle du code. }}Le message affiché à l’utilisateur doit lui proposer une solution : saisir le code à la main, ou autoriser la caméra dans les réglages du téléphone s’il l’a refusée.