
Ricerca semantica sui video utilizzando Gemini Embedding 2 o Qwen3-VL.
Ricerca semantica su filmati video. Scrivi cosa stai cercando, ricevi un clip tagliato.
[!IMPORTANT] Fonte ufficiale: github.com/ssrajadh/sentrysearch è l'unica sede ufficiale di SentrySearch. Altri siti che ripubblicano o rispecchiano questo progetto non sono affiliati né approvati dal maintainer, scarica sempre da questo repository.
Lingue: Inglese · 简体中文
Nuovo: Video di walkthrough del codebase di SentrySearch
La Pipeline:
SentrySearch suddivide i tuoi video in chunk sovrapposti, incorpora ogni chunk come video utilizzando l'API Gemini Embedding di Google, Alibaba DashScope (qwen-cloud), o un modello locale Qwen3-VL, e memorizza i vettori in un database ChromaDB locale. Quando effettui una ricerca, la tua query testuale (o immagine, vedi ricerca per immagine) viene incorporata nello stesso spazio vettoriale e confrontata con gli embedding video memorizzati. Il risultato migliore viene automaticamente tagliato dal file originale e salvato come clip.
macOS/Linux:```bash curl -LsSf https://astral.sh/uv/install.sh | sh
**Windows:**```powershell
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
> **Richiede Python 3.11 o 3.12** (le ruote PyTorch non supportano ancora 3.13+). Se il tuo Python predefinito è più recente, installa una versione gestita 3.12 e fissa l'installazione dello strumento:
> ```bash
> uv python install 3.12
> uv tool install --python 3.12 .
> ```
3. Imposta la tua chiave API (o [usa invece un modello locale](#local-backend-no-api-key-needed)) — **necessaria solo per il backend predefinito Gemini**; salta se usi `--backend local` o `--backend qwen-cloud` con `DASHSCOPE_API_KEY` in `.env`.```bash
sentrysearch init
Questo richiede la tua chiave API Gemini, la scrive in .env e la valida con un embedding di test.
5. Ricerca:```bash
sentrysearch search "red truck running a stop sign"
ffmpeg è necessario per il chunking e il trimming dei video. Se non lo hai installato a livello di sistema, viene utilizzato automaticamente il pacchetto imageio-ffmpeg incluso.
Configurazione manuale: Se preferisci non utilizzare
sentrysearch init, puoi copiare.env.examplein.enve aggiungere manualmente la tua chiave da aistudio.google.com/apikey.
$ sentrysearch init
Enter your Gemini API key (get one at https://aistudio.google.com/apikey): ****
Validating API key...
Setup complete. You're ready to go — run sentrysearch index <directory> to get started.
Se una chiave è già configurata, ti verrà chiesto se sovrascriverla.
> **Consiglio:** Imposta un limite di spesa su [aistudio.google.com/billing](https://aistudio.google.com/billing) per evitare spese accidentali.
### Indice dei filmati```bash
$ sentrysearch index /path/to/video/footage
Indexing file 1/3: front_2024-01-15_14-30.mp4 [chunk 1/4]
Indexing file 1/3: front_2024-01-15_14-30.mp4 [chunk 2/4]
...
Indexed 12 new chunks from 3 files. Total: 12 chunks from 3 files.
Opzioni:
--chunk-duration 30 — secondi per chunk--overlap 5 — sovrapposizione tra chunk--no-preprocess — salta la riduzione di risoluzione/frame rate (invia chunk grezzi)--target-resolution 480 — altezza target in pixel per la preelaborazione--target-fps 5 — frame rate target per la preelaborazione--no-skip-still — incorpora tutti i chunk, anche quelli senza variazioni visive--backend local — usa un modello locale invece di Gemini (dettagli sotto)$ sentrysearch search "red truck running a stop sign" #1 [0.87] front_2024-01-15_14-30.mp4 @ 02:15-02:45 #2 [0.74] left_2024-01-15_14-30.mp4 @ 02:10-02:40 #3 [0.61] front_2024-01-20_09-15.mp4 @ 00:30-01:00
Saved clip: ./match_front_2024-01-15_14-30_02m15s-02m45s.mp4
Se il punteggio di similarità del miglior risultato è al di sotto della soglia di confidenza (default 0,41), verrai avvisato prima di tagliare:```
No confident match found (best score: 0.28). Show results anyway? [y/N]:
Con --no-trim, i risultati a bassa confidenza vengono mostrati con una nota anziché un prompt.
Opzioni: --results N, --output-dir DIR, --no-trim per saltare il taglio automatico, --threshold 0.5 per regolare la soglia di confidenza, --save-top N per salvare i primi N clip invece del solo miglior risultato, --dedupe per scartare risultati troppo simili a una scelta con ranking più alto (previene che blocchi quasi duplicati dello stesso evento riempiano la lista), e --rerank per chiedere a un VLM di riordinare i candidati restituiti prima del taglio. Backend e modello vengono rilevati automaticamente dall'indice — passa --backend o --model solo per sovrascrivere.```bash
sentrysearch search "red truck" --save-top 5 --dedupe 0.9
sentrysearch search "pedestrian crossing behind the car" --rerank --results 10
Il valore di `--dedupe` è un limite di similarità coseno (0–1). Viene eliminato qualsiasi risultato la cui similarità con un risultato già mantenuto di rango superiore superi questo valore. Valori più bassi sono più restrittivi: `0.8` richiede che i risultati siano molto distinti, `0.95` rimuove solo chunk quasi identici. `0.9` è un buon valore predefinito.
`--rerank` estrae ogni clip candidata restituita, la invia a un VLM con la query e ordina i possibili abbinamenti visivi davanti ai risultati basati solo sugli embedding. Le ricerche Gemini e qwen-cloud utilizzano Gemini 2.5 Flash per il reranking; le ricerche locali utilizzano un reranker locale Qwen3-VL Instruct. Se il reranking non può essere eseguito o un candidato non può essere valutato, SentrySearch mantiene i risultati ordinati per embedding invece di far fallire la ricerca.
### Ricerca per immagine
Utilizza un'immagine di riferimento come query — utile per "trova clip simili a questa" quando descrivere la scena a parole è scomodo (uno screenshot di un'auto specifica, un fotogramma di riferimento da un altro video, ecc.).```bash
$ sentrysearch img ~/Downloads/image.jpg
#1 [0.72] 2026-03-12_10-44-17-left_repeater.mp4 @ 00:00-00:30
#2 [0.69] 2026-03-12_10-44-17-left_repeater.mp4 @ 00:25-00:55
#3 [0.67] 2026-02-12_20-02-15-front.mp4 @ 00:00-00:18
Saved clip: ./match_2026-03-12_10-44-17-left_repeater_00m00s-00m30s.mp4
L'immagine viene incorporata nello stesso spazio vettoriale dei chunk video indicizzati e classificata per similarità coseno. La ricerca per immagini supporta --results, --threshold, --save-top, --dedupe, --overlay, --no-trim, --backend e --model.
Formati supportati: JPG, PNG, WEBP, GIF, HEIC/HEIF sul backend Gemini; il backend locale accetta inoltre tutto ciò che PIL può decodificare (BMP, TIFF, ecc.).
Nota: La ricerca per immagini restituisce corrispondenze visivamente simili, non necessariamente lo stesso oggetto. Una query per una berlina rossa potrebbe mostrare altre berline rosse di forma simile — regola le aspettative di conseguenza.
Non sai cosa cercare? sentrysearch highlights classifica i clip più anomali nel tuo indice — chunk i cui embedding sono lontani da tutto il resto — e li taglia automaticamente. Utile per sfogliare un nuovo caricamento di filmati.```bash
$ sentrysearch highlights -n 3
#1 [0.165] 2026-02-12_20-02-15-back.mp4 @ 00:00-00:18
#2 [0.163] 2026-02-12_20-02-15-right_repeater.mp4 @ 00:00-00:18
#3 [0.149] 2026-02-12_20-02-15-front.mp4 @ 00:00-00:18
...
Metodi di punteggio (`--method`):
- **`knn`** (predefinito) — distanza coseno media dai *k* vicini più prossimi di un chunk. Robusto; evidenzia clip senza quasi gemelli.
- **`centroid`** — distanza dalla media dell'indice. Il più economico, tendenzialmente orientato verso ciò che è sottorappresentato.
- **`lof`** — Local Outlier Factor. Migliore quando l'indice ha molteplici modalità "normali" distinte (giorno vs. notte vs. garage).
Opzioni di raffinamento:
- `--against "<query>"` — valuta l'anomalia *relativamente* a una query. Con `--against-mode within` (predefinito), classifica le anomalie tra i migliori match della query ("i pedoni strani nei clip pedonali"). Con `--against-mode global`, trova clip che corrispondono alla query *ma* sono diversi dal resto dell'indice ("eventi rari di questo tipo").
- `--dedupe 0.9` — elimina risultati troppo simili a una scelta con punteggio più alto (default similarità coseno 0.9). Impedisce che fotogrammi quasi duplicati riempiano la lista.
- `--exclude-baseline` — elimina la metà dell'indice più vicina al centroide prima del punteggio. Utile quando l'indice è dominato da filmati ripetitivi "noiosi".
- `-k, --neighbors 10` — *k* per `knn`/`lof`.
- `--no-trim` — stampa la classifica senza scrivere clip.
> **Attenzione:** Anomalo statisticamente ≠ interessante. Glitch del sensore, riflessi dell'obiettivo, fotogrammi notturni in un indice prevalentemente diurno e l'unico clip del garage ottengono tutti un punteggio alto. Usa `--exclude-baseline` e `--dedupe` per filtrare il rumore, o `--against` per limitare per argomento.
### Qwen Cloud (Alibaba DashScope)
Usa il backend opzionale **qwen-cloud** per [DashScope](https://www.alibabacloud.com/help/en/model-studio/qwen-api-via-dashscope) / Model Studio degli embedding multimodali (modello predefinito `qwen3-vl-embedding`, sovrascrivibile con `--dashscope-model` o `DASHSCOPE_EMBEDDING_MODEL`):```bash
uv tool install ".[qwen-cloud]"
export DASHSCOPE_API_KEY=...
sentrysearch index /path/to/footage --backend qwen-cloud
sentrysearch search "your query" --backend qwen-cloud
Caricamenti video: i file chunk locali vengono inviati a DashScope-managed temporary OSS tramite l'SDK Python ufficiale prima che l'API li consumi (l'API HTTP si aspetta un URL; l'SDK gestisce il caricamento per te).
Indicizza e cerca utilizzando un modello Qwen3-VL-Embedding locale invece dell'API Gemini. Gratuito, privato e funziona interamente sulla tua macchina. Per la migliore qualità di ricerca, usa il backend Gemini — il modello locale da 8B è una solida alternativa quando hai bisogno di ricerca offline/privata, e il modello da 2B è un ripiego quando l'hardware non supporta 8B.
Il modello viene rilevato automaticamente dal tuo hardware — qwen8b per GPU NVIDIA e Mac con 24 GB+ di RAM, qwen2b per Mac più piccoli e sistemi solo CPU. Puoi sovrascrivere con --model qwen2b o --model qwen8b. Scegli un'installazione in base al tuo hardware:
Non funzionerà bene: Mac Intel e macchine senza GPU dedicata. Questi ricadono sulla CPU con float32 — troppo lenti e affamati di memoria per un uso pratico. Usa invece il backend dell'API Gemini (il predefinito).
Non sei sicuro? Su Mac, usa
".[local]". Su NVIDIA, usa".[local-quantized]"— la quantizzazione a 4 bit funziona sulla più ampia gamma di hardware NVIDIA con una perdita di qualità minima. (bitsandbytes richiede CUDA e non funziona su Mac/MPS.)
Versione Python: Le wheel PyTorch sono in ritardo rispetto alle nuove release di Python, quindi il backend locale richiede Python 3.11 o 3.12. Se il tuo Python predefinito è 3.13+, installa un 3.12 gestito e vincola l'installazione dello strumento ad esso:```bash uv python install 3.12 uv tool install --python 3.12 ".[local]"
**Prerequisito Mac:** Installa FFmpeg di sistema (il processore video del modello locale lo richiede — il backend Gemini utilizza invece un ffmpeg integrato):```bash
brew install ffmpeg
Indicizza con --backend local e cerca — nessun flag extra necessario:```bash
sentrysearch index /path/to/footage --backend local
sentrysearch search "car running a red light"
Il comando search rileva automaticamente il backend e il modello da ciò che hai indicizzato. Puoi anche usare `--model` come abbreviazione — implica `--backend local`:```bash
sentrysearch index /path/to/footage --model qwen2b # same as --backend local --model qwen2b
sentrysearch search "car running a red light" # auto-detects local/qwen2b from index
Options:
--model qwen2b — modello più piccolo, qualità inferiore ma solo ~6 GB di memoria (accetta anche ID HuggingFace completi)--quantize / --no-quantize — forza la quantizzazione a 4 bit attivata o disattivata (predefinito: rilevamento automatico in base all'installazione di bitsandbytes)Notes:
--rerank locale scarica un modello Qwen3-VL Instruct separato (Qwen/Qwen3-VL-8B-Instruct o Qwen/Qwen3-VL-2B-Instruct) in aggiunta al modello di embedding.Il backend locale rimane veloce ed efficiente in termini di memoria grazie ad alcune tecniche che si combinano:
fps=1.0, max_frames=32). Un chunk di 30 secondi produce ~30 fotogrammi — non centinaia.Con tutto ciò, aspettati ~2-5 secondi per chunk su una A100 e ~3-8 secondi su una T4. Su una 4090, il modello 8B in bf16 dovrebbe impiegare pochi secondi (cifra singola bassa) per chunk.
Incorpora velocità, posizione e orario nei clip tagliati:```bash sentrysearch search "car cutting me off" --overlay
Questo estrae la telemetria incorporata nei file delle dashcam Tesla (velocità, GPS) e visualizza una sovrapposizione HUD. La sovrapposizione mostra:
- **Centro superiore:** velocità ed etichetta MPH su una scheda grigia chiara
- **Sotto la scheda:** data e ora (12 ore con AM/PM)
- **In alto a sinistra:** città e nome della strada (tramite geocoding inverso)

Requisiti:
- Firmware Tesla 2025.44.25 o successivo, HW3+
- I metadati SEI sono presenti solo nei filmati di guida (non in modalità parcheggio/Sentry)
- Il geocoding inverso utilizza [l'API Nominatim di OpenStreetMap](https://nominatim.openstreetmap.org/) tramite geopy (opzionale)
Installa con supporto per sovrapposizione Tesla:```bash
uv tool install ".[tesla]"
Senza geopy, l'overlay funziona comunque ma omette il nome della città/strada.
Source: teslamotors/dashcam
SentryMerge è uno strumento gemello che taglia automaticamente un singolo video multi-telecamera di un evento da un risultato di SentrySearch. Ogni volta che viene eseguito sentrysearch search, salva in cache l'elenco dei risultati in ~/.sentrysearch/last_search.json; SentryMerge lo recupera tramite --last, seleziona il miglior set di clip multi-telecamera, chiede a un VLM gli intervalli di visibilità sub-secondo per ogni telecamera e unisce un video accurato al fotogramma che segue il soggetto tra le telecamere:```bash
sentrysearch search ""
sentrymerge --last # → merge.mp4
`--last` funziona senza rieseguire la ricerca; `sentrymerge --query "..."` riesegue la ricerca internamente. Vedi il [README di SentryMerge](https://github.com/ssrajadh/sentrymerge#readme) per le istruzioni di installazione, le opzioni del backend VLM (Gemini / OpenAI / Qwen locale) e il sistema modulare cam-config per dashcam non Tesla.
### Redigere con SentryBlur
[SentryBlur](https://github.com/ssrajadh/sentryblur) è uno strumento gemello per la redazione locale di volti, targhe e linguaggio naturale nei video. Ogni volta che `sentrysearch search` salva un clip, memorizza nella cache il percorso in `~/.sentrysearch/last_clip.json`; SentryBlur lo recupera tramite `--last`, quindi cercare e poi redigere sono due comandi senza passaggio di percorsi:```bash
sentrysearch search "car cuts me off"
sentryblur prompt --last "road signs" # → match_<...>_blurred.mp4
sentryblur faces --last e sentryblur plates --last funzionano allo stesso modo. Scegli faces o plates per rilevatori CPU veloci; usa prompt "<text>" per oggetti arbitrari (schermi di telefoni, monitor, targhette) — prompt richiede una GPU NVIDIA o Apple Silicon. Consulta il README di SentryBlur per le istruzioni di installazione e le note hardware.
sentrysearch stats
sentrysearch remove path/to/footage
sentrysearch reset
#### Chunk falliti e riprovo
Se un chunk non può essere incorporato dopo i tentativi, SentrySearch lo registra in una coda di messaggi non recapitabili (DLQ) all'indirizzo `~/.sentrysearch/dlq.json` e continua a indicizzare il resto del tuo filmato. I chunk di solito finiscono lì a causa di ripetuti errori transitori API/backend, errori del decoder per un file specifico, file mancanti o errori di memoria esaurita. I guasti che sembrano permanenti, come file mancanti, errori di decodifica e OOM, vengono registrati immediatamente perché riprovare lo stesso chunk con le stesse impostazioni difficilmente aiuta.
Ispeziona i chunk falliti:```bash
sentrysearch dlq list
Riprova alla prossima esecuzione dell'indice:```bash sentrysearch index /path/to/footage --retry-failed
Cancella la DLQ senza riprovare:```bash
sentrysearch dlq clear
Per impostazione predefinita, le future esecuzioni di sentrysearch index saltano i chunk già presenti nella DLQ, in modo da non pagare o attendere ripetutamente per i fallimenti. Utilizza --retry-failed dopo aver risolto il problema di origine, modificato le impostazioni del modello/backend o liberato memoria.
SentrySearch mantiene lo stato locale sotto ~/.sentrysearch/:
Aggiungi --verbose a uno dei due comandi per informazioni di debug (dimensioni degli embedding, tempi di risposta API, punteggi di similarità).
Sia Gemini Embedding 2 che Qwen3-VL-Embedding possono incorporare nativamente il video — i pixel grezzi del video vengono proiettati nello stesso spazio vettoriale delle query di testo. Non c'è trascrizione, nessun sottotitolaggio dei fotogrammi, nessun intermediario testuale. Una query di testo come "camion rosso a un segnale di stop" è direttamente confrontabile con un clip video di 30 secondi a livello vettoriale. Questo è ciò che rende pratica la ricerca semantica sub-secondo su ore di filmato.
Indicizzare 1 ora di filmato costa ~$2,84 con l'API di embedding di Gemini (impostazioni predefinite: chunk da 30s, overlap di 5s):
1 ora = 3.600 secondi di video = 3.600 fotogrammi elaborati dal modello. 3.600 fotogrammi × $0,00079 = ~$2,84/ora
L'API Gemini estrae e tokenizza nativamente esattamente 1 fotogramma al secondo dal video caricato, indipendentemente dal frame rate effettivo del file. Il passaggio di pre-elaborazione (che ridimensiona i chunk a 480p a 5fps tramite ffmpeg) è un'ottimizzazione locale/di larghezza di banda — mantiene i payload piccoli in modo che le richieste API siano veloci e non vadano in timeout — ma non cambia il numero di fotogrammi che l'API elabora.
Due ottimizzazioni integrate aiutano a ridurre i costi in modi diversi:
Le query di ricerca sono trascurabili (solo embedding di testo).
DashScope fattura l'embedding multimodale in CNY per 1.000 token di input, per modalità. Per il modello predefinito qwen3-vl-embedding, le tariffe pubblicate da Alibaba (controlla il documento qui sotto per la tua regione e eventuali aggiornamenti) sono simili a:
L'indicizzazione invia chunk video (modalità video); ogni query search / img è per lo più token di testo o immagine, che sono più economici per token rispetto al video. Il tuo costo reale è il conteggio dei token restituito da DashScope per ogni chiamata API (dipende da risoluzione, durata, campionamento come DASHSCOPE_VIDEO_FPS, ecc.) — non esiste un tasso fisso "$ per ora di filmato" come il tasso per fotogramma USD pubblicato da Gemini senza misurare il tuo carico di lavoro.
Alibaba documenta anche una franchigia di token gratuiti (ad es. 1 milione di token entro un periodo limitato dopo l'attivazione); conferma nella pagina Metering & billing per l'embedding multimodale di DashScope e nella console di Model Studio / fatturazione, poiché prezzi, regioni e promozioni cambiano.
Questi flag influenzano la suddivisione in chunk e la pre-elaborazione per entrambi Gemini e qwen-cloud:
--chunk-duration / --overlap — chunk più lunghi con meno overlap = meno chiamate API = costo inferiore--no-skip-still — incorpora ogni chunk anche se non accade nulla--target-resolution / --target-fps — regola la qualità della pre-elaborazione--no-preprocess — invia chunk grezzi all'APIIl backend locale potrebbe stampare avvisi durante l'indicizzazione e la ricerca. Sono estetici e non influenzano i risultati:
MPS: nonzero op is not natively supported — Una nota limitazione di PyTorch su Apple Silicon. L'operazione passa alla CPU per un passaggio; tutto il resto rimane sulla GPU. Nessun impatto sulla qualità dell'output.video_reader_backend torchcodec error, use torchvision as default — torchcodec non trova un FFmpeg compatibile su macOS. Il processore video passa automaticamente a torchvision. È previsto e produce risultati identici.You are sending unauthenticated requests to the HF Hub — Il modello viene scaricato da Hugging Face senza token. Le velocità di download potrebbero essere leggermente inferiori, ma il modello si carica correttamente. Imposta una variabile d'ambiente HF_TOKEN per silenziare questo avviso se ti dà fastidio.--no-skip-still se hai bisogno che ogni chunk sia indicizzato.Funziona con filmati .mp4 e .mov, non solo con la Sentry Mode di Tesla. Lo scanner di directory trova ricorsivamente entrambi i tipi di file indipendentemente dalla struttura delle cartelle.
ffmpeg nel PATH, oppure utilizza ffmpeg incluso tramite imageio-ffmpeg (installato per impostazione predefinita)brew install ffmpeg (richiesto dal decoder video)| Hardware | Comando di installazione | Modello rilevato automaticamente | Note |
|---|
| Apple Silicon, 24 GB+ di RAM | uv tool install ".[local]" | qwen8b | Float16 completo tramite MPS |
| Apple Silicon, 16 GB di RAM | uv tool install ".[local]" | qwen2b | 8B non ci sta; 2B usa circa 6 GB |
| Apple Silicon, 8 GB di RAM | uv tool install ".[local]" | qwen2b | Limitato — potrebbe fare swap sotto carico; si consiglia invece l'API Gemini |
| NVIDIA, 18 GB+ di VRAM | uv tool install ".[local]" | qwen8b | Precisione bf16 completa (le wheel CUDA vengono scaricate automaticamente su Linux/Windows) |
| NVIDIA, 8–16 GB di VRAM | uv tool install ".[local-quantized]" | qwen8b | Quantizzazione a 4 bit (~6–8 GB) |
| Percorso | Scritto da | Utilizzato per | È sicuro eliminarlo? |
|---|
db/ | sentrysearch index | Indice vettoriale ChromaDB per i tuoi filmati incorporati. | Sì, ma elimina l'indice. Esegui di nuovo sentrysearch index <dir> prima di cercare. |
.env | sentrysearch init | Memorizza la tua chiave API Gemini per il backend predefinito. | Sì, ma i comandi basati su Gemini ti chiederanno di configurare di nuovo una chiave. |
dlq.json | Chunk falliti di sentrysearch index | Coda dei messaggi non recapitabili (DLQ) ispezionata da sentrysearch dlq list e ripetuta con --retry-failed. | Sì. Eliminarlo dimentica i chunk falliti, quindi le future esecuzioni di indicizzazione potrebbero provarli di nuovo come nuovo lavoro. |
last_clip.json | Comandi che salvano un clip (search, img, highlights, overlay) | Consente a SentryBlur di consumare il clip salvato più recente con sentryblur ... --last. | Sì. Viene perso solo il passaggio --last; i file MP4 salvati non vengono eliminati. |
last_search.json | sentrysearch search, img e highlights | Consente a SentryMerge di consumare l'elenco di risultati più recente con sentrymerge --last. | Sì. Viene perso solo il passaggio --last; l'indice di ricerca rimane invariato. |
history | sentrysearch shell | Cronologia dei comandi Readline per la shell interattiva. | Sì. La prossima volta la shell partirà con la cronologia vuota. |