跪拜 Guibai
← All articles
Frontend · Backend · JavaScript

A 6.5MB Face Recognition Model Runs an Access Gate Entirely in the Browser

By 半刻维度 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Running biometric recognition entirely in the browser sidesteps the cost and privacy exposure of server-side GPU inference. For building access, kiosks, or any edge deployment where a camera and a screen are already present, a static web page can replace a dedicated appliance.

Summary

A complete face-recognition access gate fits in a single static HTML page. The stack uses face-api.js to load three models from a CDN — a 190KB face detector, a 90KB landmark net, and a 6.3MB recognition net — and runs inference entirely on-device. Image data never leaves the browser; a 128-dimension descriptor is extracted and compared against a whitelist stored in localStorage using Euclidean distance with a threshold of 0.6.

The flow is straightforward: upload a photo or capture from a webcam, blur the preview while the models run, detect faces and 68 keypoints, extract the descriptor, and match it against the local whitelist. A Bun server handles static file serving and an optional upload proxy, but the recognition logic is pure client-side JavaScript.

Vendor quotes for a traditional setup ran several thousand yuan per gate plus a GPU server. This approach eliminates both the server cost and the privacy risk of sending biometric data over the network, all within a 6.5MB download that loads in under three seconds.

Takeaways
Three face-api.js models — tinyFaceDetector (190KB), faceLandmark68Net (90KB), and faceRecognitionNet (6.3MB) — load from a CDN and run inference in the browser.
Face matching uses Euclidean distance between 128-dimension descriptors; a threshold of 0.6 separates residents from strangers.
The whitelist of face descriptors persists in localStorage, so enrolled faces survive page reloads without a backend database.
A Bun server delivers static files and can optionally proxy image uploads to a real backend, but recognition never touches the server.
During recognition, the preview image is blurred with a CSS filter and a loading spinner overlays it, hiding the raw photo from view.
68 facial keypoints are drawn in five color-coded groups (jaw, brows, nose, eyes, mouth) for visual debugging.
The entire model payload is 6.5MB and loads in under three seconds on a typical connection.
Conclusions

Using localStorage as a face-embedding database is viable for small deployments — a few hundred residents — but lacks any access control, rotation, or sync mechanism, so it is a single-device solution.

The 0.6 Euclidean distance threshold is a tunable security parameter with no calibration data shown; lowering it reduces false accepts but risks locking out legitimate users under varying lighting or angles.

Blurring the preview image during recognition is a thoughtful privacy touch that most access-control UIs overlook, even though the raw image is already in memory.

face-api.js wraps TensorFlow.js models that were state-of-the-art around 2018; modern alternatives like MediaPipe or ONNX runtime in the browser would likely yield smaller models and faster inference.

Concepts & terms
face-api.js
A JavaScript library built on TensorFlow.js that provides face detection, facial landmark detection, and face recognition (128-dimension descriptor extraction) running entirely in the browser.
Euclidean distance for face matching
A measure of similarity between two 128-dimension face descriptor vectors. A smaller distance indicates a closer match; a threshold (here 0.6) decides whether two faces belong to the same person.
128-dimension face descriptor
A numerical vector produced by a face recognition model that encodes the unique features of a face. Comparing two descriptors with Euclidean distance determines if they represent the same person.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗