
ElevenLabs AI 보이스 더빙: 인디 ARPG를 위한 저비용 음성 대사 파이프라인
대사 설계부터 생성, 검수, Unity 반영까지를 분리해 재생성 비용과 운영 부담을 줄이는 AI 보이스 더빙 워크플로를 정리한다. ElevenLabs를 예시로 들되 특정 요금제나 기능에 의존하지 않는 구조를 다룬다.
왜 음성 파이프라인을 먼저 설계해야 할까
인디 ARPG의 음성 대사는 전투, 퀘스트, 상점, 컷신처럼 여러 시스템에 걸쳐 늘어난다. 대사를 수정할 때마다 전체 음성을 다시 만들면 생성 크레딧과 검수 시간이 빠르게 소모된다. 핵심은 AI 음성을 많이 만드는 일이 아니라 바뀐 대사만 안전하게 다시 만들 수 있는 구조를 갖추는 것이다.
ElevenLabs 같은 음성 생성 서비스는 빠른 시안 제작과 반복 작업에 유용하다. 다만 결과물의 품질은 서비스 이름보다 대본 구조, 발음 표기, 파일 규칙, 게임 내 검수 과정에 더 크게 좌우된다.

전체 작업 흐름
아래 흐름에서는 대본을 원본 데이터로 두고 생성된 오디오는 언제든 교체 가능한 산출물로 취급한다. 게임 코드에서 문장 자체나 파일명을 직접 참조하지 않는 것이 중요하다.
flowchart LR
A[대사 원본 CSV 또는 스프레드시트] --> B[대사 ID와 상태 관리]
B --> C[발음 표기와 연기 지시 추가]
C --> D[ElevenLabs에서 음성 생성]
D --> E[파일명 및 메타데이터 검증]
E --> F[Unity Addressables 또는 AudioClip 등록]
F --> G[게임 내 자막·음성 동기화 검수]
G --> H{수정 필요?}
H -- 예 --> B
H -- 아니오 --> I[배포 후보 확정]
1. 대사를 문장이 아닌 데이터로 관리하기
대본에는 최소한 다음 필드를 둔다. 스프레드시트로 시작해도 충분하지만 대사 ID는 처음부터 고정해야 한다.
| 필드 | 예시 | 용도 |
|---|---|---|
line_id | q_main_010_merchant_003 | 코드와 오디오를 연결하는 고유 키 |
speaker | merchant | 화자와 보이스 프리셋 선택 |
text_ko | 오늘은 장사가 잘될 것 같은데. | 화면 자막과 기본 대사 |
tts_text_ko | 오늘은 장사가 잘될 것 같은데. | 발음 표기를 반영한 생성용 문장 |
direction | 밝게, 손님을 반기는 어조 | 연기 의도 |
revision | 3 | 재생성 여부 추적 |
status | approved | 초안·검수·확정 상태 |
line_id에 대사의 순번만 넣으면 퀘스트 삽입이나 삭제 때 연결이 흔들린다. 지역, 퀘스트, 화자, 의미 있는 순서 정보를 조합한 ID가 유지보수에 적합하다.
또한 자막용 문장과 생성용 문장을 분리한다. 예를 들어 화면에는 HP 포션을 표시하되 음성 생성용 문장에는 에이치피 포션 또는 게임 세계관에 맞는 읽는 법을 넣을 수 있다. 플레이어가 보는 문장과 모델에 전달할 문장은 반드시 같을 필요가 없다.
2. 재생성 비용을 줄이는 대사 작성 규칙
한 파일에 긴 독백을 넣으면 생성 횟수는 줄어든다. 하지만 대사 한 줄만 바뀌어도 긴 파일 전체를 다시 생성해야 하고 자막 타이밍 조정도 어려워진다. 반대로 지나치게 잘게 쪼개면 파일 수와 호출 관리 비용이 커진다.
실무적으로는 플레이 중 독립적으로 재생되는 자막 한 묶음을 파일 하나로 두는 편이 좋다. 전투 중 외침은 짧게 컷신의 감정 변화가 이어지는 문장은 의미 단위로 묶는다.
예상 생성량은 문자 수를 기준으로 간단히 추정할 수 있다.
수정으로 다시 생성하는 비율까지 고려하면 다음처럼 예산 여유를 잡을 수 있다.
여기서 재생성 비율은 초안 단계일수록 높다. 따라서 모든 대사를 한꺼번에 확정하려 하기보다 대표 화자와 핵심 퀘스트 일부로 음색과 문체를 먼저 검증하는 편이 안전하다.
3. ElevenLabs 생성 단계에서 고정할 것
서비스 화면이나 API를 사용하더라도 다음 항목은 대사별로 흔들리지 않게 관리한다.
- 화자별 보이스 ID 또는 프리셋
- 언어와 모델 설정
- 속도, 안정성, 스타일처럼 결과에 영향을 주는 옵션
- 입력 대본과 생성 일시
- 생성된 파일의 경로와 대사 ID
설정값을 스프레드시트나 JSON 메타데이터에 기록해 두면 나중에 음색을 바꾸거나 누락 파일을 다시 만들 때 같은 조건을 재현할 수 있다. UI에서 수동으로 생성했다면 최소한 line_id, 사용 보이스, 설정값, 검수 결과를 남긴다.
발음 검수에서는 고유명사, 스킬명, 숫자, 단위, 영문 약어를 우선 확인한다. 특히 Lv. 10, 10m, MP처럼 UI에서는 자연스럽지만 한국어 음성으로 읽기 모호한 표현은 생성용 대본에서 풀어 쓰는 편이 낫다.

4. 파일명과 폴더 규칙
오디오 파일명은 사람이 읽기 좋은 문장보다 기계가 안정적으로 찾을 수 있는 ID를 써야 한다. 예를 들면 다음과 같다.
Assets/Audio/Voice/ko/merchant/q_main_010_merchant_003_r03.wav
권장 규칙은 언어/화자/대사ID_리비전.확장자다. 최종 배포에서는 리비전 접미사를 제거하거나 메타데이터에서 현재 리비전을 가리키게 만들 수 있다. 중요한 점은 기존 파일을 덮어쓴 뒤 어떤 음성이 배포되었는지 알 수 없게 만들지 않는 것이다.
압축 형식은 프로젝트의 대상 플랫폼과 메모리 예산에 맞춰 결정한다. 원본은 편집 가능한 무손실 형식으로 보관하고 게임 빌드용 압축은 Unity Import Settings에서 별도로 관리하면 재인코딩과 품질 확인이 수월하다.
5. Unity에서 대사 ID로 재생하기
대사 시스템은 line_id를 받아 자막과 오디오를 함께 조회하도록 만든다. 아래 예시는 작은 프로젝트에서 사용할 수 있는 단순한 ScriptableObject 기반 구조다. 대규모 프로젝트라면 Addressables 키로 AudioClip을 비동기 로드하는 방식으로 확장할 수 있다.
using System;
using System.Collections.Generic;
using UnityEngine;
[Serializable]
public class VoiceLine
{
public string lineId;
[TextArea] public string subtitle;
public AudioClip clip;
}
[CreateAssetMenu(menuName = "Game/Voice Line Database")]
public class VoiceLineDatabase : ScriptableObject
{
[SerializeField] private List<VoiceLine> lines = new();
private Dictionary<string, VoiceLine> lookup;
public bool TryGet(string lineId, out VoiceLine line)
{
lookup ??= BuildLookup();
return lookup.TryGetValue(lineId, out line);
}
private Dictionary<string, VoiceLine> BuildLookup()
{
var result = new Dictionary<string, VoiceLine>();
foreach (var line in lines)
{
if (string.IsNullOrWhiteSpace(line.lineId))
{
continue;
}
if (!result.TryAdd(line.lineId, line))
{
Debug.LogError($"중복된 음성 대사 ID: {line.lineId}");
}
}
return result;
}
}
재생 코드에서는 오디오가 없을 때도 자막을 표시하고 경고를 남긴다. 이 처리가 없으면 음성 파일 누락이 UI 문제처럼 보이거나 특정 빌드에서 대사가 통째로 사라질 수 있다.
using UnityEngine;
public class DialogueVoicePlayer : MonoBehaviour
{
[SerializeField] private VoiceLineDatabase database;
[SerializeField] private AudioSource voiceSource;
public void Play(string lineId)
{
if (!database.TryGet(lineId, out var line))
{
Debug.LogError($"등록되지 않은 대사 ID: {lineId}");
return;
}
// 실제 프로젝트에서는 이 지점에서 line.subtitle을 자막 UI에 전달한다.
if (line.clip == null)
{
Debug.LogWarning($"음성 파일이 없는 대사 ID: {lineId}");
return;
}
voiceSource.Stop();
voiceSource.clip = line.clip;
voiceSource.Play();
}
}
6. 검수는 파형보다 플레이 상황에서 한다
생성 직후 파일을 듣는 검수만으로는 충분하지 않다. BGM, 효과음, 전투 소음, 카메라 거리와 함께 재생해야 실제 문제를 찾을 수 있다.
다음 항목을 체크리스트로 운영하면 좋다.
- 자막이 음성보다 너무 빨리 사라지지 않는가
- 공격 피격음과 겹쳐도 핵심 정보가 들리는가
- NPC 간 음량과 발화 속도 차이가 과하지 않은가
- 퀘스트 분기에서 잘못된 대사 ID가 재생되지 않는가
- 저장·불러오기나 씬 전환 뒤 음성이 중복 재생되지 않는가
- 언어 전환 시 이전 언어 클립이 남지 않는가
특히 전투 대사는 연기의 자연스러움보다 인지성이 우선일 때가 많다. 짧고 강한 문장으로 다시 쓰고 효과음과의 우선순위를 조절하는 편이 무조건 더 감정적인 음성을 만드는 것보다 효과적일 수 있다.
7. 권리와 배포 전 확인 사항
상용 배포 전에는 사용하는 음성 생성 서비스의 최신 약관과 선택한 음성의 사용 범위를 직접 확인해야 한다. 타인의 목소리를 복제하거나 특정 실존 인물을 연상시키는 음성을 쓰려면 명시적인 권한이 필요하다. 성우를 고용해 학습 또는 복제용 음성을 받는 경우에도 사용 기간, 매체, 2차 활용, 철회 조건을 계약서에 분명히 적어야 한다.
AI 생성 음성을 사용했다는 사실을 공개할지 여부는 프로젝트와 플랫폼 정책에 따라 결정할 문제다. 다만 팀 내부에서는 어떤 대사가 어떤 도구와 설정으로 만들어졌는지 추적 가능하게 관리해야 수정 요청이나 권리 확인에 대응할 수 있다.
마무리
저비용 파이프라인의 목표는 가장 싼 음성을 얻는 것이 아니다. 대사 ID, 발음 표기, 생성 설정, 검수 상태를 분리해 관리하면 수정이 잦은 인디 ARPG에서도 필요한 파일만 다시 만들 수 있다. 먼저 핵심 화자 몇 명과 짧은 퀘스트 한 구간으로 이 구조를 시험한 뒤 검수 기준이 잡혔을 때 전체 대사로 확장하는 것이 가장 안정적이다.


