Corriger deux blocages du scan trouves en navigateur, et consigner les mesures reelles

Les deux defauts ont ete constates en executant reellement l'application, pas par
relecture :

1. L'import du module JS partait en 404 en developpement. L'import map generee par
   Blazor reecrit « ./js/scanner-camera.js » vers un nom empreinte que l'API hote ne
   sert pas (UseStaticFiles ignore les points d'entree empreintes). Une chaine de
   requete sur le specifieur empeche la reecriture ; en publication rien n'est
   reecrit pour ce fichier, le comportement est donc identique dans les deux modes.

2. Les messages d'erreur camera etaient tous generiques. Une DOMException perd son
   « name » en traversant le pont JS vers C# : un refus de permission arrivait sous
   la forme « Permission denied undefined ». Le JS attrape donc l'erreur et renvoie
   un code de statut stable, que le C# traduit en message utile.

CLAUDE.md est mis a jour avec les mesures reelles obtenues en WASM, qui manquaient :
la performance de decodage (l'estimation de 5-10 ms/frame est confirmee, l'AOT reste
inutile) et le surcout de payload, nettement superieur aux 192 Ko documentes une fois
comptees les assemblies BCL que ZXing empeche le trimmer de retirer.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
mathieu
2026-08-18 02:10:58 +02:00
co-authored by Claude Opus 5
parent f7ad9582f6
commit 3a00591117
3 changed files with 95 additions and 34 deletions
+27 -6
View File
@@ -16,19 +16,40 @@ export function diagnostic() {
return 'ok';
}
// Renvoie un code de statut plutôt que de laisser remonter l'exception : une DOMException
// traversée par le pont JS→C# perd son `name` (mesuré : C# ne reçoit que « Permission denied
// undefined »), or c'est précisément ce nom qui dit à l'utilisateur ce qui lui manque.
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,
});
try {
// 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,
});
} catch (e) {
switch (e.name) {
case 'NotAllowedError':
case 'SecurityError':
return 'permission-refusee';
case 'NotFoundError':
case 'DevicesNotFoundError':
case 'OverconstrainedError':
return 'aucune-camera';
case 'NotReadableError':
case 'TrackStartError':
return 'camera-occupee';
default:
return 'erreur:' + (e.name || 'Error') + ' — ' + (e.message || '');
}
}
video.srcObject = flux;
video.setAttribute('playsinline', '');
await video.play();
canvas = document.createElement('canvas');
ctx = canvas.getContext('2d', { willReadFrequently: true });
return 'ok';
}
// Capture une frame et la garde en mémoire. Renvoie [largeur, hauteur], ou null si