Voice Cloning คืออะไร
Voice Cloning เป็นเทคโนโลยี AI ที่ใช้ Deep Learning สร้างเสียงเลียนแบบเสียงของคนจริง โดยวิเคราะห์ลักษณะเฉพาะของเสียง (Speaker Embedding) เช่น โทนเสียง จังหวะการพูด น้ำเสียง ความถี่ แล้วสร้างเสียงใหม่จากข้อความที่กำหนด (Text-to-Speech) ให้ฟังเหมือนคนต้นแบบ
ปัจจุบัน Voice Cloning ใช้กันแพร่หลายใน Audiobook Production, Video Dubbing, Virtual Assistant, Content Creation, Accessibility สำหรับผู้พิการทางเสียง และ Personalized TTS เทคโนโลยีพัฒนาเร็วมากจนสามารถ Clone เสียงได้จากตัวอย่างเพียง 3-10 วินาที
ติดตั้งและเตรียมสภาพแวดล้อม
# === ติดตั้ง Voice Cloning Environment ===
# สร้าง Virtual Environment
python -m venv voice-clone-env
source voice-clone-env/bin/activate # Linux/Mac
# voice-clone-env\Scripts\activate # Windows
# ติดตั้ง Coqui TTS (XTTS v2)
pip install TTS torch torchaudio
# ติดตั้ง Dependencies เพิ่มเติม
pip install soundfile librosa scipy numpy pydub
pip install fastapi uvicorn python-multipart # สำหรับ API
# ตรวจสอบ GPU
python -c "import torch; print(f'CUDA: {torch.cuda.is_available()}')"
python -c "import torch; print(f'GPU: {torch.cuda.get_device_name(0)}')"
# ดาวน์โหลด Model
python -c "from TTS.api import TTS; tts = TTS('tts_models/multilingual/multi-dataset/xtts_v2')"
# Model จะถูกดาวน์โหลดอัตโนมัติ (~1.8GB)
# โครงสร้าง Project
voice-cloner/
├── main.py # Main Script
├── api.py # FastAPI Server
├── preprocess.py # Audio Preprocessing
├── clone.py # Voice Cloning Engine
├── batch_process.py # Batch Processing
├── samples/ # Voice Samples
│ └── speaker.wav
├── output/ # Generated Audio
├── config.yaml # Configuration
└── requirements.txt
Voice Cloning Script
# clone.py — Voice Cloning Engine
import os
import torch
import numpy as np
import soundfile as sf
from TTS.api import TTS
from pydub import AudioSegment
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class VoiceCloner:
"""Voice Cloning Engine ด้วย XTTS v2"""
def __init__(self, model_name="tts_models/multilingual/multi-dataset/xtts_v2",
device=None):
self.device = device or ("cuda" if torch.cuda.is_available() else "cpu")
logger.info(f"Loading model on {self.device}...")
self.tts = TTS(model_name).to(self.device)
logger.info("Model loaded successfully")
def preprocess_audio(self, audio_path, output_path=None,
target_sr=22050, max_duration=30):
"""เตรียมไฟล์เสียงสำหรับ Voice Cloning"""
audio = AudioSegment.from_file(audio_path)
# Convert to mono
if audio.channels > 1:
audio = audio.set_channels(1)
# Set sample rate
audio = audio.set_frame_rate(target_sr)
# Normalize volume
target_dbfs = -20
change_in_dbfs = target_dbfs - audio.dBFS
audio = audio.apply_gain(change_in_dbfs)
# Trim silence
from pydub.silence import detect_leading_silence
start_trim = detect_leading_silence(audio, silence_threshold=-40)
end_trim = detect_leading_silence(audio.reverse(), silence_threshold=-40)
audio = audio[start_trim:len(audio) - end_trim]
# Limit duration
if len(audio) > max_duration * 1000:
audio = audio[:max_duration * 1000]
out_path = output_path or audio_path.replace(".wav", "_processed.wav")
audio.export(out_path, format="wav")
logger.info(f"Preprocessed: {out_path} ({len(audio)/1000:.1f}s)")
return out_path
def clone_voice(self, text, speaker_wav, output_path,
language="th", speed=1.0):
"""Clone เสียงและสร้าง Audio จากข้อความ"""
logger.info(f"Generating speech: '{text[:50]}...'")
self.tts.tts_to_file(
text=text,
speaker_wav=speaker_wav,
language=language,
file_path=output_path,
speed=speed,
)
# ตรวจสอบไฟล์ Output
if os.path.exists(output_path):
audio = AudioSegment.from_file(output_path)
duration = len(audio) / 1000
logger.info(f"Generated: {output_path} ({duration:.1f}s)")
return {"path": output_path, "duration": duration}
else:
raise FileNotFoundError(f"Failed to generate: {output_path}")
def batch_clone(self, texts, speaker_wav, output_dir,
language="th", prefix="output"):
"""Clone เสียงหลายข้อความพร้อมกัน"""
os.makedirs(output_dir, exist_ok=True)
results = []
for i, text in enumerate(texts):
output_path = os.path.join(output_dir, f"{prefix}_{i:04d}.wav")
try:
result = self.clone_voice(text, speaker_wav, output_path,
language=language)
results.append(result)
except Exception as e:
logger.error(f"Error on text {i}: {e}")
results.append({"path": None, "error": str(e)})
success = sum(1 for r in results if r.get("path"))
logger.info(f"Batch complete: {success}/{len(texts)} succeeded")
return results
def concatenate_audio(self, audio_files, output_path, gap_ms=500):
"""รวมไฟล์เสียงหลายไฟล์เข้าด้วยกัน"""
combined = AudioSegment.empty()
gap = AudioSegment.silent(duration=gap_ms)
for f in audio_files:
if f and os.path.exists(f):
audio = AudioSegment.from_file(f)
combined += audio + gap
combined.export(output_path, format="wav")
logger.info(f"Concatenated {len(audio_files)} files -> {output_path}")
return output_path
# ตัวอย่างการใช้งาน
if __name__ == "__main__":
cloner = VoiceCloner()
# Preprocess Speaker Sample
processed = cloner.preprocess_audio("samples/speaker.wav")
# Clone เสียงเดียว
result = cloner.clone_voice(
text="สวัสดีครับ นี่คือเสียงที่สร้างจาก AI Voice Cloning",
speaker_wav=processed,
output_path="output/test_output.wav",
language="th",
)
print(f"Generated: {result}")
# Batch Clone
texts = [
"ยินดีต้อนรับสู่ระบบ Voice Cloning อัตโนมัติ",
"ระบบนี้ใช้เทคโนโลยี XTTS v2 ในการสร้างเสียง",
"สามารถ Clone เสียงได้จากตัวอย่างเพียงไม่กี่วินาที",
]
results = cloner.batch_clone(texts, processed, "output/batch/")
API Server สำหรับ Voice Cloning
# api.py — FastAPI Server สำหรับ Voice Cloning
from fastapi import FastAPI, UploadFile, File, Form
from fastapi.responses import FileResponse
import tempfile
import os
import uuid
from clone import VoiceCloner
app = FastAPI(title="Voice Cloning API")
cloner = VoiceCloner()
@app.post("/clone")
async def clone_voice(
text: str = Form(...),
language: str = Form(default="th"),
speaker: UploadFile = File(...),
):
"""Clone เสียงจากไฟล์ตัวอย่างและข้อความ"""
# Save uploaded file
tmp_speaker = os.path.join(tempfile.gettempdir(), f"speaker_{uuid.uuid4()}.wav")
with open(tmp_speaker, "wb") as f:
content = await speaker.read()
f.write(content)
# Preprocess
processed = cloner.preprocess_audio(tmp_speaker)
# Generate
output_path = os.path.join(tempfile.gettempdir(), f"output_{uuid.uuid4()}.wav")
result = cloner.clone_voice(text, processed, output_path, language=language)
# Cleanup
os.remove(tmp_speaker)
if os.path.exists(processed):
os.remove(processed)
return FileResponse(
output_path,
media_type="audio/wav",
filename="cloned_voice.wav",
)
@app.post("/batch")
async def batch_clone(
texts: str = Form(...), # JSON array of texts
language: str = Form(default="th"),
speaker: UploadFile = File(...),
):
"""Batch Clone หลายข้อความ"""
import json
text_list = json.loads(texts)
tmp_speaker = os.path.join(tempfile.gettempdir(), f"speaker_{uuid.uuid4()}.wav")
with open(tmp_speaker, "wb") as f:
f.write(await speaker.read())
processed = cloner.preprocess_audio(tmp_speaker)
output_dir = os.path.join(tempfile.gettempdir(), f"batch_{uuid.uuid4()}")
results = cloner.batch_clone(text_list, processed, output_dir, language)
# Concatenate all outputs
audio_files = [r["path"] for r in results if r.get("path")]
final_output = os.path.join(tempfile.gettempdir(), f"final_{uuid.uuid4()}.wav")
cloner.concatenate_audio(audio_files, final_output)
return FileResponse(final_output, media_type="audio/wav")
@app.get("/health")
async def health():
return {"status": "ok", "device": cloner.device}
# รัน: uvicorn api:app --host 0.0.0.0 --port 8000
# ทดสอบ:
# curl -X POST http://localhost:8000/clone \
# -F "text=สวัสดีครับ" \
# -F "language=th" \
# -F "speaker=@samples/speaker.wav" \
# -o output.wav
Automation Pipeline
# batch_process.py — Automation Pipeline สำหรับ Voice Cloning
import os
import csv
import yaml
import time
import logging
from clone import VoiceCloner
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(message)s",
)
logger = logging.getLogger(__name__)
def process_csv(csv_path, speaker_wav, output_dir, language="th"):
"""
อ่านข้อความจาก CSV แล้ว Clone เสียงอัตโนมัติ
CSV Format: id, text, filename
"""
cloner = VoiceCloner()
os.makedirs(output_dir, exist_ok=True)
# Preprocess speaker
processed = cloner.preprocess_audio(speaker_wav)
results = []
with open(csv_path, "r", encoding="utf-8") as f:
reader = csv.DictReader(f)
rows = list(reader)
logger.info(f"Processing {len(rows)} items...")
start_time = time.time()
for i, row in enumerate(rows):
text = row["text"]
filename = row.get("filename", f"output_{i:04d}.wav")
output_path = os.path.join(output_dir, filename)
try:
result = cloner.clone_voice(text, processed, output_path,
language=language)
results.append({"id": row.get("id", i), "status": "ok",
**result})
logger.info(f"[{i+1}/{len(rows)}] OK: {filename}")
except Exception as e:
results.append({"id": row.get("id", i), "status": "error",
"error": str(e)})
logger.error(f"[{i+1}/{len(rows)}] FAIL: {filename} - {e}")
elapsed = time.time() - start_time
success = sum(1 for r in results if r["status"] == "ok")
logger.info(f"Done: {success}/{len(rows)} in {elapsed:.1f}s")
# Save report
report_path = os.path.join(output_dir, "report.csv")
with open(report_path, "w", encoding="utf-8", newline="") as f:
writer = csv.DictWriter(f, fieldnames=["id", "status", "path",
"duration", "error"])
writer.writeheader()
writer.writerows(results)
return results
if __name__ == "__main__":
process_csv(
csv_path="texts.csv",
speaker_wav="samples/speaker.wav",
output_dir="output/batch/",
language="th",
)
Best Practices และข้อควรระวัง
- คุณภาพเสียงตัวอย่าง: ใช้เสียงที่สะอาด ไม่มี Background Noise, เสียงดนตรี หรือเสียงรบกวน บันทึกในห้องเงียบ ใช้ไมค์คุณภาพดี
- ความยาวเสียง: สำหรับ XTTS v2 ใช้ตัวอย่าง 6-30 วินาที ยาวเกินไปอาจไม่ดีกว่า คัดเลือกส่วนที่ชัดเจนที่สุด
- จริยธรรม: ใช้เฉพาะเสียงตัวเองหรือได้รับอนุญาต ห้ามใช้สร้าง Deepfake หลอกลวง ระบุว่าเป็นเสียง AI เสมอ
- GPU Memory: XTTS v2 ใช้ VRAM ~4GB สำหรับ Inference ถ้าไม่มี GPU ใช้ CPU ได้แต่ช้ากว่า 5-10 เท่า
- Batch Processing: สำหรับงานจำนวนมาก ใช้ Batch Processing กับ Queue System เพื่อจัดการ Resources
- Watermarking: เพิ่ม Audio Watermark ในเสียงที่สร้าง เพื่อระบุว่าเป็นเสียง AI-generated
Voice Cloning คืออะไร
Voice Cloning ใช้ AI สร้างเสียงเลียนแบบเสียงคนจริง วิเคราะห์ลักษณะเฉพาะของเสียงแล้วสร้างเสียงใหม่จากข้อความ ใช้ใน Text-to-Speech, Audiobook, Dubbing, Virtual Assistant เทคโนโลยีใหม่ Clone ได้จากตัวอย่างเพียง 3-10 วินาที
ต้องใช้ข้อมูลเสียงเท่าไรสำหรับ Voice Cloning
Zero-shot Cloning (XTTS, Bark) ใช้ 3-10 วินาที Few-shot ใช้ 1-5 นาที Fine-tuning ใช้ 30 นาทีถึง 2 ชั่วโมง ยิ่งมีข้อมูลมากเสียงยิ่งเหมือน แต่เทคโนโลยีใหม่ Clone ได้ดีแม้ข้อมูลน้อย คุณภาพเสียงสำคัญกว่าปริมาณ
Voice Cloning ถูกกฎหมายหรือไม่
ถูกกฎหมายถ้าใช้เสียงตัวเองหรือได้รับอนุญาต Clone เสียงคนอื่นโดยไม่ได้อนุญาตอาจผิดกฎหมายลิขสิทธิ์และสิทธิส่วนบุคคล ห้ามสร้าง Deepfake หลอกลวง ควรระบุว่าเป็นเสียง AI เสมอ หลายประเทศกำลังออกกฎหมายควบคุม
เครื่องมือ Voice Cloning ที่ดีมีอะไรบ้าง
Open-source: Coqui TTS (XTTS v2), Tortoise TTS, Bark, OpenVoice, Fish Speech Commercial: ElevenLabs, Play.ht, Resemble AI, Murf แนะนำเริ่มจาก Coqui XTTS v2 เพราะ Open-source คุณภาพดี รองรับหลายภาษารวมถึงไทย
สรุป
Voice Cloning ด้วย AI เป็นเทคโนโลยีที่ทรงพลังและใช้งานง่ายขึ้นเรื่อยๆ ด้วย XTTS v2 สามารถ Clone เสียงจากตัวอย่างเพียงไม่กี่วินาที สร้าง Automation Pipeline ด้วย Python สำหรับ Batch Processing และเปิดเป็น API Service ด้วย FastAPI สิ่งสำคัญคือใช้อย่างมีจริยธรรม ได้รับอนุญาตจากเจ้าของเสียง ระบุว่าเป็นเสียง AI และเพิ่ม Watermark เพื่อป้องกันการนำไปใช้ในทางที่ผิด
