Nâng caoHướng dẫnClaude APINguồn: Anthropic

Voice Assistant với ElevenLabs + Claude — Trợ lý giọng nói

Nghe bài viết
00:00

Điểm nổi bật

Nhấn để đến mục tương ứng

  1. 1 Để áp dụng kiến trúc voice assistant hiệu quả, bạn cần nắm rõ: Microphone --Deepgram STT--&gt Text Text --Claude LLM --&gt Response text Text --ElevenLabs --&gt Audio Audio --&gt Speaker — đây là bước quan trọng giúp tối ưu quy trình làm việc với AI trong thực tế.
  2. 2 Về elevenlabs tts — text thành giọng nói, thực tế cho thấy ElevenLabs cung cấp nhiều giọng nói pre-built và API để generate audio: """Liệt kê tất cả voices có sẵn.""" voices_response eleven.voices.get_all voices for voice in voices_response.voices: voices.append "id": voice.voice_id, "name": voice.name, "category": voice.category, "labels": voice.labels return voices text, voice_id"21m00Tcm4T — đây là con dao hai lưỡi nếu không hiểu rõ giới hạn và điều kiện áp dụng của nó.
  3. 3 Kết quả đo lường từ streaming tts cho low latency: Để giảm latency, stream audio ngay khi Claude bắt đầu generate text: as sd as np voice_id"21m00Tcm4TlvDq8ikWAM": """Stream TTS và play ngay khi có audio.""" audio_stream eleven.generate texttext, voicevoice_id, model"eleven_multilingual_v2", streamTrue # Collect chunks và play audio_chunks — các chỉ số cụ thể này giúp bạn đánh giá chính xác hiệu quả trước khi đầu tư nguồn lực.
  4. 4 Bước thực hành then chốt trong streaming claude + tts pipeline: Kỹ thuật nâng cao: stream response từ Claude và feed từng câu vào TTS để minimize perceived latency: conversation_historyNone, voice_id"21m00Tcm4TlvDq8ikWAM": """ Stream response từ Claude, feed câu hoàn chỉnh vào TTS ngay lập tức — nắm vững điều này giúp bạn triển khai nhanh hơn và giảm thiểu lỗi thường gặp.
  5. 5 Góc nhìn thực tế về complete voice assistant loop: as sd as np sample_rate16000: """Record audio từ microphone.""" printf"Recording durations... Speak now" audio sd.rec intduration * sample_rate, sampleratesample_rate, channels1, dtypenp.int16 sd.wait return audio.tobytes async language"vi": """STT từ raw audio bytes.""" payload — hiệu quả phụ thuộc nhiều vào cách triển khai và ngữ cảnh sử dụng cụ thể.
a close up of a computer screen with code on it

Voice assistant hoàn chỉnh cần ba thành phần: STT (Speech-to-Text — nghe người dùng), LLM (xử lý và trả lời), và TTS (Text-to-Speech — nói lại). Bài này xây dựng pipeline kết hợp Deepgram STT + Claude + ElevenLabs TTS — tạo voice assistant chất lượng cao với giọng nói tự nhiên.

ElevenLabs là TTS service hàng đầu với giọng nói cực kỳ tự nhiên, hỗ trợ tiếng Việt, và cho phép clone giọng nói tùy chỉnh.

Kiến trúc Voice Assistant

Microphone  --[Deepgram STT]-->  Text
    Text    --[Claude LLM]  -->  Response text
    Text    --[ElevenLabs]  -->  Audio
  Audio     -->  Speaker

Cài đặt

pip install anthropic deepgram-sdk elevenlabs pyaudio sounddevice numpy
import os
import asyncio
import anthropic
from elevenlabs.client import ElevenLabs
from elevenlabs import VoiceSettings
from deepgram import DeepgramClient, PrerecordedOptions

claude = anthropic.Anthropic(api_key=os.environ.get("ANTHROPIC_API_KEY"))
eleven = ElevenLabs(api_key=os.environ.get("ELEVENLABS_API_KEY"))
deepgram = DeepgramClient(api_key=os.environ.get("DEEPGRAM_API_KEY"))

print("Voice assistant components initialized")

ElevenLabs TTS — Text thành giọng nói

ElevenLabs cung cấp nhiều giọng nói pre-built và API để generate audio:

def list_available_voices():
    """Liệt kê tất cả voices có sẵn."""
    voices_response = eleven.voices.get_all()
    voices = []
    for voice in voices_response.voices:
        voices.append({
            "id": voice.voice_id,
            "name": voice.name,
            "category": voice.category,
            "labels": voice.labels
        })
    return voices

def text_to_speech(
    text,
    voice_id="21m00Tcm4TlvDq8ikWAM",  # Rachel - tự nhiên, rõ ràng
    model_id="eleven_multilingual_v2",   # Hỗ trợ tiếng Việt
    output_path=None
):
    """
    Chuyển text thành audio với ElevenLabs.

    Args:
        text: Nội dung cần đọc
        voice_id: ID của voice (lấy từ list_available_voices)
        model_id: Model TTS (multilingual_v2 cho tiếng Việt)
        output_path: Lưu file nếu cần, None để stream

    Returns:
        Audio bytes hoặc path đến file
    """
    audio = eleven.generate(
        text=text,
        voice=voice_id,
        model=model_id,
        voice_settings=VoiceSettings(
            stability=0.5,          # 0-1, cao = ổn định hơn
            similarity_boost=0.8,   # 0-1, cao = giống voice hơn
            style=0.0,              # Style exaggeration
            use_speaker_boost=True  # Tăng chất lượng
        )
    )

    audio_bytes = b"".join(audio)

    if output_path:
        with open(output_path, "wb") as f:
            f.write(audio_bytes)
        return output_path

    return audio_bytes

# Test TTS
audio_data = text_to_speech(
    "Xin chào! Tôi là trợ lý AI của bạn. Tôi có thể giúp gì cho bạn?",
    output_path="greeting.mp3"
)
print(f"Generated audio: {len(audio_data)} bytes")

Streaming TTS cho low latency

Để giảm latency, stream audio ngay khi Claude bắt đầu generate text:

import sounddevice as sd
import numpy as np
import io
from pydub import AudioSegment

def stream_tts(text, voice_id="21m00Tcm4TlvDq8ikWAM"):
    """Stream TTS và play ngay khi có audio."""
    audio_stream = eleven.generate(
        text=text,
        voice=voice_id,
        model="eleven_multilingual_v2",
        stream=True
    )

    # Collect chunks và play
    audio_chunks = []
    for chunk in audio_stream:
        if chunk:
            audio_chunks.append(chunk)

    # Convert và play
    audio_bytes = b"".join(audio_chunks)
    audio = AudioSegment.from_mp3(io.BytesIO(audio_bytes))

    # Convert to numpy array cho sounddevice
    samples = np.array(audio.get_array_of_samples(), dtype=np.float32)
    samples = samples / (2**15)  # Normalize to [-1, 1]

    sd.play(samples, audio.frame_rate)
    sd.wait()  # Chờ finish

Streaming Claude + TTS Pipeline

Kỹ thuật nâng cao: stream response từ Claude và feed từng câu vào TTS để minimize perceived latency:

import re

def stream_claude_to_tts(user_message, conversation_history=None, voice_id="21m00Tcm4TlvDq8ikWAM"):
    """
    Stream response từ Claude, feed câu hoàn chỉnh vào TTS ngay lập tức.
    Giảm latency từ 3-5s xuống còn ~1s perceived.
    """
    messages = conversation_history or []
    messages.append({"role": "user", "content": user_message})

    full_response = ""
    sentence_buffer = ""
    tts_tasks = []

    # Stream Claude response
    with claude.messages.stream(
        model="claude-haiku-4-5",  # Haiku nhanh nhất
        max_tokens=1024,
        system="""Bạn là voice assistant thông minh. Trả lời ngắn gọn, tự nhiên,
        phù hợp khi đọc to. Không dùng bullet points, markdown, hay code blocks.
        Tối đa 2-3 câu mỗi lần trả lời.""",
        messages=messages
    ) as stream:
        for text in stream.text_stream:
            full_response += text
            sentence_buffer += text

            # Detect câu hoàn chỉnh (kết thúc bằng . ! ? hoặc ...)
            sentences = re.split(r'(?<=[.!?])s+', sentence_buffer)

            if len(sentences) > 1:
                # Có ít nhất 1 câu hoàn chỉnh
                complete_sentence = sentences[0].strip()
                sentence_buffer = " ".join(sentences[1:])

                if complete_sentence:
                    print(f"[TTS] {complete_sentence}")
                    # Generate TTS cho câu này (trong production: async)
                    audio = text_to_speech(complete_sentence, voice_id)
                    tts_tasks.append(audio)

        # Xử lý phần còn lại
        if sentence_buffer.strip():
            audio = text_to_speech(sentence_buffer.strip(), voice_id)
            tts_tasks.append(audio)

    # Play tất cả audio chunks theo thứ tự
    for audio_chunk in tts_tasks:
        play_audio(audio_chunk)

    return full_response, messages

def play_audio(audio_bytes):
    """Play audio bytes."""
    import io
    from pydub import AudioSegment, playback

    audio = AudioSegment.from_mp3(io.BytesIO(audio_bytes))
    playback.play(audio)

Complete Voice Assistant Loop

import sounddevice as sd
import numpy as np

def record_audio(duration=5, sample_rate=16000):
    """Record audio từ microphone."""
    print(f"Recording {duration}s... (Speak now)")
    audio = sd.rec(
        int(duration * sample_rate),
        samplerate=sample_rate,
        channels=1,
        dtype=np.int16
    )
    sd.wait()
    return audio.tobytes()

async def stt_from_bytes(audio_bytes, language="vi"):
    """STT từ raw audio bytes."""
    payload = {"buffer": audio_bytes}
    options = PrerecordedOptions(
        model="nova-2",
        language=language,
        punctuate=True,
        smart_format=True
    )
    response = await deepgram.listen.asyncprerecorded.v("1").transcribe_file(
        payload, options
    )
    return response.results.channels[0].alternatives[0].transcript

def voice_assistant():
    """Main voice assistant loop."""
    conversation_history = []
    voice_id = "21m00Tcm4TlvDq8ikWAM"  # Rachel

    print("
Voice Assistant ready!")
    print("Press Enter to speak, Ctrl+C to quit
")

    # Greeting
    greeting = "Xin chào! Tôi là trợ lý AI. Tôi có thể giúp gì cho bạn?"
    print(f"Assistant: {greeting}")
    stream_tts(greeting, voice_id)

    while True:
        try:
            input("Press Enter to speak...")

            # Step 1: Record audio
            audio_bytes = record_audio(duration=7)

            # Step 2: Transcribe
            print("Transcribing...")
            user_text = asyncio.run(stt_from_bytes(audio_bytes))

            if not user_text.strip():
                print("Không nghe thấy gì. Thử lại.")
                continue

            print(f"
You: {user_text}")

            # Step 3: Generate response + TTS
            print("Thinking...")
            response_text, conversation_history = stream_claude_to_tts(
                user_text,
                conversation_history,
                voice_id
            )

            print(f"Assistant: {response_text}
")

        except KeyboardInterrupt:
            print("
Goodbye!")
            break

# Chạy voice assistant
# voice_assistant()

Voice Cloning — Giọng tùy chỉnh

ElevenLabs cho phép clone giọng nói từ audio samples:

def clone_voice(name, audio_files, description=""):
    """
    Clone giọng nói từ audio samples.

    Args:
        name: Tên cho voice mới
        audio_files: List đường dẫn đến audio files (1-25 files, 1-5 phút mỗi file)
        description: Mô tả về giọng nói

    Returns:
        voice_id của voice mới tạo
    """
    # Mở files
    files = []
    for path in audio_files:
        files.append(open(path, "rb"))

    try:
        voice = eleven.clone(
            name=name,
            description=description,
            files=files
        )
        print(f"Voice cloned: {voice.voice_id}")
        return voice.voice_id
    finally:
        for f in files:
            f.close()

# Ví dụ: Clone giọng nói của bạn
# my_voice_id = clone_voice(
#     name="My Voice",
#     audio_files=["sample1.mp3", "sample2.mp3"],
#     description="Vietnamese male voice, professional"
# )

Kết luận

Voice assistant với ElevenLabs + Claude + Deepgram là stack hoàn chỉnh cho voice AI applications. ElevenLabs cung cấp giọng nói tự nhiên nhất trên thị trường, Deepgram xử lý STT chính xác, và Claude đảm bảo chất lượng AI reasoning.

Bước tiếp theo: Khám phá Deepgram + Claude để hiểu sâu hơn về STT, hoặc đọc về Wolfram Alpha + Claude để thêm tính toán chính xác vào voice assistant.


Bài viết liên quan

Tính năng liên quan:Text-to-SpeechElevenLabsVoice AssistantReal-time

Bai viet co huu ich khong?

Bản quyền thuộc về tác giả. Vui lòng dẫn nguồn khi chia sẻ.

Bình luận (0)
Ảnh đại diện
Đăng nhập để bình luận...
Đăng nhập để bình luận
  • Đang tải bình luận...

Đăng ký nhận bản tin

Nhận bài viết hay nhất về sản phẩm và vận hành, gửi thẳng vào hộp thư của bạn.

Bảo mật thông tin. Hủy đăng ký bất cứ lúc nào. Chính sách bảo mật.