
ElevenLabs AI 보이스로 인디 게임 더빙 구축하기
ElevenLabs의 텍스트 음성 변환을 게임에 적용할 때 필요한 파이프라인과 Unity 연동 방식을 정리합니다. 비용과 지연 시간, 권리 문제를 고려해 출시 가능한 더빙 시스템을 설계해 봅니다.
AI 보이스 더빙이 해결하는 문제
인디 게임에서 음성 더빙은 몰입감을 크게 높이지만 성우 섭외와 녹음·수정·편집에 드는 비용과 시간이 부담이 될 수 있다. ElevenLabs 같은 텍스트 음성 변환(TTS) 서비스는 대사 초안을 빠르게 들어 보고 반복 NPC 대사나 프로토타입용 음성을 만드는 데 특히 유용하다.
다만 AI 음성을 성우의 완전한 대체재로 보면 문제가 생긴다. 감정 연기와 연출의 정밀도, 음성 사용 권리, 서비스 약관, 네트워크 의존성은 프로젝트 초기에 따져야 한다. 가장 안전한 접근은 개발 중에는 AI 보이스로 빠르게 검증하고 출시 품질이 필요한 핵심 장면은 별도 녹음 또는 충분한 연출 검수를 거치는 방식이다.
먼저 결정할 것: 실시간 생성인가, 사전 생성인가
게임 대사를 재생하는 방법은 크게 두 가지다.
- 사전 생성: 빌드 과정이나 콘텐츠 제작 단계에서 음성 파일을 만들어 게임에 포함한다.
- 실시간 생성: 플레이 중 API에 대사를 보내 음성을 받아 재생한다.
대부분의 싱글플레이 인디 게임에는 사전 생성이 적합하다. 지연 시간과 인터넷 연결 문제를 피하고 같은 대사가 매번 같은 타이밍으로 재생되며 API 호출 비용도 예측하기 쉽다. 플레이어 이름처럼 매번 달라지는 문장이나 생성형 NPC 대사처럼 정해진 파일을 둘 수 없는 경우에만 실시간 생성을 검토한다.
flowchart LR
A[대사 원고] --> B[음성 생성 도구]
B --> C[WAV 또는 MP3 검수]
C --> D[Unity AudioClip 등록]
D --> E[대화 이벤트에서 재생]
A --> F[실시간 생성이 필요한 동적 대사]
F --> G[서버에서 ElevenLabs API 호출]
G --> H[클라이언트로 오디오 전달]
실시간 생성 경로에서는 API 키를 Unity 클라이언트에 넣지 않는 것이 핵심이다. 빌드 파일은 추출될 수 있으므로 키는 서버 환경 변수에 보관하고 클라이언트는 자체 백엔드에 요청한다.
대사 원고를 음성용으로 다듬기
같은 문장이라도 화면용 텍스트와 음성용 원고는 다르다. 줄바꿈, 문장 부호, 숫자 표기는 발음과 호흡에 영향을 준다.
예를 들어 UI에는 HP +25가 자연스럽지만 음성 원고에는 체력이 25 회복됐다.처럼 풀어 쓰는 편이 안정적이다. 고유명사와 약어는 팀에서 발음 표기를 정해 두고 감정이나 행동 지시는 대사 데이터의 별도 필드로 관리한다.
{
"id": "village_guard_001",
"speaker": "village_guard",
"text": "이 시간에 성문 밖으로 나가겠다고? 조심하게.",
"direction": "낮고 차분하게 경고한다",
"audio": "Assets/Audio/Dialogue/village_guard_001.wav"
}
direction은 생성 서비스에 항상 그대로 전달하기보다 음성 선택과 생성 설정을 결정하는 제작 메모로 쓰는 편이 좋다. 모델과 기능에 따라 지시문 해석 방식이 달라질 수 있기 때문이다.

ElevenLabs에서 음성을 만들 때의 실무 기준
1. 목소리는 적게 시작한다
프로토타입에서는 주요 역할 2~4명만 먼저 정한다. 캐릭터마다 완전히 다른 목소리를 많이 쓰면 관리 비용이 커지고 장면 전체의 음량과 음색도 흔들리기 쉽다. 조연과 시스템 안내는 같은 계열의 목소리를 변형해도 충분한 경우가 많다.
2. 한 파일은 짧게 유지한다
대사를 문단 단위로 길게 합치지 말고 플레이 중 제어할 수 있는 한두 문장 단위로 분리한다. 그래야 스킵, 중단, 자막 동기화, 재생 우선순위 처리가 간단해진다. 수정된 한 줄만 다시 생성할 수도 있다.
3. 생성 결과는 반드시 검수한다
한국어 고유명사, 숫자, 외래어, 감정이 바뀌는 문장을 우선 확인한다. 특히 게임 용어는 문맥에 따라 엉뚱하게 읽힐 수 있다. 승인된 결과만 프로젝트에 넣고 원고·사용한 음성·생성 날짜·파일 버전을 함께 기록해 두면 재생성이 필요할 때 혼란이 줄어든다.
4. 권리와 공개 범위를 확인한다
사용하려는 음성과 생성물의 상업적 이용 가능 범위는 계약 플랜과 해당 서비스의 최신 약관을 기준으로 확인해야 한다. 실제 인물의 목소리를 흉내 내거나 복제하는 일은 명시적인 권한 없이 진행하면 안 된다. 플레이어에게 AI 생성 음성을 사용했다는 사실을 고지할지는 플랫폼 정책과 게임의 맥락을 검토해 정한다.
Unity에서 사전 생성 음성 재생하기
사전 생성한 WAV 또는 MP3를 AudioClip으로 임포트한 뒤 대사 ID와 클립을 연결한다. 대사 수가 적은 프로젝트라면 ScriptableObject 기반 데이터베이스가 간단하고 직관적이다.
using System;
using System.Collections.Generic;
using UnityEngine;
[Serializable]
public class DialogueVoiceEntry
{
public string id;
public AudioClip clip;
}
[CreateAssetMenu(menuName = "Game/Dialogue Voice Database")]
public class DialogueVoiceDatabase : ScriptableObject
{
[SerializeField] private List<DialogueVoiceEntry> entries = new();
private Dictionary<string, AudioClip> clips;
public bool TryGet(string id, out AudioClip clip)
{
clips ??= BuildLookup();
return clips.TryGetValue(id, out clip);
}
private Dictionary<string, AudioClip> BuildLookup()
{
var lookup = new Dictionary<string, AudioClip>();
foreach (var entry in entries)
{
if (!string.IsNullOrWhiteSpace(entry.id) && entry.clip != null)
{
lookup[entry.id] = entry.clip;
}
}
return lookup;
}
}
재생기는 자막 표시와 음성 재생을 한곳에서 시작하도록 만든다. 대사를 건너뛸 때는 AudioSource.Stop()으로 재생을 중단하고 자막 UI에도 같은 종료 이벤트를 전달하면 상태가 어긋나지 않는다.
using UnityEngine;
public class DialogueVoicePlayer : MonoBehaviour
{
[SerializeField] private DialogueVoiceDatabase voiceDatabase;
[SerializeField] private AudioSource voiceSource;
public void Play(string dialogueId)
{
voiceSource.Stop();
if (!voiceDatabase.TryGet(dialogueId, out var clip))
{
Debug.LogWarning($"음성 클립을 찾지 못했습니다: {dialogueId}");
return;
}
voiceSource.clip = clip;
voiceSource.Play();
}
public void Stop()
{
voiceSource.Stop();
}
}
대사 파일이 많아져 빌드 용량이 부담된다면 모든 클립을 처음부터 메모리에 올리지 말고 Addressables 같은 비동기 로딩 체계를 검토한다. 이때도 대사 ID는 변하지 않는 키로 유지해야 원고와 오디오 에셋의 연결이 깨지지 않는다.

실시간 API 연동은 서버를 경유한다
동적 대사를 실시간으로 음성화해야 한다면 Unity에서 ElevenLabs API를 직접 호출하지 말고 다음과 같은 구조를 사용한다.
- Unity가 대사 텍스트와 화자 ID를 게임 서버에 보낸다.
- 서버가 허용된 길이와 요청 빈도를 검사한다.
- 서버가 비밀 키로 ElevenLabs API를 호출한다.
- 서버가 받은 오디오를 캐시한 뒤 Unity에 전달한다.
- Unity가 다운로드한 데이터를
AudioClip으로 변환해 재생한다.
캐시는 같은 문장에 대한 중복 호출을 줄이는 데 중요하다. 화자, 모델, 생성 옵션, 정규화한 대사 텍스트를 합쳐 해시 키를 만들면 서로 다른 설정의 결과가 섞이는 일을 막을 수 있다.
// 클라이언트는 서비스 키가 아닌 게임 서버 주소만 알고 있어야 한다.
[Serializable]
public class VoiceRequest
{
public string dialogueId;
public string text;
public string speaker;
}
네트워크 오류가 나도 대화 진행이 막히지 않도록 텍스트 자막만 표시하는 대체 경로를 준비한다. 로딩이 길어질 수 있는 음성은 재생 버튼을 기다리게 하기보다 다음 대사를 미리 요청하거나 짧은 무음 지연을 연출에 포함하는 편이 낫다.
출시 전 점검 목록
- 모든 대사 ID에 자막과 음성 파일이 각각 연결되는지 확인한다.
- 음량 기준을 정하고 캐릭터 간 체감 음량을 비교한다.
- BGM과 효과음이 있는 실제 게임 장면에서 발음과 전달력을 확인한다.
- 스킵, 자동 진행, 일시 정지, 저장·불러오기에서 음성이 남거나 중복되지 않는지 테스트한다.
- 오프라인 환경과 API 실패 상황에서 자막만으로 게임이 진행되는지 확인한다.
- 음성·생성물·배포에 관한 최신 이용 약관과 사용 권한을 출시 직전에 다시 검토한다.
마무리
AI 보이스의 강점은 단순히 비용을 줄이는 데 있지 않다. 대사와 연출을 빠르게 반복 검증할 수 있다는 점이 더 크다. 먼저 짧은 장면 하나를 사전 생성 음성으로 끝까지 연결해 보고 발음 검수와 스킵 처리, 자막 동기화가 안정된 뒤에 범위를 넓히면 인디 게임 규모에서도 관리 가능한 더빙 파이프라인을 만들 수 있다.


