Le decodage EAN-13/EAN-8 est fait en C# par ZXing.Net (IsbnScanner), conformement a la decision actee dans CLAUDE.md : le JavaScript ne fournit que les pixels de la camera, aucune logique de decodage ne lui est confiee. Le scan se greffe en amont du flux d'ajout par ISBN existant : des qu'un code est lu et reconnu comme ISBN-13 valide, la recherche de notices est declenchee sans que l'utilisateur ait a retaper quoi que ce soit. La saisie manuelle reste accessible en permanence, y compris quand la camera echoue. Points traites explicitement : - camera arriere par defaut (facingMode "environment", en "ideal" pour ne pas echouer sur un PC sans camera arriere) ; - liberation de la camera a l'annulation, au succes et au demontage du composant ; - cadence limitee a ~12 images/s et decodage restreint a la bande centrale reduite a 640 px de large : inutile de decoder chaque frame en pleine taille ; - messages distincts pour permission refusee, absence de camera, camera occupee et contexte non securise (getUserMedia exige HTTPS ou localhost : une IP de reseau local en http ne marchera jamais, c'est une source de confusion garantie). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
62 lines
2.7 KiB
JavaScript
62 lines
2.7 KiB
JavaScript
// Rôle unique de ce fichier : ouvrir la caméra et fournir des pixels à C#.
|
|
// AUCUN décodage ici — il est fait par ZXing.Net côté C# (décision actée dans CLAUDE.md).
|
|
// getUserMedia et canvas/getImageData n'ont pas d'équivalent C#, d'où ces quelques lignes.
|
|
|
|
let flux = null;
|
|
let video = null;
|
|
let canvas = null;
|
|
let ctx = null;
|
|
let derniersPixels = null;
|
|
|
|
// getUserMedia exige un contexte sécurisé : HTTPS, ou localhost.
|
|
// Une IP de réseau local (192.168.x.x) en http NE l'est PAS — piège classique en dev.
|
|
export function diagnostic() {
|
|
if (!window.isSecureContext) return 'contexte-non-securise';
|
|
if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) return 'api-absente';
|
|
return 'ok';
|
|
}
|
|
|
|
export async function demarrer(element) {
|
|
video = element;
|
|
// facingMode "environment" = caméra arrière : on scanne un livre tenu devant soi.
|
|
// "ideal" et non "exact" pour ne pas échouer sur un PC qui n'a qu'une webcam frontale.
|
|
flux = await navigator.mediaDevices.getUserMedia({
|
|
video: { facingMode: { ideal: 'environment' }, width: { ideal: 1280 }, height: { ideal: 720 } },
|
|
audio: false,
|
|
});
|
|
video.srcObject = flux;
|
|
video.setAttribute('playsinline', '');
|
|
await video.play();
|
|
canvas = document.createElement('canvas');
|
|
ctx = canvas.getContext('2d', { willReadFrequently: true });
|
|
}
|
|
|
|
// Capture une frame et la garde en mémoire. Renvoie [largeur, hauteur], ou null si
|
|
// la vidéo n'est pas encore prête. Les pixels se récupèrent ensuite via pixels().
|
|
export function capturer(largeurMax, partHauteur) {
|
|
if (!video || !ctx || video.readyState < 2 || !video.videoWidth) return null;
|
|
const echelle = Math.min(1, largeurMax / video.videoWidth);
|
|
const l = Math.round(video.videoWidth * echelle);
|
|
const h = Math.round(video.videoHeight * echelle);
|
|
if (canvas.width !== l || canvas.height !== h) { canvas.width = l; canvas.height = h; }
|
|
ctx.drawImage(video, 0, 0, l, h);
|
|
// On ne renvoie que la bande centrale, celle que l'utilisateur vise : moins de pixels
|
|
// à transférer et à décoder, donc moins de travail par frame côté C#.
|
|
const hb = Math.max(1, Math.round(h * partHauteur));
|
|
const y = Math.round((h - hb) / 2);
|
|
derniersPixels = new Uint8Array(ctx.getImageData(0, y, l, hb).data.buffer);
|
|
return [l, hb];
|
|
}
|
|
|
|
export function pixels() {
|
|
return derniersPixels;
|
|
}
|
|
|
|
// Libérer la caméra : sinon le voyant reste allumé et la batterie se vide,
|
|
// ce que l'utilisateur perçoit — à raison — comme un dysfonctionnement.
|
|
export function arreter() {
|
|
if (flux) { flux.getTracks().forEach(t => t.stop()); flux = null; }
|
|
if (video) { video.srcObject = null; video = null; }
|
|
canvas = null; ctx = null; derniersPixels = null;
|
|
}
|