Store each face detection once per file: in a group folder, every detection (incl. vector) is currently copied to every user who can see it causing the table to grow with the number of users

Aperta
#1,588 1 commento 2 reazioni 0 assegnatari Vedi su GitHub

@marcelklehr ci sta già lavorando.

Dal 29/10/2026.

  • #1593 di @marcelklehr — aperta

Valutazione

Difficoltà
5/5
Tempo stimato
Più di una settimana
Idoneità per principianti
35/100
Tipo di issue
Funzionalità
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
php, postgresql
Ambito
backend, database

Direzione di ricerca

Start with FaceDetection, FaceDetectionMapper, TaskResultListener, and FsActionService, which the issue identifies as storing and copying detections per user. Trace how detections, vectors, and per-user cluster assignments are read and written, then inspect the existing database migrations and tests for those paths. Done means detection data is stored once per file while each user's clusters and names remain private and existing access and clustering behavior still works.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

enhancement
Describe the feature you'd like to request

Store the box and embedding of each face detection once per file, and keep only the per-user part (the cluster assignment) per user. Clusters and their names would stay private to each user, as they are now.

I'm running Recognize 13.1.0 with recognize_backend 1.0.6 (CUDA), Nextcloud 35.0.2 AIO (in an LXC Container on Proxmox 9.2.21). All my photos are in one group folder that 39 users can see. Detection runs on an Nvidia T1000 8GB.

I deployed Recognize on Sunday evening & let it churn through my library. Once the first face crawl had finished the ~21k faces in ~7k photos resulted in ~816k rows in oc_recognize_face_detections (one per face per user). The table is now 6.9 GB of a 9.5 GB database. Before Recognize, the AIO database dump was 0.87 GB; it's now 9.9 GB 🥲.

AIO writes that dump next to the database, so the first I saw of it was the nightly backup failing on a full disk. I asked Claude Code to investigate. Here's its output


  • TaskResultListener inserts a complete FaceDetection, vector included, for every user returned by getUsersWithFileAccess() (TaskResultListener.php#L228-L238). That list comes from the mount cache, so it's everyone who has the folder mounted.
  • When a file's access changes or it moves into a shared folder, FsActionService copies each detection, vector included, to every new user with copyDetectionsForFileFromUserToUser() (FsActionService.php#L188, #L353, FaceDetectionMapper.php#L151-L164).
  • The vector is a json entity field (FaceDetection.php#L60), so each 512-value embedding is stored as text, about 7.5 KB per row.

Here that works out to roughly 290 KB for every face detected (39 × 7.5 KB), and the cost rises in step with the number of users who can see the folder. Inference already runs once per file since #939 fixed #916; only the storage repeats.

#948 and discussion #1063 ask for people to be shared between users. This request doesn't: each user would still get their own clusters and names, and only the detection data would be stored once. A comment on #948 already points out that detections, not only clusters, are per user (#948 comment). #1148, about users who mount a folder later getting no detections, was fixed in NC 32.

Describe the solution you'd like

Split the table in two:

  • recognize_face_detections: one row per face per file, with file_id, x, y, width, height and face_vector.
  • A per-user table (name up to you) with detection_id, user_id, cluster_id and threshold.

Clustering would still run per user, over the detections in files that user can see, and write cluster_id to that user's row. A user gaining access to a folder would get small rows instead of copies of every vector. With 39 users, the vector data here would drop from 6.9 GB to under 200 MB.

Storing the vector as binary float32 (2 KB for 512 values) would shrink it further, but that's a separate change, and #1315 already touched on it from another angle, so I'm only mentioning it.

Describe alternatives you've considered
  1. A .noimage marker on the group folder. That switches face recognition off for exactly the photos I want it for.
  2. Fewer users on the folder. They need access to the photos, so that's not an option.
  3. Recognize's own settings. For faces, 13.1.0 has faces.enabled and faces.batchSize, and nothing per user or per folder.
  4. Compression on the PostgreSQL side (ALTER COLUMN face_vector SET COMPRESSION lz4). It might shrink the table on disk, but the dump is plain SQL and stays the same size, and the backup is where it broke.
  5. More disk. That's what I did, but every new face still costs another ~290 KB.

🤖 Generated with Claude Code

Lingua principale
PHP
Stelle
700
Fork
70
Merge medio
4g 15h
PR unite (30g)
5

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di nextcloud/recognize

Tutte le issue di nextcloud/recognize

Issue simili

Altre issue su PHP

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.