# Meta's ships facial recognition on smart glasses

> Source: <https://www.buchodi.com/meta-glasses-facial-recognition/>
> Published: 2026-06-04 19:36:48+00:00

# Meta's smart glasses companion app ships a complete, dormant face-recognition pipeline on a stock account.

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-source**sqlite-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**(empty`face_mediaPath_vec`

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

pair was written to`NameTagsPending/`

. No notification.**Match**: an Android notification fired through the production`nametags_recognition`

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

.

## 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.*
