Software engineering · Feb 2025–oggi
HealthCam
Una piattaforma modulare che trasforma i video della webcam in misure associate all’uso delle applicazioni desktop. Stima del battito e rilevamento dei blink sono analizzatori locali sostituibili; una dashboard cloud permette di consultarne i risultati nel tempo.
Il mio contributo · progettazione e sviluppo end-to-end
- Backend e sistemi
- Servizi Python, orchestrazione asincrona e API autenticate.
- Data engineering
- PostgreSQL, aggregazione SQL incrementale e medie pesate.
- Prodotto web
- Dashboard Next.js per utente e demo in sola lettura.
Nella pagina di accesso scegli “Explore the demo”. Nessun account o webcam richiesti. Dati sintetici in sola lettura.
- Ruolo
- Progettazione e sviluppo end-to-end
- Stack
- Python · FastAPI · TypeScript · Next.js · PostgreSQL · Docker
- Origine
- Tesi di laurea · Università degli Studi di Milano
- Stato
- 3.0 · Plugin · Anteprima per sviluppatori

Andamento nel tempo
Medie giornaliere della frequenza cardiaca stimata.
Confronto tra app
Misure associate al contesto dell’applicazione attiva.
Copertura dei dati
Durata del monitoraggio per interpretare i risultati.
Demo con dati sintetici. Illustra il prodotto e le query; non dimostra l’accuratezza delle misure.
01 · Architettura
Una sola acquisizione, più analizzatori
HealthCam 3.0 invia ogni segmento webcam agli analizzatori abilitati in parallelo e allinea i risultati al contesto dell’app attiva. Un registro individua le capacità dei servizi; i manifest configurano processi nativi e container Docker. I risultati strutturati raggiungono un’API cloud autenticata.
Sul computer · Python / FastAPI
Webcam → segmenti da 20 secondi
Video locale e metadati temporali
Orchestratore + registro dei servizi
Manifest: runtime, ciclo di vita e capacità
Stesso segmento → analisi in parallelo
Battito · pyVHR
Plugin sostituibile
Blink · MediaPipe
Logica blink dedicata
Risultati + contesto dell’app → coda
App-Tracker → eventi allineati ai timestamp del segmento
Risultati e contesto
JSON autenticato · nessun video
Nel cloud · Next.js / PostgreSQL
API di ingestione
API key → utente · validazione Zod
Telemetria grezza · JSONB
Risultati, contesto e metadati
GitHub Actions → riepiloghi SQL
Incrementale ogni 5 min · riconciliazione giornaliera
Dashboard per utente
Andamenti, confronti e copertura
02 · Scelte tecniche
Progettare componenti sostituibili
Ho sviluppato acquisizione, orchestrazione, ciclo di vita dei servizi, ingestione, pipeline dati e applicazione web. L’analizzatore cardiaco integra pyVHR; quello dei blink usa i landmark di MediaPipe con logica di elaborazione scritta da me.
Inferenza locale, analisi storica in cloud
Il video resta sul dispositivo; il cloud conserva risultati consultabili nel tempo.
Costo: Configurazione manuale e vincoli hardware: l’attuale analizzatore BPM richiede NVIDIA/CUDA.
Processi nativi e container
Acquisizione e contesto usano le API del sistema operativo; i container isolano le dipendenze di analisi.
Costo: Più ambienti da avviare, collegare e diagnosticare.
Manifest e contratto comune
Un nuovo analizzatore dichiara runtime, comandi e capacità; il registro lo rende individuabile dall’orchestratore.
Costo: SQL e interfacce specifiche di nuove metriche richiedono ancora codice dedicato.
Componenti di ricerca integrati: pyVHR / PHuSe Lab per il battito; MediaPipe per i landmark del volto. Non ho sviluppato i loro algoritmi o modelli di base.
03 · Data engineering
Preparare i riepiloghi prima della lettura
PostgreSQL conserva la telemetria grezza in JSONB. GitHub Actions pianifica l’aggregazione SQL incrementale ogni cinque minuti e una riconciliazione giornaliera. Le dashboard leggono tabelle di riepilogo, evitando di scandire l’intero storico a ogni richiesta.
Ogni 5 minuti
Aggregazione incrementale
Un cursore seleziona i nuovi payload. Gli upsert SQL aggiornano somme, conteggi, estremi e durata per utente, giorno e app.
Ogni giorno · 02:10 UTC
Riconciliazione
Ricostruisce i riepiloghi recenti dai dati grezzi, partendo da due giorni prima dell’ultima data aggregata, per recuperare anche dati in ritardo in quella finestra.
A ogni lettura
Query sulle tabelle di riepilogo
Le medie sono pesate per il numero di campioni: giornate con pochi dati non hanno lo stesso peso di giornate con molti dati.
Il calcolo anticipato sposta le scansioni dello storico fuori dalle richieste delle dashboard. Il compromesso è un aggiornamento differito e la manutenzione di dati grezzi e riepiloghi.
Assunzioni e limiti delle trasformazioni
Il segmento è attribuito all’ultimo evento di contesto dell’app e al giorno di invio (o ricezione), non suddiviso tra i cambi di app. Il timestamp di acquisizione resta nei dati grezzi. La riconciliazione copre una finestra recente: non recupera automaticamente ogni ritardo storico. Le esecuzioni pianificate possono subire ritardi; non è stato misurato un incremento di prestazioni.
Verifiche tecniche · 30 settembre 2026
15 test superati · contratto dati e API
6 verifiche dell’API e 9 del contratto dati, con database simulato. Verificano autenticazione, validazione, richiesta di scrittura e limite di richieste; non l’intera pipeline.
Risultati, esempio di test e report riproducibile
- Autenticazione
- Chiave assente o sconosciuta → 401.
- Validazione
- JSON non valido o payload fuori contratto → 400.
- Ingestione
- Payload valido → 201 e chiamata di scrittura associata all’utente autenticato.
- Limite di richieste
- Soglia raggiunta → 429, Retry-After: 60 e nessuna chiamata di scrittura.
Leggi un test: rifiutare richieste oltre il limite
Estratto dal test esistente. Il database simulato restituisce un conteggio pari alla soglia; le asserzioni controllano la risposta e l’assenza di scritture. La chiave mostrata è un valore fittizio.
db.user.findUnique.mockResolvedValue({ id: "user-1" });
db.recordingPayload.count.mockResolvedValue(INGEST_RATE_LIMIT.max);
const response = await POST(
request(validCloudRequest(), { "x-api-key": "valid-key" }),
);
expect(response.status).toBe(429);
expect(response.headers.get("Retry-After")).toBe("60");
expect(db.recordingPayload.create).not.toHaveBeenCalled();Ambito: test isolati del contratto e dell’API. Non verificano PostgreSQL reale, richieste concorrenti, retry dell’agente o accuratezza delle misure. Il contratto accetta un risultato di analisi in errore; l’invio di quel risultato dall’agente non è verificato da queste suite.
Scarica il report: risultati, versione e riproduzione (Markdown)04 · Ricerca e valutazione
Valutare un analizzatore della piattaforma
Per la tesi ho integrato pyVHR, pacchetto di ricerca del PHuSe Lab dell’Università degli Studi di Milano, come analizzatore del battito da webcam (rPPG). Acquisizione, orchestrazione, archiviazione e dashboard di HealthCam sono separate dall’accuratezza di questo stimatore.

Errore assoluto medio≈ 11,6 BPM
Differenze tra app≈ 3 BPM
Ho allineato le stime al Polar H10 e analizzato errore, concordanza e luminosità. La configurazione valutata non distingueva queste differenze in modo affidabile; il risultato riguarda quella configurazione dello stimatore e quell’esperimento.
Fonte: presentazione di tesi HealthCam 2.0, slide 10–11.
La sostituibilità degli analizzatori era un obiettivo architetturale del progetto. Il risultato sperimentale delimita l’uso di questo stimatore; un altro analizzatore può riutilizzare acquisizione, orchestrazione e ingestione.
Metodo, fonti e limiti di riproducibilità05 · Gestione dei dati
Il video resta sul dispositivo
L’agente invia risultati, contesto di applicazioni e finestre, timestamp e metadati dei file. Video e file di metadati vengono eliminati dopo analisi e upload riusciti; gli errori possono lasciarli sul dispositivo. I dati derivati restano sensibili. Le API locali non sono autenticate e richiedono una macchina di sviluppo fidata.
Cosa si può valutare oggi
Il sistema, il risultato e i prossimi passi.
2.0 · Tesi: servizi separati e prima valutazione rPPG. 3.0 · Oggi: manifest, registro delle capacità e più analizzatori in parallelo.
Implementato
- Acquisizione webcam e contesto dell’app attiva
- Analizzatori rPPG e blink eseguiti in parallelo
- Servizi configurati tramite manifest
- Ingestione autenticata, PostgreSQL e dashboard BPM
Ancora in sviluppo
- Installer per utenti finali
- Installazione dei servizi dallo Store
- Dashboard e notifiche complete per il blink
- Invio persistente, ingestione idempotente e test di integrazione più ampi
Limiti attuali di affidabilità
La coda di invio è in memoria. Un errore di un analizzatore blocca l’invio dell’intero segmento, anche quando gli altri riescono; gli upload falliti vengono ritentati. Persistenza della coda, gestione dei risultati parziali e idempotenza dell’ingestione sono i prossimi interventi. I test pubblicati non verificano il percorso completo webcam/GPU/database.
La demo mostra l’interfaccia. L’esecuzione locale richiede accesso al repository privato, configurazione manuale e hardware compatibile. Progetto sperimentale di tesi e portfolio, non un dispositivo medico.
Contatti
Parliamo di lavoro, collaborazioni o idee da costruire.
Se stai valutando il mio profilo, vuoi propormi una collaborazione o hai un problema operativo da risolvere, scrivimi. Possiamo partire dal contesto, anche senza avere già tutte le risposte.
Oppure scrivimi diretto diego.webwork@gmail.com
Verona e Nord Italia. Disponibile per lavoro e progetti freelance. Disponibile al trasferimento.