Developer Guide

SeaVoice Integration Guide

Hướng dẫn chi tiết triển khai tích hợp dịch vụ SeaVoice Enterprise TTS API v2.1.0 vào bất kỳ dự án nào

Hướng Dẫn Tích Hợp SeaVoice Enterprise TTS API v2.1.0

Tài liệu kỹ thuật chi tiết dành cho kỹ sư phần mềm / đội ngũ phát triển để triển khai tích hợp dịch vụ chuyển đổi văn bản thành giọng nói (SeaVoice Enterprise TTS), nhân bản giọng nói (Voice Cloning), thiết kế giọng nói (Voice Design) và tự động chọn giọng (Auto Voice) vào bất kỳ hệ thống nào (Node.js/TypeScript, Python, Go, Java, PHP, v.v.).


1. Tổng Quan Về SeaVoice API

SeaVoice Enterprise TTS là giải pháp giọng nói AI thế hệ mới (phiên bản v2.1.0), tối ưu hóa đặc biệt cho tiếng Việt và tiếng Anh với khả năng:

  • TTS chuẩn qua Voice ID: Sinh âm thanh tự nhiên từ kho giọng đăng ký sẵn hoặc hệ thống chuẩn.
  • Voice Cloning (Nhân bản giọng nói tức thì): Sao chép đặc trưng giọng nói từ một đoạn file âm thanh mẫu (ref_audio) hoặc từ tensor đặc trưng (prompt_id).
  • Voice Design (Thiết kế giọng theo mô tả): Tạo ra giọng nói độc bản hoàn toàn mới bằng các thuộc tính âm học tự nhiên (giới tính, độ tuổi, cao độ âm vực, phong cách thì thầm, ngữ điệu vùng miền).
  • Auto Voice (Tự động nhận diện ngữ cảnh): Tự động phân tích ngữ cảnh của văn bản để lựa chọn giọng đọc và biểu cảm phù hợp.
  • Biểu cảm phi ngôn ngữ (Non-verbal Emotion Tags): Hỗ trợ chèn các thẻ cảm xúc tự nhiên trực tiếp vào nội dung văn bản (ví dụ: cười [laughter], thở dài [sigh], thì thầm [whisper], v.v.).

2. Thông Số Kỹ Thuật & Cấu Hình Môi Trường

2.1. Endpoint & Tài Liệu

  • Base URL chính: https://api.seavoice.seateklab.vn
  • Swagger / API Docs: https://api.seavoice.seateklab.vn/docs
  • Format trả về:
    • audio/wav (Binary stream - tối ưu tốc độ và bộ nhớ).
    • application/json (Base64 chuỗi audio).

2.2. Biến Môi Trường Khuyến Nghị Cho Dự Án

# URL API của SeaVoice (mặc định trỏ đến cụm Enterprise)
SEAVOICE_BASE_URL=https://api.seavoice.seateklab.vn

# Thời gian chờ tối đa (mili-giây) - tác vụ TTS sinh model GPU có thể mất 3-15s
SEAVOICE_TIMEOUT_MS=60000

# Đơn giá tham chiếu (nếu hệ thống có module tính quota/billing)
# Quy ước tham chiếu: 1 ký tự = 1 VNĐ
SEAVOICE_CHAR_PRICE_VND=1

3. Kiến Trúc Tích Hợp Khuyến Nghị (Architecture Design)

Đối với các dự án production (Web App, Mobile App, Microservices), không nên gọi trực tiếp SeaVoice API từ client (Browser/Mobile) mà nên đi qua tầng Backend Service:

Lợi ích của kiến trúc này:

  1. Bảo mật & Quản trị: Ẩn endpoint nội bộ, kiểm soát quota và chi phí của từng tài khoản người dùng.
  2. Lưu trữ vĩnh viễn (Persistence): Âm thanh sau khi sinh được lưu vào kho lưu trữ đối tượng (S3, Cloudflare R2, Google Cloud Storage), tránh phụ thuộc vào retention policy của API.
  3. Hiệu năng & Caching: Cho phép cache lại kết quả nếu cùng một đoạn văn bản và Voice ID được yêu cầu nhiều lần.

4. Chi Tiết Các API Endpoints

4.1. Kiểm Tra Sức Khỏe Dịch Vụ & GPU (GET /health)

Dùng cho health check định kỳ, uptime monitoring hoặc readiness probe trong Kubernetes.

  • Method: GET
  • Path: /health
  • Response: 200 OK
{
  "status": "healthy",
  "gpu_available": true,
  "model_loaded": true,
  "version": "2.1.0"
}

4.2. Sinh Giọng Nói Từ Voice ID (POST /v1/tts/generate)

Sinh giọng nói nhanh từ một voice_id đã có sẵn trong danh mục.

  • Method: POST
  • Path: /v1/tts/generate
  • Headers: Content-Type: application/json
  • Request Body:
{
  "text": "Chào bạn, đây là giọng đọc thử nghiệm từ hệ thống SeaVoice. [laughter] Rất vui được đồng hành cùng bạn!",
  "voice_id": "Dp8TcVudawfON6pdX4YwOO",
  "language_id": "vi",
  "speed": 1.0,
  "duration": null,
  "num_step": 32,
  "response_format": "audio"
}
Tham sốKiểuBắt buộcMô tả
textstringCóĐoạn văn bản cần đọc (tối đa 5.000 ký tự). Có thể kèm emotion tag.
voice_idstringCóMã định danh giọng đọc (chuẩn 22 ký tự Base62).
language_idstringKhôngMã ngôn ngữ: "vi" (mặc định), "en".
speednumberKhôngTốc độ phát (0.5 đến 2.0, mặc định: 1.0).
durationnumberKhôngÉp độ dài thời gian phát (giây). Thường để null để mô hình tự tính.
num_stepnumberKhôngSố bước khử nhiễu (Denoising steps: 10 - 64, mặc định: 32). Bước càng cao âm thanh càng mượt nhưng thời gian render lâu hơn.
response_formatstringKhông"audio" (mặc định, trả về buffer WAV) hoặc "base64".
  • Response:
    • Nếu response_format = "audio": HTTP 200 kèm Content-Type: audio/wav. Header tùy chọn x-audio-url.
    • Nếu response_format = "base64": HTTP 200 kèm JSON { "audio": "<base64_string>" }.

4.3. Nhân Bản Giọng Nói (POST /v1/tts/voice-clone)

Tạo ra giọng nói tức thì bằng cách cung cấp một file âm thanh mẫu (Instant Voice Cloning).

  • Method: POST
  • Path: /v1/tts/voice-clone
  • Content-Type: multipart/form-data
  • Form Fields:
TrườngKiểuBắt buộcMô tả
textstringCóVăn bản cần đọc.
ref_audioFile/BlobĐiều kiệnFile âm thanh mẫu (WAV/MP3/M4A, độ dài lý tưởng 5-15 giây, rõ tiếng, ít tạp âm).
sample_voicestringĐiều kiệnTên mẫu giọng có sẵn từ hệ thống nếu không tải ref_audio.
prompt_idstringĐiều kiệnMã prompt .pt latent tensor đã lưu từ trước.
ref_textstringKhôngNội dung văn bản chính xác của đoạn audio mẫu ref_audio (giúp mô hình căn chỉnh âm vị chuẩn xác hơn).
voice_idstringKhôngVoice ID liên kết nếu có.
language_idstringKhôngNgôn ngữ mục tiêu ("vi", "en").
speedstring/numberKhôngTốc độ (0.5 - 2.0).
num_stepstring/numberKhôngSố bước suy luận (mặc định: 32).
response_formatstringKhông"audio" hoặc "base64".

4.4. Thiết Kế Giọng Độc Bản (POST /v1/tts/voice-design)

Tạo ra giọng đọc mới dựa trên câu mô tả tự nhiên các thuộc tính âm học (Natural Instruct Prompting).

  • Method: POST
  • Path: /v1/tts/voice-design
  • Headers: Content-Type: application/json
  • Request Body:
{
  "text": "Xin kính chào quý thính giả đang theo dõi bản tin sáng.",
  "instruct": "female, young adult, moderate pitch, american accent",
  "language_id": "vi",
  "speed": 1.0,
  "num_step": 32,
  "response_format": "audio"
}

Taxonomy Thuộc Tính Hợp Lệ Cho Trường instruct:

Trường instruct là chuỗi các từ khóa phân cách bởi dấu phẩy ,. SeaVoice API v2.1.0 hỗ trợ các nhóm thuộc tính:

  1. Giới tính (Gender): female (Nữ), male (Nam).
  2. Cao độ / Âm vực (Pitch):
    • very low pitch (Rất trầm)
    • low pitch (Trầm)
    • moderate pitch (Vừa phải / Chuẩn)
    • high pitch (Cao)
    • very high pitch (Rất cao)
  3. Độ tuổi (Age):
    • child (Trẻ em)
    • teenager (Thiếu niên)
    • young adult (Thanh niên)
    • middle-aged (Trung niên)
    • elderly (Cao tuổi / Già)
  4. Phong cách đặc biệt (Style):
    • whisper (Thì thầm / ASMR)
  5. Giọng vùng miền / Ngữ điệu (Accent):
    • Quốc tế: american accent, british accent, australian accent, canadian accent, chinese accent, japanese accent, korean accent, indian accent, russian accent, portuguese accent.
    • Tiếng Trung (nếu chọn): 东北话, 四川话, 陕西话, 青岛话, v.v.

Gợi ý preset thông dụng:

  • female, young adult, moderate pitch: Nữ thanh niên truyền cảm nhẹ nhàng (đọc truyện, tin tức).
  • female, young adult, low pitch: Nữ thanh niên trầm ấm dịu dàng (podcast, thiền).
  • male, young adult, low pitch: Nam thanh niên trầm ấm truyền cảm.
  • male, middle-aged, moderate pitch: Nam trung niên phong thái trang trọng tin tức.

4.5. Tự Động Chọn Giọng Theo Ngữ Cảnh (POST /v1/tts/auto-voice)

Mô hình tự động phân tích tâm trạng, giọng điệu của văn bản để sinh âm thanh tối ưu nhất mà không cần chỉ định trước voice_id hay instruct.

  • Method: POST
  • Path: /v1/tts/auto-voice
  • Headers: Content-Type: application/json
  • Request Body:
{
  "text": "Hôm nay tôi nhận được một món quà vô cùng bất ngờ! Thật tuyệt vời!",
  "language_id": "vi",
  "speed": 1.0,
  "response_format": "audio"
}

4.6. Quản Lý Voice Registry (Đăng Ký & Quản Trị Giọng)

Khi người dùng tạo ra một giọng ưng ý (từ Voice Clone hoặc Voice Design) và muốn lưu lại để tái sử dụng lâu dài:

A. Đăng ký giọng mới (POST /v1/tts/voices)

  • Method: POST
  • Path: /v1/tts/voices
  • Content-Type: multipart/form-data
  • Fields:
    • name: Tên giọng đọc (VD: "Giọng MC Hoàng Nam").
    • voice_id (tùy chọn): Nếu không truyền, hệ thống sẽ tự sinh Voice ID 22 ký tự.
    • description: Mô tả chi tiết về giọng.
    • gender: "male" | "female" | "unspecified".
    • language_id: "vi" | "en".
    • instruct: Chuỗi thuộc tính nếu tạo từ Voice Design.
    • ref_audio: File âm thanh mẫu nếu tạo từ Voice Clone.
  • Response:
{
  "voice_id": "Dp8TcVudawfON6pdX4YwOO",
  "name": "Giọng MC Hoàng Nam",
  "created_at": "2026-09-22T08:00:00Z"
}

B. Lấy danh sách giọng (GET /v1/tts/voices)

  • Response: Danh sách các voice object chứa voice_id, name, gender, description.

C. Xóa giọng (DELETE /v1/tts/voices/{voice_id})

  • Response: 200 OK hoặc 204 No Content.

4.7. Danh Mục Hỗ Trợ & Non-verbal Emotion Tags

A. Thẻ Cảm Xúc Phi Ngôn Ngữ (GET /v1/tts/emotions)

Chèn trực tiếp các thẻ này vào đoạn text gửi lên để giọng đọc biểu đạt cảm xúc tự nhiên:

  • [laughter]: Tiếng cười khúc khích
  • [sigh]: Tiếng thở dài
  • [gasp]: Tiếng hít thở kinh ngạc
  • [whisper]: Chuyển sang giọng nói thì thầm
  • [applause]: Tiếng vỗ tay
  • [yawn]: Tiếng ngáp
  • [cry]: Tiếng sụt sùi khóc
  • [cough]: Tiếng ho nhẹ
  • [surprise-wa]: Thán từ ngạc nhiên ("Oà!")

Ví dụ text:

Thật là một câu chuyện hài hước! [laughter] Tôi không thể nhịn cười được. Nhưng sau đó [sigh], mọi chuyện lại không như mong đợi.

B. Danh Sách Ngôn Ngữ (GET /v1/tts/languages)

Trả về danh sách ngôn ngữ: [{"code": "vi", "name": "Tiếng Việt"}, {"code": "en", "name": "English"}].

C. Mẫu Giọng Có Sẵn (GET /v1/tts/sample-voices)

Trả về mảng tên các preset giọng có sẵn trên server SeaVoice để người dùng chọn thử mà không cần upload file.


5. Mã Nguồn Mẫu Triển Khai (Code Implementations)

Module client chuẩn hoá xử lý gọi API, parse buffer stream và fallback base64:

// seavoice-client.ts
export interface GenerateParams {
  text: string;
  voiceId: string;
  languageId?: string;
  speed?: number;
  numStep?: number;
}

export class SeaVoiceClient {
  private baseUrl: string;

  constructor(baseUrl = process.env.SEAVOICE_BASE_URL || 'https://api.seavoice.seateklab.vn') {
    this.baseUrl = baseUrl.replace(/\/+$/, '');
  }

  /**
   * Sinh âm thanh từ Voice ID
   */
  async generateSpeech(params: GenerateParams): Promise<{ audioBuffer: Buffer; contentType: string }> {
    const endpoint = `${this.baseUrl}/v1/tts/generate`;
    
    const response = await fetch(endpoint, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        text: params.text,
        voice_id: params.voiceId,
        language_id: params.languageId || 'vi',
        speed: params.speed ?? 1.0,
        num_step: params.numStep ?? 32,
        response_format: 'audio',
      }),
    });

    if (!response.ok) {
      const errorDetail = await response.text().catch(() => response.statusText);
      throw new Error(`SeaVoice API Error (${response.status}): ${errorDetail}`);
    }

    const contentType = response.headers.get('content-type') || 'audio/wav';

    // Xử lý nếu API trả về JSON chứa chuỗi Base64
    if (contentType.includes('application/json')) {
      const json = await response.json() as { audio?: string; data?: string };
      const base64Data = json.audio || json.data;
      if (!base64Data) throw new Error('SeaVoice returned JSON without audio data');
      return {
        audioBuffer: Buffer.from(base64Data, 'base64'),
        contentType: 'audio/wav',
      };
    }

    // Xử lý Binary stream
    const arrayBuffer = await response.arrayBuffer();
    return {
      audioBuffer: Buffer.from(arrayBuffer),
      contentType,
    };
  }

  /**
   * Nhân bản giọng nói từ Buffer file âm thanh
   */
  async cloneVoice(text: string, refAudioBuffer: Buffer, filename = 'sample.wav'): Promise<Buffer> {
    const endpoint = `${this.baseUrl}/v1/tts/voice-clone`;
    
    const formData = new FormData();
    formData.append('text', text);
    formData.append('response_format', 'audio');
    formData.append('ref_audio', new Blob([refAudioBuffer], { type: 'audio/wav' }), filename);

    const response = await fetch(endpoint, {
      method: 'POST',
      body: formData,
    });

    if (!response.ok) {
      const errorDetail = await response.text();
      throw new Error(`SeaVoice Clone Error (${response.status}): ${errorDetail}`);
    }

    const arrayBuffer = await response.arrayBuffer();
    return Buffer.from(arrayBuffer);
  }
}

5.2. Triển Khai Bằng Python (FastAPI / Django / Scripts)

Sử dụng thư viện httpx hoặc requests:

# seavoice_service.py
import httpx
import os

SEAVOICE_BASE_URL = os.getenv("SEAVOICE_BASE_URL", "https://api.seavoice.seateklab.vn")

class SeaVoiceService:
    def __init__(self, base_url: str = SEAVOICE_BASE_URL):
        self.base_url = base_url.rstrip("/")

    def generate_speech(self, text: str, voice_id: str, speed: float = 1.0) -> bytes:
        url = f"{self.base_url}/v1/tts/generate"
        payload = {
            "text": text,
            "voice_id": voice_id,
            "language_id": "vi",
            "speed": speed,
            "num_step": 32,
            "response_format": "audio"
        }
        
        with httpx.Client(timeout=60.0) as client:
            response = client.post(url, json=payload)
            response.raise_for_status()
            
            content_type = response.headers.get("content-type", "")
            if "application/json" in content_type:
                import base64
                data = response.json()
                b64_str = data.get("audio") or data.get("data")
                return base64.b64decode(b64_str)
            
            return response.content

    def clone_voice(self, text: str, audio_file_path: str) -> bytes:
        url = f"{self.base_url}/v1/tts/voice-clone"
        
        with open(audio_file_path, "rb") as f:
            files = {"ref_audio": (os.path.basename(audio_file_path), f, "audio/wav")}
            data = {
                "text": text,
                "response_format": "audio"
            }
            with httpx.Client(timeout=90.0) as client:
                response = client.post(url, data=data, files=files)
                response.raise_for_status()
                return response.content

5.3. Các Lệnh cURL Kiểm Thử Nhanh

Test Sinh TTS:

curl -X POST "https://api.seavoice.seateklab.vn/v1/tts/generate" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Xin chào, đây là bài kiểm tra âm thanh.",
    "voice_id": "Dp8TcVudawfON6pdX4YwOO",
    "response_format": "audio"
  }' \
  --output test_tts.wav

Test Voice Design:

curl -X POST "https://api.seavoice.seateklab.vn/v1/tts/voice-design" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Giọng đọc này được tạo hoàn toàn tự động bằng thuộc tính.",
    "instruct": "female, young adult, low pitch",
    "response_format": "audio"
  }' \
  --output test_design.wav

Test Voice Clone với File Mẫu:

curl -X POST "https://api.seavoice.seateklab.vn/v1/tts/voice-clone" \
  -F "text=Xin chào, tôi là giọng nói nhân bản của bạn." \
  -F "ref_audio=@/path/to/my_voice_sample.wav" \
  -F "response_format=audio" \
  --output test_clone.wav

6. Mô Hình Tính Phí & Quản Lý Quota (Pricing & Billing)

Khi tích hợp vào dự án SaaS hoặc hệ thống doanh nghiệp, công thức tính chi phí khuyến nghị được áp dụng theo OpenStory:

  • Đơn vị tính: Số ký tự văn bản (character count).
  • Tỷ lệ quy đổi: 1 ký tự văn bản = 1 VNĐ.
  • Chuyển đổi tiền tệ quốc tế:
    • $1\text{ USD} = 25.000\text{ VNĐ} = 1.000.000\text{ Microdollars}$.
    • Do đó: $1\text{ VNĐ} = 40\text{ Microdollars}$.
  • Công thức trừ tiền: $$\text{Chi phí (VNĐ)} = \text{len}(\text{trim}(text)) \times 1\text{ VNĐ}$$
export function calculateTtsCost(text: string) {
  const charCount = text.trim().length;
  const vndAmount = charCount; // 1 ký tự = 1 VNĐ
  const costMicros = charCount * 40; // Đơn vị microdollars

  return { charCount, vndAmount, costMicros };
}

7. Các Lưu Ý Vận Hành, Giới Hạn & Xử Lý Lỗi (Troubleshooting)

Mã Lỗi / Tình HuốngNguyên NhânGiải Pháp Xử Lý
HTTP 400 Bad RequestChuỗi instruct chứa thuộc tính không hợp lệ hoặc thiếu tham số bắt buộc.Sử dụng hàm lọc sanitizeVoiceDesignInstruct để chỉ giữ lại các từ khóa trong Taxonomy chuẩn.
HTTP 500 / 502 / 504Cụm GPU đang khởi động hoặc quá tải mô hình suy luận.Cấu hình cơ chế Retry với Exponential Backoff (thử lại 2-3 lần, giãn cách 2s - 5s).
Timeout (> 60s)Đoạn văn bản quá dài hoặc mạng kết nối chậm.1. Tăng timeout của HTTP client lên ít nhất 60-90 giây.<br>2. Cắt nhỏ văn bản (chunking) theo từng câu hoặc đoạn tối đa 500-1000 ký tự rồi ghép audio.
Âm thanh bị rè / vỡ tiếngFile ref_audio có quá nhiều tạp âm nền hoặc âm lượng quá lớn.Chuẩn hóa âm thanh đầu vào: chuyển về định dạng WAV, mono, tần số 24.000Hz hoặc 44.100Hz, khử nhiễu trước khi gửi.
Voice ID không tìm thấyVoice ID chưa được đăng ký trong hệ thống SeaVoice.Gọi POST /v1/tts/voices để đăng ký giọng vào Registry trước khi gọi /v1/tts/generate.

8. Checklist Triển Khai (Go-Live Checklist)

  • Đã kiểm tra kết nối tới https://api.seavoice.seateklab.vn/health thành công.
  • Đã thiết lập biến môi trường SEAVOICE_BASE_URL trên các môi trường Dev, Staging, Production.
  • Đã triển khai tầng backend proxy (tránh gọi API trực tiếp từ frontend).
  • Đã cấu hình Cloud Storage (S3 / R2) để lưu trữ file âm thanh đầu ra và phục vụ qua CDN.
  • Đã thiết lập cơ chế timeout (tối thiểu 60s) và retry policy cho các lệnh gọi suy luận GPU.
  • Đã kiểm tra hỗ trợ các thẻ cảm xúc phi ngôn ngữ ([laughter], [whisper], [sigh]).
  • Đã tích hợp logic tính phí / trừ quota theo số lượng ký tự văn bản.