Fusionner la phase scan camera (ZXing.Net)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -60,18 +60,54 @@ Le décodage EAN-13 se fait en **C# avec [ZXing.Net](https://www.nuget.org/packa
|
||||
|---|---|
|
||||
| Décodage EAN-13 propre (380×160) | 0,04 ms/frame |
|
||||
| **Pire cas** : frame 640×480 bruitée sans code-barres (échec) | 0,53 ms/frame |
|
||||
| Surcoût du payload PWA | +192 Ko (brotli) |
|
||||
| Poids de l'assembly `zxing.wasm` seul | +192 Ko (brotli) |
|
||||
|
||||
Le pire cas est le chiffre qui gouverne le framerate : la majorité des frames caméra ne contiennent pas de code-barres lisible, et c'est l'échec de décodage qui coûte le plus cher.
|
||||
|
||||
⚠️ Ces chiffres sont mesurés en **JIT x64 natif**. En Blazor WASM le code est *interprété* par défaut : compter un facteur ~10-20×, soit ~5-10 ms/frame — largement suffisant pour scanner à 10-15 fps. Activer `<RunAOTCompilation>true</RunAOTCompilation>` ramène ça à 1-2 ms, au prix d'un build nettement plus lent.
|
||||
### Mesures en WASM réel — faites le 2026-08-18, phase scan
|
||||
|
||||
L'estimation « ~5-10 ms/frame en interprété » ci-dessus n'était qu'une extrapolation. Elle a
|
||||
été **vérifiée dans un vrai navigateur** (Chromium 148, x86_64 de bureau), sur le publish
|
||||
`Release` du client, en appelant le décodeur depuis la console via `BancEssaiScan` :
|
||||
|
||||
| Configuration | Pire cas 640×288 (bande visée) | Pire cas 640×480 |
|
||||
|---|---|---|
|
||||
| Publish `Release`, interprété | **4,4 – 6,4 ms/frame** | 6,7 – 7,8 ms/frame |
|
||||
| Build `Debug`, interprété | 17,7 ms/frame | 28,7 ms/frame |
|
||||
|
||||
**L'estimation était bonne** : le mode interprété tient largement les 10-15 fps visés (une
|
||||
frame toutes les 80 ms n'utilise que ~6 % du budget). **Aucune raison d'activer l'AOT** —
|
||||
il reste à confirmer sur un téléphone, sensiblement plus lent qu'un x86_64 de bureau.
|
||||
|
||||
⚠️ Ne jamais juger la fluidité sur un build `Debug` : il est **4 à 5× plus lent** que le
|
||||
`Release`, de quoi conclure à tort qu'il faut l'AOT.
|
||||
|
||||
### ⚠️ Le surcoût de payload réel est bien supérieur à 192 Ko
|
||||
|
||||
Mesuré par différence entre deux publish `Release` complets (somme brotli de `_framework`) :
|
||||
**+351 Ko** au total, dont ~4,7 Ko de code applicatif. Le coût imputable à ZXing.Net est donc
|
||||
d'environ **+346 Ko brotli**, soit **1,8× le poids de son propre assembly**. Le surplus vient
|
||||
des assemblies BCL que le trimmer ne peut plus retirer :
|
||||
|
||||
| Assembly | Delta brotli |
|
||||
|---|---|
|
||||
| `zxing.wasm` | +192 495 o |
|
||||
| `System.Text.RegularExpressions` | +91 237 o (de 7 Ko à 98 Ko : ZXing utilise Regex, tout le moteur reste) |
|
||||
| `System.Runtime.Numerics` | +30 701 o (nouveau) |
|
||||
| `System.Private.CoreLib` | +17 586 o |
|
||||
| divers (`Threading`, `Collections`, `InteropServices`…) | ~14 Ko |
|
||||
|
||||
Ne pas reprendre « +192 Ko » comme coût du scan : c'est le poids de l'assembly, pas celui
|
||||
de la fonctionnalité.
|
||||
|
||||
### Pièges à connaître
|
||||
|
||||
- **Le JS interop ne disparaît pas.** `getUserMedia` et `<canvas>`/`getImageData` sont des API web sans équivalent C#. Prévoir ~30 lignes de JS maison dont le seul rôle est de pousser un `byte[]` vers C#. Toute la logique de décodage reste en C#.
|
||||
- **Ne pas perdre de temps à essayer de réduire la taille via un reader ciblé.** Remplacer `MultiFormatReader` par `EAN13Reader` pour aider le trimmer **ne change rien** : mesuré à 192 495 octets à l'octet près dans les deux cas. ZXing.Net n'est pas trim-friendly.
|
||||
- `RGBLuminanceSource` accepte directement le buffer RGBA du canvas (`BitmapFormat.RGBA32`) — **aucune bibliothèque d'image nécessaire** (pas de SkiaSharp ni ImageSharp).
|
||||
- Le scan caméra exige **HTTPS** (garanti par YunoHost en prod ; en dev, `localhost` est considéré comme sûr).
|
||||
- Le scan caméra exige **HTTPS** (garanti par YunoHost en prod ; en dev, `localhost` est considéré comme sûr). Corollaire vérifié : tester le scan depuis un téléphone en pointant l'IP locale du PC (`http://192.168.x.x`) **échouera toujours** — ce n'est pas un contexte sécurisé. Le composant détecte ce cas et le dit explicitement.
|
||||
- **Une `DOMException` perd son `name` en traversant le pont JS→C#** : `getUserMedia` refusé remonte en C# sous la forme « Permission denied undefined », sans `NotAllowedError`. Or c'est ce nom qui distingue « permission refusée » de « pas de caméra » de « caméra occupée ». Le JS doit donc **attraper l'erreur et renvoyer un code de statut** ; parser le message côté C# ne marche pas.
|
||||
- **L'import du module JS doit porter une chaîne de requête** (`./js/scanner-camera.js?m=1`). En développement, l'import map généré par Blazor réécrit le chemin vers un nom empreinté que l'API hôte ne sert pas (elle utilise `UseStaticFiles`, qui ignore les points d'entrée empreintés) : l'import part en 404 et le scan ne démarre jamais. La chaîne de requête empêche cette réécriture ; en publication rien n'est réécrit pour ce fichier, donc le comportement est identique.
|
||||
|
||||
### Squelette validé
|
||||
|
||||
|
||||
Reference in New Issue
Block a user