Từ kinh nghiệm triển khai hệ thống TTS (Text-to-Speech) cho dự án podcast tự động của mình, tôi nhận ra rằng chi phí API có thể trở thành gánh nặng lớn khi quy mô tăng lên. Trong bài viết này, tôi sẽ chia sẻ cách tôi triển khai Edge TTS - giải pháp tổng hợp giọng nói miễn phí với chất lượng cao, hoàn toàn chạy local.
Bảng so sánh chi phí AI và TTS 2026
Trước khi đi vào chi tiết kỹ thuật, hãy cùng xem bức tranh tổng quan về chi phí AI và TTS năm 2026:
- GPT-4.1 output: $8/MTok — Chi phí cao nhất trong top tier
- Claude Sonnet 4.5 output: $15/MTok — Premium option
- Gemini 2.5 Flash output: $2.50/MTok — Cân bằng giữa giá và chất lượng
- DeepSeek V3.2 output: $0.42/MTok — Tiết kiệm nhất, giảm 95% so với Claude
Với 10 triệu token/tháng, chi phí sẽ là:
- GPT-4.1: $80/tháng
- Claude Sonnet 4.5: $150/tháng
- Gemini 2.5 Flash: $25/tháng
- DeepSeek V3.2: $4.2/tháng
Để tối ưu chi phí, bạn có thể sử dụng nền tảng HolySheep AI với tỷ giá ¥1=$1 (tiết kiệm 85%+), hỗ trợ WeChat/Alipay, độ trễ dưới 50ms cùng tín dụng miễn phí khi đăng ký.
Edge TTS là gì và tại sao nên dùng?
Edge TTS là thư viện Python mã nguồn mở, sử dụng API tổng hợp giọng nói của Microsoft Edge để tạo âm thanh tự nhiên. Điểm mạnh của nó:
- Hoàn toàn miễn phí — Không giới hạn số lượng từ
- Chất lượng cao — Sử dụng mô hình neural từ Microsoft
- Nhiều giọng đọc — Hỗ trợ hàng chục giọng tiếng Việt và quốc tế
- Chạy local — Không cần internet khi đã tải mô hình
- API đơn giản — Tích hợp dễ dàng vào project
Cài đặt Edge TTS
pip install edge-tts
Hoặc sử dụng conda
conda install -c conda-forge edge-tts
Yêu cầu hệ thống: Python 3.8+, ffmpeg (để chuyển đổi định dạng âm thanh).
# Cài đặt ffmpeg trên Ubuntu/Debian
sudo apt update
sudo apt install ffmpeg
Cài đặt ffmpeg trên macOS
brew install ffmpeg
Cài đặt ffmpeg trên Windows (sử dụng winget)
winget install ffmpeg
Sử dụng cơ bản với Edge TTS
import edge_tts
import asyncio
async def synthesize_speech():
"""Tổng hợp giọng nói cơ bản"""
# Khởi tạo communicate với text và giọng đọc
communicate = edge_tts.Communicate(
text="Xin chào! Đây là bài hướng dẫn Edge TTS của HolySheep AI.",
voice="vi-VN-NamMinhNeural" # Giọng tiếng Việt Nam
)
# Lưu thành file MP3
await communicate.save("output.mp3")
print("Đã tạo file output.mp3 thành công!")
Chạy async function
asyncio.run(synthesize_speech())
Danh sách giọng đọc tiếng Việt
import edge_tts
async def list_vietnamese_voices():
"""Liệt kê tất cả giọng tiếng Việt có sẵn"""
voices = await edge_tts.list_voices()
# Lọc giọng tiếng Việt
vi_voices = [v for v in voices if v["Locale"].startswith("vi")]
print("=" * 60)
print("DANH SÁCH GIỌNG TIẾNG VIỆT")
print("=" * 60)
for voice in vi_voices:
print(f"Tên: {voice['Name']}")
print(f" Locale: {voice['Locale']}")
print(f" Giới tính: {voice['Gender']}")
print(f" ShortName: {voice['ShortName']}")
print("-" * 40)
Chạy
asyncio.run(list_vietnamese_voices())
Kết quả điển hình:
- vi-VN-NamMinhNeural — Nam, giọng miền Bắc
- vi-VN-HoaiMyNeural — Nữ, giọng miền Nam
- vi-VN-AnNeural — Nữ, giọng trung bình
Tùy chỉnh tham số nâng cao
import edge_tts
import asyncio
async def advanced_synthesis():
"""Tổng hợp với các tham số nâng cao"""
# Các tham số điều chỉnh:
# - Rate: Tốc độ đọc (-50% đến +100%)
# - Volume: Âm lượng (-50% đến +50%)
# - Pitch: Cao độ (Hz)
communicate = edge_tts.Communicate(
text="Chào mừng bạn đến với hướng dẫn Edge TTS. "
"Tôi sẽ hướng dẫn bạn cách tùy chỉnh giọng nói.",
voice="vi-VN-HoaiMyNeural",
rate="+10%", # Nhanh hơn 10%
volume="+5%", # To hơn 5%
pitch="+10Hz" # Cao hơn 10Hz
)
# Xuất văn bản SSML để kiểm tra
# substitute = await communicate.get_ssml()
# print(substitute)
await communicate.save("advanced_output.mp3")
print("Đã tạo file với tốc độ và âm lượng tùy chỉnh!")
asyncio.run(advanced_synthesis())
Tích hợp với HolySheep AI cho pipeline hoàn chỉnh
Trong thực tế, tôi thường kết hợp Edge TTS với HolySheep AI để tạo pipeline hoàn chỉnh: dùng LLM để tạo nội dung, rồi dùng Edge TTS để chuyển thành giọng nói. Dưới đây là ví dụ:
import edge_tts
import openai
import asyncio
import re
Cấu hình HolySheep AI - KHÔNG dùng api.openai.com
openai.api_base = "https://api.holysheep.ai/v1"
openai.api_key = "YOUR_HOLYSHEEP_API_KEY" # Thay bằng key của bạn
async def generate_and_speak(topic: str, voice: str = "vi-VN-NamMinhNeural"):
"""
Pipeline hoàn chỉnh: Tạo nội dung bằng LLM -> Tổng hợp giọng nói
Chi phí: DeepSeek V3.2 chỉ $0.42/MTok
"""
# Bước 1: Gọi LLM để tạo nội dung
response = openai.ChatCompletion.create(
model="deepseek-chat", # Hoặc gpt-4.1, claude-3-5-sonnet, gemini-2.0-flash
messages=[
{
"role": "system",
"content": "Bạn là người viết bài podcast ngắn gọn, súc tích."
},
{
"role": "user",
"content": f"Viết một đoạn podcast 200 từ về chủ đề: {topic}"
}
],
max_tokens=500,
temperature=0.7
)
content = response.choices[0].message.content
print(f"Nội dung tạo được: {len(content)} ký tự")
# Bước 2: Làm sạch text cho TTS
# Loại bỏ các ký tự đặc biệt không phù hợp
clean_text = re.sub(r'[📌•→●★]', '-', content)
clean_text = re.sub(r'\n{3,}', '\n\n', clean_text)
# Bước 3: Tổng hợp giọng nói với Edge TTS
communicate = edge_tts.Communicate(
text=clean_text,
voice=voice,
rate="+5%",
volume="+0%"
)
output_file = f"podcast_{topic[:20].replace(' ', '_')}.mp3"
await communicate.save(output_file)
print(f"✅ Đã tạo podcast: {output_file}")
# Báo cáo chi phí
input_tokens = response.usage.prompt_tokens
output_tokens = response.usage.completion_tokens
total_tokens = response.usage.total_tokens
cost_per_million = 0.42 # DeepSeek V3.2
cost = (total_tokens / 1_000_000) * cost_per_million
print(f"💰 Chi phí LLM: ${cost:.4f} ({total_tokens} tokens)")
print(f"📊 Chi phí TTS: Miễn phí (Edge TTS local)")
Chạy demo
asyncio.run(generate_and_speak("Công nghệ AI 2026"))
Xử lý text dài với chunking
Khi xử lý văn bản dài (podcast, audiobook), bạn cần chia nhỏ text để tránh timeout:
import edge_tts
import asyncio
import re
class EdgeTTSLongForm:
"""Xử lý văn bản dài bằng chunking thông minh"""
def __init__(self, voice: str = "vi-VN-NamMinhNeural"):
self.voice = voice
self.CHUNK_SIZE = 3000 # Ký tự mỗi chunk
self.CHUNK_OVERLAP = 200 # Độ chồng lấn
async def synthesize_long_text(self, text: str, output_file: str):
"""Tổng hợp văn bản dài thành file MP3"""
# Chia văn bản thành các đoạn
chunks = self._split_into_chunks(text)
print(f"Tổng cộng {len(chunks)} đoạn cần xử lý...")
# Tạo list các task
tasks = []
for i, chunk in enumerate(chunks):
print(f" Đang xử lý đoạn {i+1}/{len(chunks)}...")
communicate = edge_tts.Communicate(
text=chunk.strip(),
voice=self.voice,
rate="+5%"
)
temp_file = f"temp_chunk_{i:03d}.mp3"
tasks.append(communicate.save(temp_file))
# Chạy song song (giới hạn 5 task cùng lúc)
for i in range(0, len(tasks), 5):
batch = tasks[i:i+5]
await asyncio.gather(*batch)
# Ghép các file MP3
await self._merge_audio_files(len(chunks), output_file)
# Dọn file tạm
for i in range(len(chunks)):
temp_file = f"temp_chunk_{i:03d}.mp3"
try:
import os
os.remove(temp_file)
except:
pass
print(f"✅ Hoàn thành: {output_file}")
def _split_into_chunks(self, text: str) -> list:
"""Chia văn bản thành các đoạn có ý nghĩa"""
# Tách theo câu
sentences = re.split(r'(?<=[.!?])\s+', text)
chunks = []
current_chunk = ""
for sentence in sentences:
if len(current_chunk) + len(sentence) < self.CHUNK_SIZE:
current_chunk += sentence + " "
else:
if current_chunk:
chunks.append(current_chunk.strip())
# Overlap
words = current_chunk.split()[-20:]
current_chunk = " ".join(words) + " " + sentence + " "
if current_chunk.strip():
chunks.append(current_chunk.strip())
return chunks
async def _merge_audio_files(self, num_chunks: int, output_file: str):
"""Ghép các file MP3 thành một"""
# Sử dụng pydub hoặc ffmpeg để merge
from pydub import AudioSegment
combined = AudioSegment.empty()
for i in range(num_chunks):
temp_file = f"temp_chunk_{i:03d}.mp3"
audio = AudioSegment.from_mp3(temp_file)
combined += audio
combined.export(output_file, format="mp3")
Sử dụng
async def demo_long_form():
tts = EdgeTTSLongForm(voice="vi-VN-HoaiMyNeural")
long_text = """
Đây là một văn bản dài mô phỏng nội dung podcast.
Với Edge TTS, bạn có thể tổng hợp hàng nghìn ký tự mà không tốn chi phí.
Kết hợp với HolySheep AI để tạo nội dung tự động.
"""
# Lặp lại để tạo văn bản dài
long_text = long_text * 50
await tts.synthesize_long_text(long_text, "long_podcast.mp3")
asyncio.run(demo_long_form())
Triển khai Docker cho production
Để sử dụng Edge TTS trong môi trường production, tôi khuyên dùng Docker:
# Dockerfile
FROM python:3.11-slim
WORKDIR /app
Cài đặt ffmpeg
RUN apt-get update && apt-get install -y \
ffmpeg \
&& rm -rf /var/lib/apt/lists/*
Cài đặt thư viện Python
RUN pip install --no-cache-dir \
edge-tts \
fastapi \
uvicorn \
pydub
Copy code
COPY app.py .
Expose port
EXPOSE 8000
Chạy server
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"]
# app.py - FastAPI server cho Edge TTS
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import edge_tts
import asyncio
import uuid
import os
app = FastAPI(title="Edge TTS API", version="1.0.0")
class TTSRequest(BaseModel):
text: str
voice: str = "vi-VN-NamMinhNeural"
rate: str = "+0%"
volume: str = "+0%"
format: str = "mp3" # mp3, wav, ogg
class TTSResponse(BaseModel):
success: bool
audio_url: str = None
duration_seconds: float = None
error: str = None
@app.post("/tts", response_model=TTSResponse)
async def text_to_speech(request: TTSRequest):
try:
# Validate voice
voices = await edge_tts.list_voices()
valid_voice = any(v["ShortName"] == request.voice for v in voices)
if not valid_voice:
return TTSResponse(
success=False,
error=f"Voice '{request.voice}' không hợp lệ"
)
# Tạo file tạm
filename = f"{uuid.uuid4()}.mp3"
# Tổng hợp
communicate = edge_tts.Communicate(
text=request.text,
voice=request.voice,
rate=request.rate,
volume=request.volume
)
await communicate.save(filename)
# Lấy thông tin duration
from pydub import AudioSegment
audio = AudioSegment.from_mp3(filename)
duration = len(audio) / 1000 # Convert ms to seconds
# Cleanup
os.remove(filename)
return TTSResponse(
success=True,
audio_url=f"/audio/{filename}",
duration_seconds=duration
)
except Exception as e:
return TTSResponse(
success=False,
error=str(e)
)
@app.get("/voices")
async def list_voices():