Immagini IA vocali e dittafono inline in TAMSIV
La v1.3.2 è la release più ambiziosa che ho pubblicato su TAMSIV. Due funzionalità principali, una delicata migrazione tecnica e un cambiamento di filosofia sul rapporto tra voce e contenuti visivi.
In superficie, è semplice: tu parli, l'IA genera un'immagine, che viene allegata al tuo compito. Sotto, c'è una pipeline che concatena speech-to-text, analisi contestuale tramite LLM, generazione di immagini, upload su Supabase Storage e visualizzazione con URL firmato. Inoltre, un dittafono che passa da un overlay a schermo intero a un componente inline integrato nella parte inferiore dello schermo. E come bonus, una migrazione del gesture handler che mi ha fatto scorrere ogni file del progetto alla ricerca di importazioni insidiose.
Punti chiave
- Le immagini AI sono generate direttamente dalla voce: l'LLM analizza il contesto del compito per creare un prompt ottimizzato, senza intervento dell'utente.
- Il dittafono inline sostituisce l'overlay a schermo intero, con trascrizione visualizzata prima della fine del TTS per una sensazione di reattività immediata.
- La migrazione del gesture handler ha corretto un bug invisibile su iOS ma bloccante su Android in modalità release.
- L'opzione "skip TTS" consente un doppio vantaggio: tempo di risposta dimezzato e costi API ridotti per gli utenti che non necessitano della risposta vocale.
Come funziona la generazione di immagini AI direttamente dalla voce?
L'idea è nata da una semplice osservazione: un compito con un'immagine è immediatamente più coinvolgente di un compito con solo testo. La ricerca in psicologia cognitiva lo conferma: secondo uno studio di John Medina (Brain Rules), il cervello elabora le immagini 60.000 volte più velocemente del testo. Se puoi associare un'immagine pertinente a ogni compito, aumenti la ritenzione e la motivazione.
Il problema è che nessuno andrà a cercare manualmente un'immagine per ogni compito. Doveva essere automatico, contestuale e attivato dalla voce. Ecco la pipeline completa:
- L'utente parla: "Crea un compito per preparare la presentazione al cliente con un'immagine".
- STT nativo trascrive la voce in testo, come descritto nel mio articolo su STT nativo vs Deepgram.
- L'LLM analizza il contesto: titolo del compito, descrizione, tag esistenti.
- L'LLM genera un prompt ottimizzato per il modello di immagine, in inglese, con dettagli di stile e composizione.
- Il provider di immagini (Runware o Gemini) genera il visual.
- Upload su Supabase Storage, creazione di un record in
privat.task_attachmentscon il tipoai_generated. - Visualizzazione immediata tramite URL firmato.
Avevo dettagliato la scelta tra i provider di immagini nell'articolo dedicato alla generazione di immagini AI. La v1.3.2 ha integrato questa pipeline direttamente nel flusso vocale, rendendola accessibile senza alcuna frizione.
Perché l'LLM scrive il prompt al posto dell'utente?
Chiedere a un utente di scrivere un buon prompt per un'immagine è come chiedere a qualcuno di parlare fluentemente una lingua che non ha mai imparato. I modelli di generazione di immagini sono sensibili alla formulazione: l'ordine delle parole, i modificatori di stile, i termini tecnici come "illuminazione cinematografica" o "profondità di campo ridotta" fanno una differenza enorme sul risultato.
La soluzione è elegante: l'LLM conversazionale, che comprende già il contesto della discussione, diventa un traduttore tra l'intenzione umana e il linguaggio tecnico del modello di immagine. L'utente dice "un'immagine di presentazione professionale", l'LLM traduce in "diapositive di presentazione aziendale professionale su una scrivania moderna, ambiente aziendale pulito, illuminazione direzionale morbida, fotorealistico, dettagli 4K".
È lo stesso principio che applico in tutta l'architettura di TAMSIV: l'IA deve fare il lavoro cognitivo che l'utente non dovrebbe fare. Ne parlavo nell'articolo sulla personalizzazione vocale: l'intelligenza non è solo capire le parole. È capire l'intenzione dietro le parole.
Come il dittafono inline cambia l'esperienza utente?
Prima della v1.3.2, il dittafono apriva un overlay a schermo intero. Premevi il microfono, tutto scompariva a favore di un'interfaccia dedicata alla conversazione. Era funzionale, ma interrompeva il contesto. Non vedevi più la tua lista di attività, non vedevi più a che punto eri.
Il dittafono inline cambia le carte in tavola. Si integra direttamente nella parte inferiore dello schermo, come una tastiera. Vedi ancora il tuo contenuto sopra. La trascrizione del testo appare in tempo reale mentre parli. E soprattutto, il testo trascritto viene visualizzato prima della fine della generazione TTS.
Perché è importante? Secondo gli studi del Nielsen Norman Group sui tempi di risposta, 1 secondo è il limite per mantenere il flusso di pensiero dell'utente. Oltre, inizia a percepire un ritardo. Visualizzando la trascrizione immediatamente mentre l'audio viene generato in parallelo, inganniamo la percezione: l'utente vede che l'IA ha capito, anche se la risposta audio non è ancora pronta.
È una tecnica ben nota in UX: il modello RAIL di Google raccomanda esattamente questo. Rispondere visivamente in meno di 100ms affinché l'interazione sembri istantanea, anche se l'elaborazione completa richiede più tempo.
Cosa offre in pratica l'opzione "skip TTS"?
Non tutti gli utenti hanno bisogno di sentire la risposta dell'IA. Alcuni si trovano in un ambiente rumoroso. Altri vogliono solo leggere la trascrizione. Altri ancora usano TAMSIV in modalità silenziosa per abitudine.
L'opzione "skip TTS" permette di disattivare la sintesi vocale della risposta. Il vantaggio è duplice:
- Tempo di risposta: senza attendere la generazione e il download dell'audio TTS, la risposta viene visualizzata quasi istantaneamente.
- Costi API: ogni chiamata TTS ha un costo (OpenAI fattura per carattere). Su migliaia di interazioni quotidiane, si somma rapidamente.
È anche una questione di accessibilità. Alcune persone preferiscono leggere piuttosto che ascoltare. Altri hanno problemi di udito. Offrendo la scelta, rispettiamo le preferenze di ognuno. È lo stesso spirito del design del dittafono originale: la voce è un canale, non un obbligo.
Perché la migrazione del gesture handler era così critica?
È il tipo di bug che ti fa dubitare della tua sanità mentale. Tutto funziona in debug. Tutto funziona su iOS. Passi in modalità release su Android: il componente non risponde più al tocco. Nessun errore nei log. Nessun crash. Semplicemente... non funziona.
Il colpevole: importazioni di TouchableOpacity, FlatList e ScrollView provenienti da react-native invece che da react-native-gesture-handler, utilizzate all'interno di GestureDetector. La documentazione di React Native Gesture Handler è chiara: all'interno di un GestureDetector, tutti i componenti tattili devono provenire dalla libreria gesture handler, non da React Native standard.
Il bug era insidioso per tre motivi:
- Invisibile in debug: il bridge JavaScript di React Native in modalità debug gestisce gli eventi tattili in modo diverso dalla modalità release con Hermes.
- Invisibile su iOS: UIKit e il sistema di responder chain di iOS sono più tolleranti del sistema di gestione degli eventi di Android.
- Nessun errore esplicito: nessun avviso, nessun crash. Il componente viene visualizzato, ha lo stile corretto, ma il tocco non attiva nulla.
La correzione ha richiesto di scorrere ogni file del progetto. Non una ricerca rapida, perché alcune importazioni erano mescolate: il TouchableOpacity proveniva dal gesture handler, ma lo ScrollView nello stesso file proveniva da React Native. Alla fine ho stabilito una regola rigorosa per il resto dello sviluppo, che applico ancora oggi.
Come garantire le prestazioni con queste nuove funzionalità?
Aggiungere funzionalità è facile. Aggiungere funzionalità senza degradare le prestazioni è un mestiere. La v1.3.2 introduce una pipeline di immagini e un dittafono inline, due componenti potenzialmente pesanti. Ecco le ottimizzazioni implementate.
Innanzitutto, zero re-render inutili. Il dittafono inline utilizza React.memo e callback stabili per evitare di innescare re-render nella lista delle attività sovrastante. Ogni animazione passa attraverso useNativeDriver: true per essere eseguita sul thread nativo, non sul thread JavaScript.
Poi, la pulizia aggressiva. L'AudioPlayerService implementa un timeout di sicurezza di 30 secondi. Se un audio non termina entro questo limite (problema di rete, file corrotto), il servizio forza la pulizia. Senza questo, le risorse audio si accumulano in memoria. Avevo già dettagliato l'architettura di questo servizio nell'articolo sulla pipeline vocale.
Infine, le immagini generate vengono caricate in lazy loading con un placeholder sfocato. L'immagine viene scaricata solo quando la scheda dell'attività è visibile sullo schermo. Su un feed di 50 attività, questo significa potenzialmente 50 immagini che non vengono caricate inutilmente. È il tipo di ottimizzazione che influisce direttamente sull'egress di Supabase che avevo cercato di ridurre.
Qual è l'impatto della v1.3.2 sull'uso quotidiano?
Il cambiamento più notevole è la fluidità. Prima della v1.3.2, usare TAMSIV era funzionale ma un po' rigido. Dopo, è diventato naturale. Tu parli, vedi la tua attività crearsi con un'immagine, continui la tua giornata. Il dittafono inline non ti toglie più dal tuo contesto.
I feedback dei tester alpha hanno confermato l'intuizione. Il dittafono inline è stato unanimemente preferito all'overlay. L'immagine AI è diventata la funzionalità più utilizzata dopo la creazione di attività di base. E soprattutto, la correzione del gesture handler ha risolto una dozzina di segnalazioni di "pulsanti che non funzionano" che non riuscivamo a riprodurre in debug.
È la release che ha fatto passare TAMSIV da "funziona" a "è piacevole". E in build in public, è una pietra miliare importante quanto il primo commit. Ne parlavo nel bilancio a 650 commit: la qualità percepita fa la differenza tra un'app che si prova e un'app che si tiene.
Domande frequenti
È possibile generare immagini AI anche per i memo?
Attualmente, la generazione di immagini AI è disponibile per le attività. Il meccanismo utilizza la tabella privat.task_attachments con il tipo ai_generated. L'estensione ai memo è prevista ed è tecnicamente semplice poiché la tabella privat.memo_attachments esiste già con la stessa struttura.
Il dittafono inline funziona in background?
No. Il dittafono richiede che l'app sia in primo piano per l'acquisizione audio e la visualizzazione della trascrizione in tempo reale. È una scelta deliberata: il riconoscimento vocale nativo del dispositivo è ottimizzato per il foreground, e la visualizzazione immediata della trascrizione è la chiave dell'esperienza.
L'opzione "skip TTS" è permanente o per conversazione?
È un'impostazione permanente memorizzata nel profilo utente. Una volta attivata, tutte le conversazioni future saranno in modalità solo testo. Puoi riattivarla in qualsiasi momento dalle impostazioni.
Il bug del gesture handler influisce ancora sull'app?
No. La migrazione è stata completa e una regola di sviluppo rigorosa è stata implementata: ogni componente tattile all'interno di un GestureDetector deve obbligatoriamente utilizzare gli import di react-native-gesture-handler. Questo viene verificato ad ogni code review.
Quanto costa la generazione di un'immagine AI?
Con il provider Runware (HiDream-I1-Fast), circa 0,003 euro per immagine. Con Gemini 2.5 Flash Image, leggermente di più. I costi sono controllati da quote per piano di abbonamento: il piano Free non ha accesso, Pro ha una quota giornaliera, Team una quota più elevata.