Limitations
This checks handshapes, not ASL. ASL is a full language with its own grammar and facial and body grammar this tool doesn't see — no facial expression, no mouth morpheme, no body shift, none of it. "Handshape match" is the only claim this tool makes.
The published eval does not meet this project's own ship bar yet
This is the limitation that matters most, so it leads. The model currently shipped was evaluated against a random, file-level split of a single-source community dataset, not a genuine held-out signer. No real per-signer val/test holdout exists (data/self-collected/ is empty — volunteer recruitment is a human task, see data/ATTRIBUTION.md). This split is a random, file-level (not signer-level) division of the single-source asl-now pool, run only because --provisional-split was passed explicitly. It does not test generalization to an unseen signer and must not be read as SPEC.md §3.2's actual ship-bar claim.
Concretely: the 95.7% figure on the concept page almost certainly overstates real accuracy on a genuinely new signer, because a file-level split lets near-duplicate samples from the same capture session leak between training and test data. Recruiting and recording consenting volunteer signers — the fix — is a human task, not something this build could complete on its own. Ship-bar status: not met.
24 letters, not 26
J and Z are structurally absent, not missing by oversight. Both require traced motion — a single held frame cannot show a trajectory. A classifier built on one static image per prediction has no way to distinguish J from I, or Z from nothing at all, without motion data this project does not capture.
M, N, S, and T are genuinely hard to tell apart
These four are closed-fist handshapes differing mainly in thumb position — genuinely confusable even for people, not just this model. The real, measured numbers from this build's own eval:
| Letter | Precision | Recall | F1 | Test samples |
|---|---|---|---|---|
| M | 1 | 0.9231 | 0.96 | 13 |
| N | 1 | 0.9231 | 0.96 | 13 |
| S | 0.8571 | 1 | 0.9231 | 12 |
| T | 0.9091 | 1 | 0.9524 | 10 |
The Drill mode's "confusable" bias exists specifically because of families like this one — see the full confusion matrix.
The training pool's signer composition is unverified
The sid220/asl-now-fingerspelling community dataset that supplies this project's training data has no signer/participant field at all — it cannot be checked for how many distinct people contributed, or how evenly. It is used for training only, never for the published test numbers, for exactly this reason.
Rotation correction is in-plane only
normalize.ts corrects 2D (in-plane) rotation — a hand tilted sideways in the camera's view gets straightened out. MediaPipe's z coordinate is relative depth, not a metric measurement, so true out-of-plane rotation (the hand turned toward or away from the camera) is not corrected. A handshape held at a steep angle to the camera is more likely to be misread.
The camera-graded loop is not usable by a blind or low-vision visitor
This is a genuine, stated accessibility limit, not a performed one: there is no technical substitute for "does your hand visually match this shape," and this project does not have one. The flashcard mode (camera denied or absent) is offered as the accessible path for keyboard/no-camera users — not as a solution for visually-impaired users, because it is not one. It still requires seeing the reference description and confirming a shape was made by sight.
Every network request this product makes
A cold visit fetches MediaPipe's WASM runtime (~3.2MB, cdn.jsdelivr.net) and hand-tracking model (~7.5–8MB, storage.googleapis.com) — real, visible requests, named here rather than hidden. Once that one-time load finishes, no further request happens during live classification: your camera feed and hand landmarks never leave your device. See Concept & eval for the exact claim and what would make it false.