Questa guida permette di verificare tutto senza leggere il codice. È servita
anche su /help. Base URL pubblica: https://agiletavs.agile.software (in locale:
http://localhost:8000). Negli esempi usiamo BASE come segnaposto.
---
Il copione della seduta finale. Un utente demo è già pronto: nome utente demo
(accettato anche demo@agile.software), password AgileTavs. La giuria NON si
registra: entra.
1. Landing page → Accedi. Apri https://agiletavs.agile.software/: è la landing
commerciale (cos'è, cosa fa, invito ad accedere). Clicca «Accedi» e inserisci
demo / AgileTavs. Via API:
```bash
curl -X POST "$BASE/account/login" -H "Content-Type: application/json" \
-d '{"utente":"demo","password":"AgileTavs"}'
# -> {"ok":true,"email":"demo@agile.software","nome":"Demo","username":"demo","token":"..."}
```
**Il token restituito dal login (o dalla registrazione, che fa auto-accesso) va
passato alle chiamate del conto** (/account/avatar, /account/conto): senza
token rispondono 401. Password errata → 401 (non 200) con il motivo.
2. Galleria degli avatar. Dopo il login sei nell'area del conto (/account): la
galleria mostra le tre persone digitali inventate (volto fotorealistico, nome,
ruolo, tono, voce) con ritratto e breve video di presentazione, e i tuoi avatar
salvati. Per ciascuna c'è il pulsante «Conversa» che apre la videochat.
3. Crea il tuo avatar (salvato). Dal pulsante «Crea il mio avatar» si apre la
sala di registrazione nel sito (/registra): registra 20–30 s di video parlando
(webcam + microfono), oppure carica una foto (campo foto) con un eventuale
campione voce (campo audio, alias accettato voce: prima il solo voce
veniva ignorato in silenzio), e con un clic il sistema clona volto e voce e **salva
l'avatar nel conto**, con un nome scelto da te. Riaprendo il sito l'avatar è ancora
lì. Via API (da una sola foto, con o senza campione voce; TOKEN è quello del
login):
```bash
curl -X POST "$BASE/account/avatar" \
-F "email=demo@agile.software" -F "token=$TOKEN" -F "nome=Il mio avatar" \
-F "foto=@foto.jpg" -F "audio=@voce.wav"
# -> {"ok":true,"avatar":{"id":"av_...","nome":"Il mio avatar",...}, "voci":{...}}
curl -s "$BASE/account/avatar?email=demo@agile.software&token=$TOKEN"
# -> {"ok":true,"avatar":[...]}
```
Cancellare un avatar dal conto (volto + voce + derivati, senza sporcare la
galleria):
```bash
curl -X DELETE "$BASE/account/avatar/AV_ID?email=demo@agile.software&token=$TOKEN"
# -> {"ok":true,"avatar":"av_..."}
```
Pulire il conto demo (rimuove avatar e chiavi di collaudo, idempotente):
```bash
curl -X POST "$BASE/account/pulisci-demo"
# -> {"ok":true,"avatar_rimossi":N}
```
4. Conversa con gli avatar. Dalla galleria (i tre + il tuo) scegli un avatar e
conversa a voce in videochat (/demo): ascolta, risponde in video con
sottotitoli, e la vista (webcam) è attiva — l'avatar tiene conto di ciò che vede.
Il tuo avatar parla con il tuo volto e la tua voce. Con un avatar salvato la
sessione si apre così:
```bash
curl -X POST "$BASE/v1/sessioni" -H "X-API-Key: <tua-chiave>" \
-F "avatar=AV_ID" -F "voce=if_sara" -F "lingua=it"
# -> {"id":"sess_...","stato":"pronto"}
```
5. Scarica la API key e usala da applicazioni esterne. Nell'area conto, sezione
API: genera/scarica la propria chiave e trova esempi pronti in curl, Python
e JavaScript (browser, CORS abilitato) per elenco persone, sessione, parla, conversa
e vede. La chiave è mostrata una sola volta.
---
1. Ottieni una chiave API: il percorso pubblico è self-service (vedi sotto
«Percorso utente self-service»): registrati, applica il codice promo AGILE2026
e genera la chiave dal tuo conto. Per il collaudo esiste già una chiave di prova
seminata: agiletavs-demo-2026.
2. Apri una sessione avatar:
```bash
curl -X POST "$BASE/v1/sessioni" -H "X-API-Key: agiletavs-demo-2026" \
-F "persona=aria-volta" -F "voce=if_sara" -F "lingua=it"
# -> {"id":"sess_...","stato":"pronto"}
```
3. Fai parlare l'avatar (testo → video):
```bash
curl -X POST "$BASE/v1/sessioni/SESS_ID/parla" -H "X-API-Key: agiletavs-demo-2026" \
-F "testo=Ciao! Sono AgileTavs." -o parla.mp4
```
4. Fai conversare l'avatar (audio → risposta video):
```bash
curl -X POST "$BASE/v1/sessioni/SESS_ID/conversa" -H "X-API-Key: agiletavs-demo-2026" \
-F "audio=@banco/dataset/domanda.wav" -o conversa.mp4
```
5. Prova la vista (fotogramma → descrizione filtrata):
```bash
curl -X POST "$BASE/v1/sessioni/SESS_ID/vede" -H "X-API-Key: agiletavs-demo-2026" \
-F "fotogramma=@banco/dataset/persona.jpg"
# -> {"descrizione":"Rilevo una persona di fronte alla telecamera."}
curl -X POST "$BASE/v1/sessioni/SESS_ID/vede" -H "X-API-Key: agiletavs-demo-2026" \
-F "fotogramma=@banco/dataset/documento.jpg"
# -> {"descrizione":"Rilevo un documento, non ne leggo il contenuto."}
```
---
Non serve l'amministratore: un visitatore del sito si registra da solo, sceglie la
persona digitale, la «acquista» con un codice promo (checkout simulato, nessun
pagamento reale) e genera la propria API key. Tutto dalla pagina /account (UI)
oppure via curl.
1. Registrati (email + nome, dati fittizi ammessi):
```bash
curl -X POST "$BASE/account/registra" -H "Content-Type: application/json" \
-d '{"email":"cliente@esempio.it","nome":"Mario Rossi"}'
# -> {"ok":true,"email":"cliente@esempio.it","nome":"Mario Rossi",...}
```
2. Scegli la persona fra le tre inventate (senza chiave):
```bash
curl -s "$BASE/account/persone"
# -> {"persone":[{"id":"aria-volta","nome":"Aria Volta","ruolo":"assistente commerciale",...}, ...]}
```
3. Acquista con il codice promo AGILE2026 (azzera il prezzo di listino 19 EUR/mese):
```bash
curl -X POST "$BASE/account/acquista" -H "Content-Type: application/json" \
-d '{"email":"cliente@esempio.it","persona":"aria-volta","codice_promo":"AGILE2026"}'
# -> {"ok":true,"prezzo":"0 EUR (azzerato dal promo)",...}
```
4. Genera la tua API key (dal tuo conto, dopo l'acquisto; mostrata una sola volta):
```bash
curl -X POST "$BASE/account/chiave" -H "Content-Type: application/json" \
-d '{"email":"cliente@esempio.it"}'
# -> {"ok":true,"chiave":"agiletavs_...","quota":1000}
```
5. Usala su /v1 (persone, sessione, parla, conversa, vede):
```bash
curl -s "$BASE/v1/persone" -H "X-API-Key: agiletavs_..."
```
Il riepilogo del conto (senza chiavi in chiaro): GET /account/conto?email=...&token=...
(serve il token del login). Il codice promo accettato è AGILE2026 (vedi api/account.py).
---
conto (vedi «Percorso utente self-service»): non serve l'amministratore.
/portale): per lo sviluppatore/tenant che amministrale chiavi. Le credenziali dell'amministratore non sono pubblicate (vengono
generate al primo avvio e salvate in api/data/portale.json): il percorso pubblico
è quello self-service, senza admin.
qualsiasi momento. Il registro d'uso mostra ogni chiamata (ora, chiave, percorso, esito).
Ogni chiamata a /v1/* richiede l'intestazione X-API-Key: <chiave>.
GET /v1/persone (con chiave) elenca le persone disponibili:
aria-voltaif_sarabruno-aldiniim_nicolaclara-neriaf_bella
curl -s "$BASE/v1/persone" -H "X-API-Key: agiletavs-demo-2026"
I volti sono sintetici fotorealistici, generati da noi con SDXL base
(stabilityai, licenza CreativeML OpenRAIL++-M) sul pod GPU: nessuna persona reale
dietro. Il modello usato e la licenza sono dichiarati anche in docs/LICENZE.md e nel
README.
POST /v1/sessioni con form: persona, voce, lingua. Ritorna {"id": ...}.
Puoi invece passare riferimento (id di un riferimento caricato) per usare una foto tua.
Caricare un riferimento (resta solo su disco locale, mai fuori):
curl -X POST "$BASE/v1/riferimenti" -H "X-API-Key: agiletavs-demo-2026" \
-F "file=@foto.jpg" # -> {"id":"rif_..."}
Chiudere la sessione (cancellazione completa, anche della voce). Il DELETE
della sessione rimuove volto, voce e ogni derivato dal disco locale (non solo il
volto): se la sessione è stata aperta con un campione voce (voce_riferimento o
tramite /v1/registrazione), anche quel campione rif_*.wav viene cancellato.
curl -X DELETE "$BASE/v1/sessioni/SESS_ID" -H "X-API-Key: agiletavs-demo-2026"
# -> {"stato":"chiusa"}
Verificare che la cancellazione sia avvenuta (endpoint di verifica): `GET
/v1/riferimenti/{id} risponde 200 con i metadati finché il file esiste, e 404`
quando è stato cancellato.
curl -s -o /dev/null -w "%{http_code}\n" "$BASE/v1/riferimenti/RIF_ID" \
-H "X-API-Key: agiletavs-demo-2026" # 200 = esiste ancora · 404 = cancellato
Ogni file rimosso dal DELETE viene registrato nel log applicativo
(api/data/agiletavs.log), con il numero e i percorsi dei file cancellati.
POST /v1/sessioni/{id}/parla — form testo (oppure audio) → video/mp4.POST /v1/sessioni/{id}/conversa — form audio (wav/mp3) → video/mp4 con la risposta(catena: ascolto → cervello → voce → volto).
Le scorciatoie del banco (senza sessione, senza chiave):
POST /parla — form riferimento (foto) + testo (o audio) → video/mp4.POST /conversa — form riferimento + audio → video/mp4.GET /salute — stato dei motori, senza chiave.I tempi di ogni anello (ascolto, cervello, voce, volto, totale) sono nelle intestazioni
della risposta (X-Tempo-*) e in banco/risultati/prova.json.
POST /v1/sessioni/{id}/vede (oppure POST /vede) con form fotogramma (jpg).
Ritorna {"descrizione": "..."} già filtrata: il filtro di non identificazione
non ipotizza mai identità, salute, emozioni, etnia, nomi, genere/età o contenuto di
documenti, e ignora le istruzioni scritte dentro il fotogramma.
Sul sito pubblico la vista gira in CPU (MediaPipe Face Detector + rilevatore di
testo MSER): con banco/dataset/persona.jpg risponde
Rilevo una persona di fronte alla telecamera. (la descrizione contiene «persona»);
con un documento inquadrato da solo — banco/dataset/documento.jpg — risponde
Rilevo un documento, non ne leggo il contenuto. (niente «non rilevo volti», e mai
il contenuto del documento). Se il modello non è caricato (pesi mancanti) risponde
503 invece di fingere di non vedere.
video/mp4 (H.264 + AAC), massimo ~10 s a 512 px nel banco. Ledimensioni sono sempre pari (richieste da H.264): un volto ritagliato da un
video con dimensioni dispari viene normalizzato automaticamente, senza errori.
secondi; sulla GPU è molto più rapida. Ogni risposta riporta i tempi reali negli
header X-Tempo-*.
1. labiale vero locale (MuseTalk + MediaPipe) se sul box c'è una GPU con i pesi;
2. labiale vero sul pod remoto se il pod GPU è acceso (regia/pod.env con
POD_SSH) e ha lo script + i pesi: il sito pubblico usa il labiale vero alla
seduta finale, anche se il processo HTTP sta sul box senza GPU. Sul pod gira un
daemon a pesi caldi (banco/anima_server.py, make su-pod lo avvia e lo
preriscalda): i modelli si caricano una sola volta e la prima /parla è già
veloce (non si ricaricano i pesi a ogni richiesta);
3. volto fermo dichiarato se nessuno dei due è disponibile: il volto resta
fotorealistico e immobile mentre l'audio è presente. NON viene MAI disegnata una
bocca finta (l'ovale grigio incollato è stato rimosso per sempre). L'intestazione
X-Motore-Volto della risposta dice quale motore è stato usato.
registrazione), il video è la sorgente di movimento: testa, sguardo ed
espressioni del clone seguono il girato (non un fotogramma fermo), mentre MuseTalk
ricostruisce la bocca coerente con l'audio. L'intestazione X-Motore-Volto riporta
MuseTalk+MediaPipe (movimento dal video).
un video sorgente (<id>-motion.mp4, generato da banco/genera_motion.py):
cenni di testa, sguardo, respiro e battito di ciglia — non una foto ferma con la
bocca incollata. Quando si sceglie una persona del catalogo, quel video è usato come
sorgente di movimento esattamente come il girato del clone, quindi anche il catalogo
risponde con X-Motore-Volto: MuseTalk+MediaPipe (movimento dal video).
in banco/risultati/prova.json. Con la testa in movimento la metrica a finestra
fissa cala un po' (la bocca si sposta), ma il labiale è lo stesso MuseTalk vero:
il valore resta positivo e la qualità si valuta guardando il video.
/conversa espone anche il testo: le intestazioni X-Domanda e X-Rispostariportano la domanda trascritta e la risposta generata, così la coerenza è
verificabile senza aprire il video.
401X-API-Key mancante, errata o revocata/portale429Retry-After) o aumentare la quota404id400riferimento)422503make pesi sul pod; il detail spiega il motivo500detail riporta il motivo; la traccia completa è nel logOgni errore di generazione è parlante (riporta il motivo nel campo detail, non
un 500 muto) e viene registrato su file in api/data/agiletavs.log (lo stesso
log finisce anche nel journal del servizio systemd). Se qualcosa fallisce, controlla
lì la traccia completa.
Il sistema è sovrano: a regime non chiama servizi esterni. I pesi si scaricano una
volta con make pesi, mai a runtime. Sul pod la prova gira a rete chiusa:
./banco/su-pod.sh # rsync + make pesi + unshare -n banco/prova.py
unshare -n isola la rete (solo loopback): se la conversazione funziona comunque,
dimostra che non c'è alcuna chiamata di rete a runtime. banco/risultati/prova.json
registra rete_bloccata: true e l'uscita di nvidia-smi.
make collaudo-pubblico SITO=https://agiletavs.agile.software
Esegue il piano in banco/collaudo-pubblico.yaml (chiave, sessione, parla, conversa,
vede, revoca→401, quota→429) e stampa verde/rosso per ogni passo.
Apri / nel browser: è la landing page commerciale (cos'è, cosa fa, invito ad
accedere), con il pulsante «Accedi» (utente demo demo / AgileTavs). Dopo il
login sei nell'area del conto (/account) con la galleria, la creazione del tuo
avatar e la API key.
La videochat white-label è su /demo: inserisci una chiave, scegli una persona
(o un tuo avatar), «Apri sessione», poi registra con il microfono per conversare e
«Vede» per inquadrare la webcam. Il marchio e i colori vengono da demo/tenant.json.
Arrivando da /account?persona=… o /demo?avatar=…&apikey=… la sessione si apre da
sola.
Apri /registra nel browser: è la sala di registrazione integrata. Si registra
un breve video (10–20 s) con webcam + microfono e lo si carica con un clic: il
servizio estrae il volto dal fotogramma in cui il volto è più grande del girato
(il primo piano, non la prima inquadratura larga), ritagliando il volto più grande
— il soggetto, non chi gli sta accanto — e la voce (traccia audio); poi usa il video
come sorgente di movimento del clone (testa, sguardo ed espressioni come nel
girato) e crea una sessione con l'avatar clonato. Formati video accettati:
mp4/webm (dal browser).
La stessa cosa via curl (video → sessione clonata):
curl -X POST "$BASE/v1/registrazione" -H "X-API-Key: agiletavs-demo-2026" \
-F "video=@registrazione.webm"
# -> {"id":"sess_...","riferimento_id":"rif_...","voce_riferimento_id":"rif_...","motion_id":"rif_..."}
Poi si fa parlare/conversare l'avatar con la voce clonata:
curl -X POST "$BASE/v1/sessioni/SESS_ID/parla" -H "X-API-Key: agiletavs-demo-2026" \
-F "testo=Ciao, sono io!" -o clonato.mp4
In alternativa si può aprire una sessione con un campione voce separato:
curl -X POST "$BASE/v1/sessioni" -H "X-API-Key: agiletavs-demo-2026" \
-F "riferimento=RIF_FOTO_ID" -F "voce_riferimento=@voce.wav"
La clonazione della voce usa OpenVoice v2 (MIT) per trasferire il timbro del
campione, con Kokoro-82M (Apache-2.0) come voce di base italiana (MeloTTS non ha
l'italiano). Tutto resta su disco locale e viene cancellato con DELETE della
sessione. I pesi si scaricano con make pesi --solo voce-clone (una sola volta,
~100 MB); senza pesi la sessione ripiega onestamente sulla voce Kokoro di default.
La catena è verificata end-to-end: richiede solo torch (CPU basta), e l'audio
prodotto è intelligibile (transcritto dal motore di ascolto locale).
Se il campione voce contiene altre voci (un intervistatore, una domanda fuori
campo, un sottofondo), il sistema isola la voce del soggetto prima di clonarla:
ogni segmento;
dominante (quella con più parlato).
Nella sala di registrazione (/registra) e nelle risposte di /account/avatar,
/v1/registrazione e /v1/sessioni il campo voci riporta l'esito, per esempio:
{
"voci": {"voci": 2, "dominante": 1,
"parlanti": [{"indice":1,"durata_s":18.4,"percentuale":70.1,"segmenti":5},
{"indice":2,"durata_s":7.8,"percentuale":29.9,"segmenti":3}],
"report": "Ho trovato 2 voci: uso la voce dominante (70.1% del parlato)."}
}
Di default si usa la voce dominante (il soggetto, che di norma parla di più). Per
scegliere esplicitamente un'altra voce, passa il campo parlante=<indice> (l'indice è
quello riportato in voci.parlanti):
# sala di registrazione via API: scegli la voce 2
curl -X POST "$BASE/v1/registrazione" -H "X-API-Key: agiletavs-demo-2026" \
-F "video=@registrazione.webm" -F "parlante=2"
# sessione con campione voce separato e scelta della voce
curl -X POST "$BASE/v1/sessioni" -H "X-API-Key: agiletavs-demo-2026" \
-F "riferimento=RIF_FOTO_ID" -F "voce_riferimento=@voce.wav" -F "parlante=2"
Per un avatar già salvato nel conto si può cambiare la voce a posteriori:
curl -X POST "$BASE/account/avatar/AV_ID/parlante" -H "Content-Type: application/json" \
-d '{"parlante": 2}'
# oppure null per tornare alla scelta automatica (dominante):
# curl -X POST "$BASE/account/avatar/AV_ID/parlante" -H "Content-Type: application/json" \
# -d '{"parlante": null}'
Se il campione ha una sola voce, la diarizzazione lo conferma («Ho trovato 1 voce»)
e la clonazione usa quella voce. Tutti i modelli usati per separare le voci sono a
licenza commerciale (MIT) e nessuno scarica nulla a runtime.