Product Management
Đăng nhập
ESC

Nhập từ khóa để tìm kiếm

↑↓ Di chuyển
Enter Mở
ESC Đóng

Bài 3 — TTS và độ trễ: làm agent nói tự nhiên và nhanh

Đã đọc 0/9 mục · còn khoảng 4 phút
Cách chúng tôi ghi nhận

Một mục được tính là đã đọc khi nó nằm giữa màn hình đủ lâu so với độ dài của nó (bảng và sơ đồ tính một nửa), bạn vẫn đang cuộn hoặc bấm phím, và bạn đã thấy tới cuối mục. Lướt nhanh hoặc để tab mở không được tính. Chúng tôi chỉ lưu thời gian đọc từng mục — không lưu gì khác.

TTS là nơi agent "mở miệng". Hai chỉ số quan trọng nhất: độ tự nhiên (nghe có giống người) và time-to-first-audio (bao lâu để phát ra âm thanh đầu tiên). Người dùng cảm nhận độ trễ mạnh nhất ở đây, vì họ đang chờ nghe.

Time-to-first-byte/audio (TTFB): chỉ số vàng

Đừng đo tổng thời gian sinh cả câu. Đo thời gian tới byte audio đầu tiên. Nếu TTS bắt đầu phát sau 200ms, hội thoại mượt; nếu sau 1.5s, khách tưởng máy đơ.

Mẹo cốt lõi: streaming TTS. Thay vì chờ sinh xong toàn bộ câu, phát audio ngay khi từng phần được tạo.

# Nối LLM streaming vào TTS streaming để giảm TTFB
sentence_buf = ""
for token in llm_stream(prompt):
    sentence_buf += token
    if ends_sentence(sentence_buf):          # gặp . ! ? hoặc dấu ngắt
        for audio_chunk in tts_stream(sentence_buf):
            speaker.play(audio_chunk)          # phát ngay
        sentence_buf = ""

Bí quyết: không chờ LLM sinh xong cả câu trả lời rồi mới gọi TTS. Ngắt theo câu (hoặc cụm), gửi câu đầu tiên đi TTS ngay khi có, trong lúc LLM vẫn đang sinh câu tiếp theo.

Ngân sách độ trễ end-to-end

Hãy phân bổ như một ngân sách tiền bạc. Ví dụ mục tiêu 800ms từ khi khách dứt lời:

  • Endpointing/mạng: ~150ms
  • ASR final: ~100ms
  • LLM time-to-first-token: ~300ms
  • TTS time-to-first-audio: ~150ms
  • Đệm phát/mạng ra: ~100ms
Mỗi khối vượt ngân sách thì cả hệ thống chậm. Bạn phải đo từng khối riêng, không đo mỗi tổng.

Điều khiển giọng bằng SSML

SSML (Speech Synthesis Markup Language) cho phép kiểm soát ngắt nghỉ, nhấn, tốc độ, cách đọc số:

<speak>
  Dạ số dư của mình là
  <say-as interpret-as="cardinal">1250000</say-as> đồng.
  <break time="300ms"/>
  Mình cần em hỗ trợ gì thêm không ạ?
</speak>

Các bước tinh chỉnh giọng:

  • Chọn voice phù hợp thương hiệu (giới tính, vùng miền, độ trẻ).
  • Dùng <break> để tạo nhịp tự nhiên, tránh đọc như đọc máy.
  • Dùng <say-as> cho số điện thoại, tiền, ngày để đọc đúng.
  • Điều chỉnh rate chậm lại một chút khi đọc thông tin quan trọng.

Cache những câu cố định

Các câu lặp lại ("Dạ em nghe", "Cảm ơn quý khách đã gọi") nên cache audio sẵn. Không cần gọi TTS mỗi lần → TTFB gần như 0 cho lời chào. Hãy lập danh sách các câu tĩnh trong kịch bản (chào đầu, chờ máy, xác nhận, tạm biệt), sinh audio một lần và lưu lại. Với câu nửa tĩnh ("Dạ đơn hàng số ..."), cache phần cố định và chỉ TTS phần biến đổi rồi ghép lại.

Codec và sample rate theo kênh

Độ trễ và chất lượng còn phụ thuộc kênh phát. Điện thoại (PSTN) thường 8kHz codec nén; web (WebRTC) dùng Opus 48kHz. Các bước cần làm:

  • Xác định kênh đích trước khi chọn voice và định dạng TTS.
  • Sinh audio đúng sample rate của kênh để tránh resample tốn thời gian và méo tiếng.
  • Chọn định dạng streaming (ví dụ PCM/Opus theo chunk) để phát dần thay vì tải nguyên file.
  • Test nghe thật trên chính kênh đó, đừng nghe trên tai nghe studio rồi kết luận.

Cân bằng chất lượng và tốc độ

Voice chất lượng cao nhất đôi khi trễ hơn. Hãy thử nhiều mức: nếu use case là tổng đài đông khách, một voice trễ thấp hơn một chút thường thắng voice "đẹp nhất" nhưng chậm. Đo cả TTFB lẫn điểm đánh giá độ tự nhiên (MOS chủ quan) rồi chọn điểm cân bằng phù hợp thương hiệu.

Checklist tối ưu độ trễ TTS

  • [ ] Dùng streaming TTS, phát theo câu/cụm?
  • [ ] Nối LLM-streaming vào TTS-streaming (không chờ trọn câu trả lời)?
  • [ ] Đo TTFB riêng, không chỉ tổng thời gian?
  • [ ] Cache audio cho câu chào/xác nhận cố định?
  • [ ] SSML cho số, tiền, ngày, ngắt nghỉ?
  • [ ] Chọn codec/sample rate khớp kênh (điện thoại vs web)?

Sai lầm thường gặp

  • Chờ sinh xong toàn câu trả lời của LLM rồi mới gọi TTS. Đây là nguyên nhân số một gây trễ. Hãy stream theo câu.
  • Đo tổng thời gian thay vì TTFB. Tổng có thể dài nhưng nếu audio đầu phát nhanh, khách vẫn thấy mượt.
  • Bỏ qua ngắt nghỉ. Giọng đọc liền một mạch không dấu ngắt nghe như robot dù voice có xịn.
  • Không cache lời chào. Lãng phí độ trễ cho câu bạn biết trước 100%.
  • Đọc sai số/tiền. "1250000" đọc thành "một hai năm không..." khiến khách bối rối; luôn dùng say-as.
Học xong bài này rồi? Tạo tài khoản miễn phí để lưu lại — lần sau vào là biết ngay đang dở ở đâu, và học hết khóa thì có chứng chỉ. Lưu tiến độ của tôi