ElevenLabs API로 다국어 오디오북 만들기 - 음성 클론부터 챕터 자동 생성까지 완벽 가이드
ElevenLabs API로 다국어 오디오북 자동 생성하기
ElevenLabs는 업계 최고 수준의 AI 음성 합성 API를 제공합니다. 이 가이드에서는 Python을 활용해 음성 클론, 텍스트 분할, 챕터별 오디오 자동 생성까지 전체 워크플로우를 단계별로 구축합니다.
1단계: 환경 설정 및 패키지 설치
먼저 필요한 Python 패키지를 설치합니다.
pip install elevenlabs pydub requests
API 키를 환경 변수로 설정합니다.
# Linux/Mac
export ELEVENLABS_API_KEY=“YOUR_API_KEY”
Windows PowerShell
$env:ELEVENLABS_API_KEY=“YOUR_API_KEY”
기본 클라이언트를 초기화하는 코드입니다.
import os
from elevenlabs.client import ElevenLabs
client = ElevenLabs(
api_key=os.getenv(“ELEVENLABS_API_KEY”)
)
2단계: 음성 클론(Voice Cloning) 설정
자신만의 목소리 또는 특정 화자의 음성을 클론하여 오디오북에 활용할 수 있습니다. 최소 1분 이상의 깨끗한 음성 샘플이 필요합니다.
def clone_voice(name, description, file_paths):
"""음성 클론 생성"""
voice = client.clone(
name=name,
description=description,
files=[open(f, "rb") for f in file_paths]
)
print(f"음성 클론 완료: {voice.voice_id}")
return voice.voice_id
사용 예시
voice_id = clone_voice(
name=“내레이터_한국어”,
description=“한국어 오디오북 내레이션용 차분한 남성 음성”,
file_paths=[“sample_voice_01.mp3”, “sample_voice_02.mp3”]
)
클론 없이 기존 제공 음성을 사용하려면 사용 가능한 음성 목록을 조회합니다.
voices = client.voices.get_all()
for v in voices.voices:
print(f”{v.name} → {v.voice_id} (언어: {v.labels})“)
3단계: 텍스트 분할 유틸리티 구현
ElevenLabs API는 요청당 최대 5,000자 제한이 있습니다. 긴 텍스트를 문장 단위로 안전하게 분할하는 함수를 만듭니다.
import re
def split_text(text, max_chars=4500):
"""텍스트를 API 제한에 맞게 청크 단위로 분할"""
sentences = re.split(r’(?<=[.!?。!?])\s+’, text)
chunks = []
current_chunk = ""
for sentence in sentences:
if len(current_chunk) + len(sentence) + 1 <= max_chars:
current_chunk += (" " + sentence if current_chunk else sentence)
else:
if current_chunk:
chunks.append(current_chunk.strip())
current_chunk = sentence
if current_chunk:
chunks.append(current_chunk.strip())
return chunks
테스트
chunks = split_text(long_text)
print(f”총 {len(chunks)}개 청크로 분할됨”)
4단계: 챕터별 오디오 자동 생성
핵심 워크플로우입니다. 각 챕터 텍스트를 읽어 청크로 분할하고, API 호출 후 결과를 병합합니다.
from pydub import AudioSegment
import time
import io
def generate_chapter_audio(chapter_text, voice_id, chapter_num, output_dir=“output”):
"""단일 챕터의 오디오를 생성하고 저장"""
os.makedirs(output_dir, exist_ok=True)
chunks = split_text(chapter_text)
combined = AudioSegment.empty()
for i, chunk in enumerate(chunks):
print(f" 챕터 {chapter_num} - 청크 {i+1}/{len(chunks)} 생성 중...")
audio_generator = client.text_to_speech.convert(
voice_id=voice_id,
text=chunk,
model_id="eleven_multilingual_v2",
output_format="mp3_44100_128"
)
audio_bytes = b"".join(audio_generator)
segment = AudioSegment.from_mp3(io.BytesIO(audio_bytes))
combined += segment
# Rate limit 방지를 위한 딜레이
time.sleep(1)
output_path = os.path.join(output_dir, f"chapter_{chapter_num:02d}.mp3")
combined.export(output_path, format="mp3", bitrate="192k")
print(f"챕터 {chapter_num} 저장 완료: {output_path}")
return output_path</code></pre>
5단계: 다국어 오디오북 전체 파이프라인 실행
여러 챕터와 다국어를 지원하는 전체 자동화 파이프라인입니다.
LANGUAGE_VOICE_MAP = {
"ko": "YOUR_KOREAN_VOICE_ID",
"en": "YOUR_ENGLISH_VOICE_ID",
"ja": "YOUR_JAPANESE_VOICE_ID",
}
def generate_audiobook(chapters, language=“ko”):
"""전체 오디오북 생성 파이프라인"""
voice_id = LANGUAGE_VOICE_MAP.get(language)
if not voice_id:
raise ValueError(f”지원하지 않는 언어: {language}“)
output_dir = f"audiobook_{language}"
audio_files = []
for idx, chapter in enumerate(chapters, 1):
print(f"\n[챕터 {idx}/{len(chapters)}] 처리 시작")
path = generate_chapter_audio(chapter, voice_id, idx, output_dir)
audio_files.append(path)
# 전체 병합 파일 생성
full_audio = AudioSegment.empty()
pause = AudioSegment.silent(duration=2000) # 챕터 간 2초 묵음
for f in audio_files:
full_audio += AudioSegment.from_mp3(f) + pause
full_path = os.path.join(output_dir, "full_audiobook.mp3")
full_audio.export(full_path, format="mp3", bitrate="192k")
print(f"\n전체 오디오북 생성 완료: {full_path}")
return full_path
실행
chapters = [
open(f”chapter_{i}.txt”, “r”, encoding=“utf-8”).read()
for i in range(1, 6)
]
generate_audiobook(chapters, language=“ko”)
다국어 모델 비교
모델 지원 언어 수 음질 지연 시간 추천 용도 eleven_multilingual_v2 29개 최상 보통 오디오북, 더빙 eleven_turbo_v2_5 32개 상 매우 빠름 실시간 앱, 챗봇 eleven_monolingual_v1 영어 전용 상 빠름 영어 전용 콘텐츠
## Pro Tips: 파워 유저를 위한 고급 팁
- **발음 교정:** SSML 태그 대신 발음 사전(Pronunciation Dictionary) API를 활용하세요. client.pronunciation_dictionaries.add_rules_to_the_pronunciation_dictionary()로 특수 용어의 발음을 커스터마이즈할 수 있습니다.- **감정 조절:** 텍스트에 괄호 지시문을 삽입하면 톤이 달라집니다. 예: (속삭이며) 비밀이야... 또는 (흥분하며) 드디어 성공했다!- **비용 최적화:** eleven_turbo_v2_5 모델은 v2 대비 약 50% 저렴합니다. 프로토타입 단계에서는 터보 모델로 테스트 후, 최종본만 v2로 생성하세요.- **병렬 처리:** concurrent.futures.ThreadPoolExecutor로 여러 챕터를 동시에 생성하면 처리 시간을 크게 단축할 수 있습니다. 다만 API Rate Limit(분당 요청 수)을 반드시 확인하세요.- **음성 안정성:** stability 파라미터를 0.7~0.85 사이로 설정하면 오디오북에 적합한 일관된 톤을 유지합니다.
## Troubleshooting: 자주 발생하는 오류 해결
401 Unauthorized
API 키가 잘못되었거나 만료된 경우입니다. ElevenLabs 대시보드에서 키를 재발급하고 환경 변수를 갱신하세요.
# API 키 확인
curl -H "xi-api-key: YOUR_API_KEY" https://api.elevenlabs.io/v1/user
# 정상 응답이면 키가 유효합니다
### 429 Too Many Requests (Rate Limit)
무료 플랜은 분당 요청 제한이 엄격합니다. 지수 백오프(exponential backoff)를 적용하세요.
import time
def api_call_with_retry(func, max_retries=3):
for attempt in range(max_retries):
try:
return func()
except Exception as e:
if “429” in str(e) and attempt < max_retries - 1:
wait = 2 ** (attempt + 1)
print(f”Rate limit 도달. {wait}초 후 재시도…”)
time.sleep(wait)
else:
raise
생성된 오디오에 잡음이나 끊김 현상
텍스트 청크가 문장 중간에서 잘린 경우 발생합니다. split_text 함수에서 문장 종결 부호 기준으로 분할되는지 확인하세요. 한국어의 경우 마침표(.) 외에 물음표(?), 느낌표(!)도 분할 기준에 포함해야 합니다.
음성 클론 품질이 낮은 경우
배경 소음이 없는 고품질 WAV/MP3 샘플을 3분 이상 제공하세요. 여러 짧은 파일보다 한두 개의 긴 파일이 더 효과적입니다.
자주 묻는 질문 (FAQ)
Q1: ElevenLabs 무료 플랜으로 오디오북을 만들 수 있나요?
무료 플랜은 월 10,000자(약 10분 분량)까지 지원합니다. 짧은 단편 소설이나 테스트용으로는 충분하지만, 본격적인 오디오북 제작에는 Starter 플랜(월 30,000자) 이상을 권장합니다. 음성 클론 기능은 유료 플랜에서만 사용할 수 있습니다.
Q2: eleven_multilingual_v2 모델이 한국어를 잘 지원하나요?
네, 한국어를 포함한 29개 언어를 지원하며 한국어 발음과 억양 품질이 우수합니다. 다만 전문 용어나 고유명사의 경우 발음 사전(Pronunciation Dictionary)을 활용해 정확한 발음을 지정하는 것이 좋습니다. 한영 혼용 텍스트도 자연스럽게 처리합니다.
Q3: 생성된 오디오북의 저작권과 상업적 사용은 어떻게 되나요?
ElevenLabs 유료 플랜 사용자는 생성된 오디오의 상업적 사용 권리를 보유합니다. 다만 음성 클론의 경우 원본 화자의 동의가 반드시 필요하며, 이는 ElevenLabs 이용약관과 각국 법률의 적용을 받습니다. 상업적 배포 전 반드시 라이선스 조건을 확인하세요.