0Pricing
AI Agents · Lezione

Text-to-Speech nelle risposte degli agenti

API OpenAI TTS, ElevenLabs e Google TTS nelle pipeline degli agenti

Text-to-Speech nelle risposte degli agenti è una lezione AI Agents gratuita su CoddyKit. Questa è la lezione 2 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento AI Agents, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso AI Agents include 4 lezioni in totale.

Perché gli agenti hanno bisogno del TTS

Un agente vocale che ascolta soltanto ma risponde con testo non è un vero agente vocale. Text-to-Speech (TTS) converte le risposte testuali dell'agente in audio parlato, completando l'intero ciclo vocale.

Due API principali: OpenAI TTS (veloce, conveniente, 6 voci) e ElevenLabs (voci ultra-realistiche, streaming e clonazione della voce).

Nozioni di base su OpenAI TTS

L'API TTS di OpenAI converte il testo in parlato in pochi secondi. Sei voci integrate: alloy, echo, fable, onyx, nova, shimmer. Supporta i formati di output MP3, opus, AAC e FLAC.

import openai
import os

client = openai.OpenAI(api_key=os.getenv('OPENAI_API_KEY'))

def text_to_speech(text, voice='alloy', output_path='response.mp3'):
    response = client.audio.speech.create(
        model='tts-1',          # tts-1 (fast) or tts-1-hd (higher quality)
        voice=voice,            # alloy, echo, fable, onyx, nova, shimmer
        input=text,
        response_format='mp3'   # mp3, opus, aac, flac
    )
    with open(output_path, 'wb') as f:
        f.write(response.content)
    print(f'Audio saved to: {output_path}')
    return output_path

# Available voices:
# alloy    - neutral, balanced
# echo     - warm, conversational
# fable    - expressive
# onyx     - deep, authoritative
# nova     - friendly, upbeat
# shimmer  - soft, clear

TTS in streaming con OpenAI

Per ridurre la latenza percepita, trasmetta l'audio in streaming man mano che viene generato invece di attendere il file completo. Chi effettua la chiamata può iniziare a riprodurre l'audio mentre il resto viene ancora sintetizzato.

import openai
import os

client = openai.OpenAI(api_key=os.getenv('OPENAI_API_KEY'))

def stream_tts_to_file(text, output_path, voice='nova'):
    with client.audio.speech.with_streaming_response.create(
        model='tts-1',
        voice=voice,
        input=text
    ) as response:
        response.stream_to_file(output_path)
    return output_path

def stream_tts_to_bytes(text, voice='nova'):
    audio_chunks = []
    with client.audio.speech.with_streaming_response.create(
        model='tts-1',
        voice=voice,
        input=text
    ) as response:
        for chunk in response.iter_bytes(chunk_size=4096):
            audio_chunks.append(chunk)
    return b''.join(audio_chunks)

ElevenLabs SDK: TTS di alta qualità

ElevenLabs produce alcune tra le voci più realistiche disponibili. Supporta la clonazione della voce, il controllo del tono emotivo e lo streaming.

Installi il pacchetto con pip install elevenlabs.

from elevenlabs import ElevenLabs, VoiceSettings
import os

client = ElevenLabs(api_key=os.getenv('ELEVENLABS_API_KEY'))

def elevenlabs_tts(text, voice_id='pNInz6obpgDQGcFmaJgB', output_path='response.mp3'):
    # Common voice IDs:
    # Rachel:  21m00Tcm4TlvDq8ikWAM
    # Adam:    pNInz6obpgDQGcFmaJgB
    # Bella:   EXAVITQu4vr4xnSDxMaL

    audio = client.generate(
        text=text,
        voice=voice_id,
        model='eleven_multilingual_v2',  # supports 29 languages
        voice_settings=VoiceSettings(
            stability=0.5,        # 0.0-1.0: lower = more expressive
            similarity_boost=0.8, # 0.0-1.0: higher = closer to original voice
            style=0.3             # 0.0-1.0: style exaggeration
        )
    )

    with open(output_path, 'wb') as f:
        for chunk in audio:
            f.write(chunk)

    return output_path

TTS in streaming con ElevenLabs

ElevenLabs supporta lo streaming: riceva i blocchi audio prima che venga sintetizzato l'intero testo. Questo è fondamentale per gli agenti vocali, nei quali la latenza è importante.

from elevenlabs import ElevenLabs
import os

client = ElevenLabs(api_key=os.getenv('ELEVENLABS_API_KEY'))

def streaming_tts(text, voice_id='pNInz6obpgDQGcFmaJgB'):
    audio_stream = client.generate(
        text=text,
        voice=voice_id,
        model='eleven_turbo_v2',  # fastest model, optimized for streaming
        stream=True
    )
    return audio_stream  # yields audio chunks as they are generated

def stream_to_file(text, output_path, voice_id='pNInz6obpgDQGcFmaJgB'):
    stream = streaming_tts(text, voice_id)
    with open(output_path, 'wb') as f:
        for chunk in stream:
            if chunk:
                f.write(chunk)
    print(f'Streaming TTS complete: {output_path}')

Riproduzione dell'audio con sounddevice

Dopo aver generato l'audio TTS, lo riproduca sul dispositivo locale. sounddevice insieme a soundfile è l'opzione multipiattaforma più semplice per un agente in esecuzione su una macchina locale.

Installi i pacchetti con pip install sounddevice soundfile.

import sounddevice as sd
import soundfile as sf
import numpy as np
import tempfile
import os

def play_audio_file(audio_path):
    data, sample_rate = sf.read(audio_path)
    sd.play(data, sample_rate)
    sd.wait()  # block until playback finishes

def play_mp3_bytes(audio_bytes):
    # Write to temp file then play (soundfile needs a file)
    with tempfile.NamedTemporaryFile(suffix='.mp3', delete=False) as f:
        f.write(audio_bytes)
        tmp_path = f.name
    try:
        play_audio_file(tmp_path)
    finally:
        os.unlink(tmp_path)

def say(text, voice='nova'):
    audio_bytes = stream_tts_to_bytes(text, voice=voice)
    play_mp3_bytes(audio_bytes)

# Usage
say('Hello! How can I help you today?')

Riproduzione dell'audio con pygame

pygame offre un controllo maggiore: è possibile verificare se l'audio è ancora in riproduzione, interromperlo in anticipo e riprodurre più suoni. È utile per gestire le interruzioni negli agenti vocali.

Installi il pacchetto con pip install pygame.

import pygame
import io
import tempfile
import os

pygame.mixer.init(frequency=44100, size=-16, channels=1, buffer=512)

def play_audio_pygame(audio_bytes):
    with tempfile.NamedTemporaryFile(suffix='.mp3', delete=False) as f:
        f.write(audio_bytes)
        tmp_path = f.name

    try:
        pygame.mixer.music.load(tmp_path)
        pygame.mixer.music.play()
        while pygame.mixer.music.get_busy():
            pygame.time.wait(50)  # check every 50ms
    finally:
        pygame.mixer.music.stop()
        os.unlink(tmp_path)

def stop_audio():
    if pygame.mixer.music.get_busy():
        pygame.mixer.music.stop()
        print('Audio stopped (interrupt)')

Memorizzazione nella cache delle risposte TTS

Frasi comuni come saluti, messaggi di errore e prompt dei menu vengono sintetizzate ripetutamente. Memorizzi i relativi file audio nella cache, così pagherà la sintesi una sola volta per frase.

import hashlib
import os

TTS_CACHE_DIR = '/tmp/tts_cache'
os.makedirs(TTS_CACHE_DIR, exist_ok=True)

def cached_tts(text, voice='nova'):
    cache_key = hashlib.md5(f'{voice}:{text}'.encode()).hexdigest()
    cache_path = os.path.join(TTS_CACHE_DIR, f'{cache_key}.mp3')

    if os.path.exists(cache_path):
        print('TTS cache hit')
        return cache_path

    # Generate and save
    audio_bytes = stream_tts_to_bytes(text, voice=voice)
    with open(cache_path, 'wb') as f:
        f.write(audio_bytes)

    print(f'TTS cached: {cache_path}')
    return cache_path

# Pre-warm cache for common phrases on startup
COMMON_PHRASES = [
    'Hello! How can I help you today?',
    'I did not catch that. Could you repeat?',
    'Let me look that up for you.',
    'Thank you, goodbye!'
]

def prewarm_tts_cache():
    for phrase in COMMON_PHRASES:
        cached_tts(phrase)
    print(f'Pre-warmed {len(COMMON_PHRASES)} phrases')

TTS frase per frase per lo streaming

Per le risposte LLM lunghe, suddivida il testo in frasi e le sintetizzi e riproduca una alla volta. L'utente ascolta la prima frase entro circa 500 ms, mentre il resto viene ancora generato.

import re

def split_into_sentences(text):
    sentences = re.split(r'(?<=[.!?])\s+', text.strip())
    return [s.strip() for s in sentences if s.strip()]

def stream_response_as_voice(llm_response_text, voice='nova'):
    sentences = split_into_sentences(llm_response_text)
    print(f'Speaking {len(sentences)} sentences')

    for i, sentence in enumerate(sentences):
        if not sentence:
            continue
        print(f'Speaking ({i+1}/{len(sentences)}): {sentence[:60]}')
        cache_path = cached_tts(sentence, voice=voice)
        play_audio_file(cache_path)

# Example
response = 'The weather today is sunny and 22 degrees. Perfect for outdoor activities. Bring sunscreen if you plan to be outside for more than an hour.'
stream_response_as_voice(response)

Scelta della voce e del modello

Abbini la scelta della voce alla personalità dell'agente. Utilizzi voci più profonde (onyx, echo) per agenti formali o professionali e voci più calde (nova, shimmer) per assistenti amichevoli.

VOICE_PROFILES = {
    'assistant':    {'service': 'openai',     'voice': 'nova',   'model': 'tts-1'},
    'professional': {'service': 'openai',     'voice': 'onyx',   'model': 'tts-1-hd'},
    'narrator':     {'service': 'openai',     'voice': 'fable',  'model': 'tts-1-hd'},
    'premium':      {'service': 'elevenlabs', 'voice_id': '21m00Tcm4TlvDq8ikWAM', 'model': 'eleven_multilingual_v2'}
}

def speak(text, persona='assistant'):
    profile = VOICE_PROFILES.get(persona, VOICE_PROFILES['assistant'])

    if profile['service'] == 'openai':
        audio_bytes = stream_tts_to_bytes(text, voice=profile['voice'])
        play_mp3_bytes(audio_bytes)
    elif profile['service'] == 'elevenlabs':
        output_path = elevenlabs_tts(text, voice_id=profile['voice_id'])
        play_audio_file(output_path)

speak('Your meeting has been rescheduled.', persona='professional')

Regolazione della velocità e dell'intonazione

Contesti diversi richiedono caratteristiche vocali diverse. Gli avvisi di notifica dovrebbero essere leggermente più veloci, mentre la narrazione dovrebbe essere più lenta ed espressiva. Elabori l'audio TTS dopo la sintesi per regolare la velocità senza modificare l'intonazione.

from pydub import AudioSegment
from pydub.effects import speedup
import os

def adjust_speech_speed(audio_path, speed_factor=1.0, output_path=None):
    if speed_factor == 1.0:
        return audio_path

    audio = AudioSegment.from_file(audio_path)

    if speed_factor > 1.0:
        # Speed up without changing pitch
        audio = speedup(audio, playback_speed=speed_factor)
    else:
        # Slow down: overlay with silence (simple method)
        # For production: use ffmpeg with atempo filter
        slow_factor = 1.0 / speed_factor
        audio = audio._spawn(
            audio.raw_data,
            overrides={'frame_rate': int(audio.frame_rate / slow_factor)}
        ).set_frame_rate(audio.frame_rate)

    if output_path is None:
        base = os.path.splitext(audio_path)[0]
        output_path = f'{base}_speed{speed_factor}.mp3'

    audio.export(output_path, format='mp3')
    return output_path

# Usage
path = text_to_speech('Your meeting starts in 5 minutes.')
fast_path = adjust_speech_speed(path, speed_factor=1.2)  # 20% faster for alerts

Verifica delle conoscenze

Qual è il principale vantaggio della sintesi TTS frase per frase in un agente vocale?

Riepilogo: Text-to-Speech nelle risposte dell'agente

OpenAI TTS (tts-1, tts-1-hd) offre 6 voci, sintesi rapida e supporto allo streaming: è ideale per la maggior parte degli agenti vocali. ElevenLabs offre voci realistiche di qualità superiore con eleven_turbo_v2 per lo streaming a bassa latenza.

Riproduca l'audio con sounddevice (semplice) o pygame (interrompibile). Memorizzi nella cache le frasi comuni per eliminare i costi ripetuti delle API. Utilizzi la sintesi frase per frase per le risposte lunghe, così da ridurre al minimo la latenza percepita. La memorizzazione nella cache del TTS con hash MD5 garantisce che lo stesso testo venga sempre fornito dalla cache.

Domande Frequenti

La lezione «Text-to-Speech nelle risposte degli agenti» è gratuita?

Sì — il testo completo di «Text-to-Speech nelle risposte degli agenti» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso AI Agents, passa a CoddyKit PRO. Il corso AI Agents include 4 lezioni in totale.

Cosa imparerò in «Text-to-Speech nelle risposte degli agenti»?

API OpenAI TTS, ElevenLabs e Google TTS nelle pipeline degli agenti Eserciti AI Agents con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare AI Agents?

Non è richiesta alcuna esperienza precedente. AI Agents su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 2 di 4.

Quanto tempo richiede la lezione «Text-to-Speech nelle risposte degli agenti»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione AI Agents?

Sì. Ogni lezione AI Agents include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Speech-to-Text con Whisper e Deepgram
  2. Text-to-Speech nelle risposte degli agenti
  3. Creazione di un ciclo di conversazione vocale
  4. Ottimizzazione della latenza per gli agenti vocali
← Torna a AI Agents