0Pricing
AI Agents · Pelajaran

Text-to-Speech dalam Respons Agen

API OpenAI TTS, ElevenLabs, dan Google TTS dalam pipeline agen.

Text-to-Speech dalam Respons Agen adalah pelajaran AI Agents gratis di CoddyKit. Ini adalah pelajaran 2 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar AI Agents, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus AI Agents mencakup 4 pelajaran total.

Mengapa Agen Membutuhkan TTS

Agen suara yang hanya mendengarkan tetapi merespons dalam bentuk teks bukanlah agen suara yang sesungguhnya. Text-to-Speech (TTS) mengubah respons teks agen menjadi audio ucapan sehingga melengkapi seluruh siklus suara.

Dua API utama: OpenAI TTS (cepat, terjangkau, 6 suara) dan ElevenLabs (suara yang sangat realistis, penstriman, dan kloning suara).

Dasar-Dasar OpenAI TTS

API TTS OpenAI mengubah teks menjadi ucapan dalam hitungan detik. Enam suara bawaan: alloy, echo, fable, onyx, nova, shimmer. Mendukung format keluaran MP3, opus, AAC, dan 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 OpenAI melalui Penstriman

Untuk mengurangi latensi yang dirasakan, alirkan audio saat dibuat, alih-alih menunggu seluruh berkas selesai. Pemanggil dapat mulai memutar audio saat bagian lainnya masih disintesis.

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)

Deepgram SDK: TTS Berkualitas Tinggi

ElevenLabs menghasilkan suara yang paling realistis. Layanan ini mendukung kloning suara, pengaturan nuansa emosional, dan penstriman.

Instal dengan 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 ElevenLabs melalui Penstriman

ElevenLabs mendukung penstriman—menerima bagian-bagian audio sebelum seluruh teks selesai disintesis. Hal ini penting bagi agen suara yang memerlukan latensi rendah.

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}')

Memutar Audio dengan sounddevice

Setelah membuat audio TTS, putar audio tersebut di perangkat lokal. sounddevice bersama soundfile adalah pilihan lintas platform paling sederhana untuk agen yang berjalan di komputer lokal.

Instal dengan 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?')

Memutar Audio dengan pygame

pygame memberikan kontrol yang lebih besar: Anda dapat memeriksa apakah audio masih diputar, menghentikannya lebih awal, dan memutar beberapa suara. Fitur ini berguna untuk penanganan interupsi pada agen suara.

Instal dengan 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)')

Menyimpan Respons TTS dalam Tembolok

Frasa umum seperti salam, pesan kesalahan, dan perintah menu berulang kali disintesis. Simpan berkas audio tersebut dalam tembolok agar Anda hanya membayar sintesis satu kali untuk setiap frasa.

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 per Kalimat untuk Penstriman

Untuk respons LLM yang panjang, bagi teks menjadi beberapa kalimat, lalu sintesis dan putar setiap kalimat satu per satu. Pengguna dapat mendengar kalimat pertama dalam waktu sekitar 500ms sementara bagian lainnya masih dibuat.

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)

Memilih Suara dan Model

Sesuaikan pilihan suara dengan persona agen. Gunakan suara yang lebih dalam (onyx, echo) untuk agen formal atau profesional, dan suara yang lebih hangat (nova, shimmer) untuk asisten yang bersahabat.

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')

Menyesuaikan Kecepatan Bicara dan Tinggi Nada

Konteks yang berbeda memerlukan karakteristik ucapan yang berbeda. Peringatan notifikasi sebaiknya sedikit lebih cepat, sedangkan penceritaan sebaiknya lebih lambat dan ekspresif. Proses audio TTS setelah sintesis untuk menyesuaikan kecepatan tanpa mengubah tinggi nada.

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

Uji Pemahaman

Apa manfaat utama sintesis TTS per kalimat pada agen suara?

Rangkuman: Teks ke Ucapan dalam Respons Agen

OpenAI TTS (tts-1, tts-1-hd) menyediakan 6 suara dengan sintesis cepat dan dukungan penstriman—ideal untuk sebagian besar agen suara. ElevenLabs menawarkan suara realistis dengan kualitas lebih tinggi melalui eleven_turbo_v2 untuk penstriman berlatensi rendah.

Putar audio dengan sounddevice (sederhana) atau pygame (dapat diinterupsi). Simpan frasa umum dalam tembolok untuk menghilangkan biaya API berulang. Gunakan sintesis per kalimat untuk respons panjang guna meminimalkan latensi yang dirasakan. Penyimpanan TTS dalam tembolok dengan hash MD5 memastikan teks yang sama selalu disajikan dari tembolok.

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Text-to-Speech dalam Respons Agen” gratis?

Ya — teks lengkap “Text-to-Speech dalam Respons Agen” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus AI Agents, upgrade ke CoddyKit PRO. Kursus AI Agents mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “Text-to-Speech dalam Respons Agen”?

API OpenAI TTS, ElevenLabs, dan Google TTS dalam pipeline agen. Kamu berlatih AI Agents dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai AI Agents?

Tidak diperlukan pengalaman sebelumnya. AI Agents di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 2 dari 4.

Berapa lama pelajaran “Text-to-Speech dalam Respons Agen” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran AI Agents ini?

Ya. Setiap pelajaran AI Agents menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. Speech-to-Text dengan Whisper dan Deepgram
  2. Text-to-Speech dalam Respons Agen
  3. Membangun Putaran Percakapan Suara
  4. Optimasi Latensi untuk Agen Suara
← Kembali ke AI Agents