Per avviare la sintesi vocale mentre un agente AI sta ancora componendo la risposta, invia a Kokoro ogni frase completa non appena è pronta. Nella guida pubblicata il 22 ottobre 2026, AWS descrive questo schema con Kokoro-82M su un endpoint real-time di Amazon SageMaker AI e un agente Strands ospitato in Amazon Bedrock AgentCore. Le frasi vengono sintetizzate in sequenza: il vantaggio è iniziare con la prima senza attendere il resto della risposta.

Prima di iniziare

Per seguire l’implementazione descritta da AWS servono un account AWS con le autorizzazioni necessarie, AWS CDK v2 inizializzato, Python 3.12 o successivo, uv, Docker e una versione compatibile di Boto3. Il container deve includere l’etichetta per il bidirectional streaming di SageMaker. Sono inoltre utili competenze con WebSocket e Starlette o ASGI, l’interfaccia standard per i server Python asincroni.

L’esempio esegue Kokoro-82M, un modello con 82 milioni di parametri, in un container personalizzato su un endpoint real-time di SageMaker AI con istanza GPU ml.g5.xlarge. L’agente Strands usa Amazon Bedrock per generare testo ed è ospitato nel runtime di Amazon Bedrock AgentCore. L’endpoint espone GET /ping, POST /invocations per lo streaming della risposta e WS /invocations-bidirectional-stream per la sessione WebSocket bidirezionale.

Procedura di implementazione

  1. Distribuisci prima l’endpoint Kokoro. Il runtime dell’agente dipende dal servizio di sintesi, quindi l’endpoint SageMaker deve essere disponibile prima di distribuire l’agente.
  2. Gestisci i messaggi WebSocket come frame binari. SageMaker invia i messaggi del client bidirezionale al container in frame binari. Un handler Starlette che chiama receive_text() può generare KeyError('text') anche quando l’endpoint risulta InService. Accetta i byte e decodificali in UTF-8 quando il contenuto è testo; prova esplicitamente il percorso binario.
  3. Mantieni aperta la sessione per le richieste successive. Riutilizza la stessa connessione per inviare altre frasi e chiudila solo quando il client manda un messaggio di chiusura esplicito. Per ogni richiesta di sintesi, il flusso comprende messaggi di controllo, audio e completamento.
  4. Invia le frasi complete man mano che arrivano. Il chunker lato client ricava frasi complete dai frammenti generati dall’agente e le trasmette a Kokoro; alla fine invia anche l’eventuale testo residuo, che potrebbe non terminare con un punto. L’handler sintetizza i messaggi uno dopo l’altro: non genera più frasi audio contemporaneamente.
  5. Distribuisci l’agente dopo l’endpoint e collega i due servizi. Nell’esempio, l’agente Strands viene eseguito in Bedrock AgentCore e usa Amazon Bedrock per generare la risposta. La prima frase può così entrare in sintesi mentre il modello continua a produrre le successive.
  6. Verifica il ciclo completo prima di considerare concluso il test. Controlla che la sessione accetti frame binari, che una seconda frase passi sulla stessa connessione e che il client riceva i messaggi di inizio sintesi, i dati audio e il completamento. Invia poi la chiusura esplicita. Un endpoint InService, da solo, non garantisce che l’handler interpreti correttamente i frame ricevuti.

Scegliere come inviare l’audio al browser

Se il frontend usa già Server-Sent Events (SSE), trasportare l’audio in base64 può essere una soluzione pratica. La codifica aumenta i dati di circa un terzo e i blocchi SSE possono spezzare i frame audio: il client deve accumularli e ricomporli prima di elaborarli. Nel percorso bidirezionale verso Kokoro, invece, si possono multiplexare audio binario grezzo e messaggi di controllo JSON. Un blocco è un messaggio di controllo solo se, preso per intero, può essere interpretato come un oggetto JSON.

Nel collegamento dal runtime AgentCore al browser, l’esempio mantiene SSE e base64 perché il runtime restituisce dizionari serializzabili in JSON. Le misure di trasporto riportate da AWS riguardano 24 clip:

Formato audioByte grezziByte in base64Bitrate
PCM grezzo2.396.4003.195.200384 kbps
MP3 48k308.304411.07249,5 kbps
AAC 32k fMP4258.039344.08441,6 kbps

Come leggere i risultati di latenza

Nel test isolato di AWS, lo stesso testo di 267 caratteri e quattro frasi è stato provato cinque volte per modalità contro un endpoint attivo. Il tempo medio al primo byte audio è stato di 329,3 ms in modalità batch e 156,7 ms inviando inizialmente solo la prima frase. AWS ha riportato una riduzione relativa del 52,4% per quel test.

Nel confronto end-to-end, AWS ha riportato un tempo al primo audio 2,4 volte più rapido con modalità bidirezionale nel test locale e 3,5 volte più rapido nel runtime AgentCore distribuito. Il confronto ha mantenuto lo stesso prompt, modello Bedrock ed endpoint, variando il momento di avvio della sintesi. Sono risultati riferiti alle prove descritte da AWS, non una misura universale delle prestazioni di Kokoro o di SageMaker.

Altri modi per eseguire Kokoro

Trelis Research ha mostrato Kokoro-ONNX in esecuzione locale su CPU e un server separato basato su Kokoro-FastAPI su un’istanza H100 di Runpod. Per il server con richieste concorrenti, Trelis Research ha riportato un’elaborazione di circa 55-78 ore di audio per ogni ora reale. Questi esempi descrivono percorsi di esecuzione distinti; il dato di throughput non è direttamente confrontabile con il tempo al primo audio misurato da AWS.

Sicurezza e risorse da rimuovere

Il container d’esempio di AWS blocca una versione meno recente di PyTorch associata all’avviso PYSEC-2026-2286. AWS indica PyTorch 2.10.0 come versione in cui l’avviso è corretto e segnala di rivedere il blocco prima di usare il campione oltre una prova di fattibilità.

Per terminare la distribuzione, rimuovi prima il runtime dell’agente e poi l’endpoint SageMaker. I comandi di pulizia descritti da AWS non eliminano il bucket S3 usato per la cache dei pesi né il repository ECR dell’immagine del container: se restano, possono continuare a generare costi di archiviazione.