cd /news/computer-vision/meta-s-ships-facial-recognition-on-s… · home topics computer-vision article
[ARTICLE · art-21878] src=buchodi.com pub= topic=computer-vision verified=true sentiment=· neutral

Meta's ships facial recognition on smart glasses

A security researcher discovered that Meta's smart glasses companion app, Stella, contains a fully functional on-device facial recognition pipeline, including three face models, a local database, and a biometric vector index. The researcher demonstrated the pipeline works end-to-end by triggering a "Person Recognized" notification on a test image, though the feature remains dormant for ordinary users with no visible UI or server-pushed identity data. The finding reveals Meta has assembled the complete technical infrastructure for real-time facial identification through its smart glasses, gated behind a server-side switch.

read7 min publishedJun 4, 2026

Stella is the companion app for Meta's smart glasses. Inspecting version 273.0.0.21

of the Android build (com.facebook.stella

), I found the entire computational and storage stack for on-device facial recognition: three face models, a local database schema, a cosine-similarity vector index dimensioned to match the models, a write path that stages biometric records to disk, a fully wired notification surface, and a user-facing "Connections" widget.

I want to be precise about what that does and does not mean, because the gap between the two is important.

What I can demonstrate: the machinery is present, it is wired together. Several facial extraction and facial fingerprinting models are present and I was able run the recognition pipeline end-to-end on a test image and it detected a face, generate a 2048-dimension biometric embedding, searched a local index, and on a match fired an Android notification stating to the user "Person Recognized".

To get the pipeline to run I invoked its existing handler directly with a test photo.

What I cannot demonstrate: that any of this is active for ordinary users. On a stock, unenrolled account the user-facing UI does not appear, and the screen the recognition notification deep-links to is missing from the build. I also did not observe Meta server-pushing identity data to the relevant database on my test account.

So this is not "Meta is secretly identifying the people you look at." It is: the complete apparatus to do exactly that is sitting on the device, assembled and functional, gated by Meta.

All findings below are reproducible against com.facebook.stella

v273.0.0.21.

Three face-recognition models ship on the device (~100 MB) #

Three ExecuTorch (.pte

) models arrive on the device via NMLML, Meta's asset-delivery system, downloaded from Meta.

Asset name (Meta's naming) File Size Function
android_facerec_scrfd
SCRFD.pte
3.4 MB Detects faces in an image
android_facerec_kps_aligner
KPSAligner.pte
117 KB Crops and aligns each detected face
android_facerec_sface
SFace.pte
96 MB Converts a face into a 2048-number embedding (the biometric fingerprint)

These map onto open-source architectures, the same model families that other apps and academic projects already use:

SCRFD* Sample and Computation Redistribution for Efficient Face Detection*(InsightFace, ICLR 2022). Reference implementation:github.com/deepinsight/insightface

.SFace* Sigmoid-Constrained Hypersphere Loss for Face Recognition*(Zhong et al., 2021). Reference:github.com/zhongyy/SFace

KPSAligner keypoint-based alignment, standard practice since 2015 (MTCNN, dlib, InsightFace).

Meta's SFace variant seems to be scaled larger than the public reference (96 MB vs. ~40 MB; 2048-dimension output vs. the reference's 128–512).

Worth stating plainly: shipping detection and embedding models is not, by itself, evidence of recognition. Plenty of apps run on-device face detection for framing or autofocus.

A cosine-similarity face index, dimensioned exactly to the on-device fingerprinter #

The recognition pipeline that actually runs and reads into this database:

/data/user/0/com.facebook.stella/files/rldrive/person_profiles/objects.db

This lives under RLDrive, Meta's cross-device sync framework, in a person_profiles

namespace designed to be populated remotely. I did not directly observe Meta pushing data to person_profiles

specifically on my test account. I want to be clear that I'm describing the channel's existence, not an observed transmission.

The schema:

CREATE TABLE person (
  nodeid  INTEGER PRIMARY KEY,
  name    TEXT,     
  uri     TEXT,     
  blob    BLOB,
  deleted INTEGER,
  version BLOB
);

CREATE TABLE face (
  nodeid    INTEGER PRIMARY KEY,
  mediaPath TEXT,    -- the face_id used in the deep link
  personUri TEXT,    -- soft reference back to person.uri
  blob      BLOB,
  deleted   INTEGER,
  uri       TEXT,
  version   BLOB
);

CREATE VIRTUAL TABLE face_mediaPath_vec
  USING vec0(mediaPath float[2048] distance_metric=cosine);
  -- 2048-float biometric fingerprint per face, cosine-distance search
  -- (uses the sqlite-vec extension)

Each face

row points at a person

via personUri

. Each face.mediaPath

is the primary key into face_mediaPath_vec

, which stores the 2048-number embedding. Recognition is a cosine-similarity query against that index, followed by a join into person.name

for the notification text.

A few things line up:

vec0

is the open-sourcesqlite-vec extension, which turns SQLite into a vector-similarity engine.- The dimension float[2048]

is the exact output shape of the SFace embedder shipped on the app. - The cosine

metric is the standard choice for comparing face embeddings.

The schema permits multiple face

rows per personUri

(no UNIQUE

constraint), but whether a production deployment uses one-to-one or one-to-many is not visible from a non-enrolled device.

End-to-end test confirms both branches and isolates where writes go. I SHA-256-snapshotted and row-counted the database, then ran the full recognition pipeline twice: once against an empty index (no-match), once against an index pre-loaded with a single embedding (match):

No match(emptyface_mediaPath_vec

): one(uuid.jpg, uuid.emb)

pair was written toNameTagsPending/

. No notification.Match: an Android notification fired through the productionnametags_recognition

channel - title*"Person recognized", body"Recognized Michel Foucault"*. Nothing was added toNameTagsPending/

.

Unrecognized faces are staged to disk: crop plus fingerprint in NameTagsPending/ #

When the device sees a face that the local index does not match, Stella writes it to:

/data/user/0/com.facebook.stella/files/NameTagsPending/

Each unrecognized face produces a pair of files named with a fresh UUID:

  • a .jpg

— the cropped, aligned face, the output of SCRFD + KPSAligner; and - an .emb

— the 2048-number SFace fingerprint.

The directory is mode 0700

and survives reboots. Writes happen only on the no-match branch; matched faces go to a notification and leave no on-disk trace.

I verified the embedding's structure directly:

File:    NameTagsPending/1566ab46-[...].emb
Size:    8,192 bytes (2048 × float32, big-endian)
L2 norm: 0.999999          ← canonical L2-normalized face embedding
Min/max: −0.092110 / +0.098950
Mean:    +0.000292

Together, (uuid.jpg, uuid.emb)

is a complete, indexable biometric record of one face — the same shape and encoding the cosine index in person_profiles/objects.db

is built to match against.

The name NameTagsPending most literal reading is "faces pending a name" — biometrically encoded, awaiting a label. I'll note the structural fact and let it carry its own weight: a face image and its fingerprint, stored side by side in plaintext, mode 0700

, surviving reboots, is precisely the dataset you would assemble if you intended to retroactively identify faces once a label arrives.

The notification surface is fully wired #

Stella defines a dedicated Android notification channel

NotificationChannel{
  id          = "nametags_recognition"
  name        = "NameTags recognition"
  description = "Notifications for recognized NameTags connections"
  importance  = IMPORTANCE_HIGH      (heads-up + sound + badge)
  sound       = system notification sound
}

The notification template is hardcoded in the recognition handler. Title is always "Person recognized"; body is always "Recognized " + name

, where name

comes from the person

table in person_profiles/objects.db

:

NotificationCompat.Builder(ctx, "nametags_recognition")
  .setContentTitle("Person recognized")
  .setContentText("Recognized " + matched_name)
  .setAutoCancel(true)
  .setContentIntent(
    PendingIntent.getActivity(
      ctx,
      matched_name.hashCode(),
      Intent.ACTION_VIEW with
        Uri "fb-viewapp://name_tags?face_id=" + face_id,
      FLAG_IMMUTABLE | FLAG_UPDATE_CURRENT))
  .build()

NotificationManagerCompat.notify(matched_name.hashCode(), notification)

The notification is tappable: its contentIntent

is a deep link of the form fb-viewapp://name_tags?face_id=<face_id>

, a Meta-authored URL scheme meant to open a person-profile screen inside Stella.

One honest caveat: in v273, I could not find that destination screen. Tapping the notification routes Stella to its default tab, because the target Compose destination is absent from the navigation graph. The notification fires; the screen it points at isn't built into this release.

A user-facing "Connections" entry point exists in the APK #

Stella v273 contains a widget rendering a card under a section header titled "Connections", with the text "See your connections" / "Remember the people you met and make new connections." Both strings are hardcoded literals in the APK not server-pushed.

On a stock, unenrolled account, the card does not appear on the Glasses tab at all. It became visible during testing. In normal use, a user would not see this.

What this adds up to #

  • The full on-device face-recognition stack: detection, alignment, embedding, vector index, storage, write path, and notification surface is present and assembled in Stella v273.
  • It is functional. Run end-to-end, it recognizes a known face and names it in a notification, and it stages unknown faces (crop + fingerprint) to disk.
  • The index dimension, embedding shape, and storage schema are mutually consistent, this is a coherent system, not stray dead code.
  • The pieces a user would actually touch: the "Connections" card and the profile screen the notification opens are either absent from the build or buried deeper.
  • The database the live pipeline uses sits in a sync namespace Meta populates server-side, alongside other namespaces it already populates, but I did not observe a push to the face namespace on my account.

What I am not claiming: that Meta is identifying strangers for users today, that enrollment data is flowing, or that any of this is enabled in production.

What's hard to wave away: building, shipping, and wiring this much apparatus down to an 2048-dimension facial fingerprinting and a hardcoded "Person recognized" notification, is an engineering investment. Capability that doesn't ship by accident. Whether and when it goes into production is Meta's to answer.

This research is published alongside reporting in WIRED.

── more in #computer-vision 4 stories · sorted by recency
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/meta-s-ships-facial-…] indexed:0 read:7min 2026-06-04 ·