음성 제작 요청은 말투와 연령을 고르는 단계에서 더 구체적으로 바뀌었다. 캐릭터 하나를 정하면 그 목소리를 유지하면서 감정만 달라지게 하고 싶다는 것이었다. 이어 연령별 남녀 캐릭터를 고정해 등록하고, 각각 기쁨·슬픔·분노를 같은 문장으로 비교하게 해 달라는 요구가 나왔다.
여기서 먼저 짚을 것은 ‘같은 목소리’의 기준이다. 설명문을 다시 쓰는 것과 기준 음성을 재사용하는 것은 다르다. 참조 자료가 같아도 결과가 같은 캐릭터로 들리는지는 직접 들어 봐야 한다. 로컬 코드와 기존 검사 기록을 이 기준으로 살폈다.
다음 원고에서도 같은 캐릭터를 부르기
말투·연령·감정을 조합하면 새 목소리의 방향을 탐색할 수 있다. 하지만 다음 원고에서도 같은 인물을 쓰려면 그때 고른 기준을 남겨야 한다. 이 작업에서는 선택한 목소리를 캐릭터 프로필로 저장하도록 확장했다.
캐릭터 등록 코드는 기준 음성, 그 음성이 읽은 원고, 화자의 특징을 담은 벡터와 참조 음성 코드, 기본 말투·연령·시드를 한 프로필에 연결한다. 여기서 벡터와 음성 코드는 다음 합성에 다시 넣을 조건이다. 사람을 판별하는 정확도나 동일 인물일 확률을 뜻하지 않는다.
현재 생성 계획은 저장된 캐릭터를 선택하면 그 프로필의 기본 말투와 연령을 사용한다. 같은 요청에서 모드나 연령까지 바꾸려 하면 오류를 낸다. 새 음색을 만들고 싶은 요청은 새 캐릭터 등록으로 보내고, 이미 고른 캐릭터를 연기시키는 요청은 그 기준을 재사용하게 한 것이다.
남겨 둘 기준과 바꿀 연기를 다른 칸에 둔다
기쁨이나 분노를 지시할 때 프로필의 기준 음성과 화자 자료를 덮어쓰지 않는다. 생성 코드는 저장된 참조 자료를 읽고, 기본 지시 뒤에 이번 감정의 연기 지시를 덧붙인다. 실행 전후에는 참조 텐서의 해시를 대조하고, 결과 기록에 어떤 기준을 사용했는지 남긴다.
프로필을 읽는 코드도 기준 음성과 캐시 파일의 해시가 저장된 값과 다르면 중단한다. 이름이 같다는 이유만으로 다른 파일을 조용히 받아들이지 않으려는 경계다. 등록 이름이 겹칠 때 기존 캐릭터를 덮어쓰지 않는 처리도 있다. 반복 제작에서 비교할 기준이 사라지지 않게 한 선택이다.
설치된 로컬 구현은 Qwen3-TTS의 기존 추론 코어에 감정 지시와 고정된 화자·참조 조건을 함께 넣는 실험 방식이다. 단순히 시드를 같게 했다는 설명으로 이 범위를 대신하지 않는다. 반대로 참조 조건이 같다고 결과의 음색까지 완전히 같다고 말하지도 않는다. 프로그램이 고정한 것은 입력 조건이며, 들리는 결과는 별도로 확인해야 한다.
감정 이름을 늘리는 대신, 필요한 연기를 문장으로 적는다
현재 모듈은 감정 프리셋 60종에 자유 설명과 혼합 지시를 더한다. 자주 쓰는 감정은 목록에서 고르고, 미묘한 상황은 문장으로 적을 수 있게 했다. 목록에 없는 말이라고 새 캐릭터를 만들거나 감정 이름을 매번 코드에 추가할 필요는 없다.
혼합 지시의 숫자에도 해석 범위를 남겼다. 분노 3, 슬픔 1을 넣으면 상대적인 강조값으로 정리해 연기 지시에 사용한다. 결과 음성에 분노가 75% 들어 있다고 측정한 값은 아니다. NaN·무한값·0이나 음수 같은 가중치는 거절하는 갈래가 있고, 기존 시험에는 이런 입력을 구별하는 검사가 있다.
실무에서는 ‘슬프게’라는 한 단어 뒤에 원고를 어떻게 읽을지 덧붙이는 편이 판단하기 쉽다. 예를 들어 소리를 크게 내는 분노와 화를 억누르며 낮게 말하는 분노는 원하는 결과가 다르다. 감정 이름, 강도, 호흡과 속도의 방향을 나누어 적으면 무엇을 고칠지도 구체적으로 말할 수 있다.
같은 문장을 읽게 해야 비교할 차이가 줄어든다
연령별 캐릭터 작업은 남녀 20명을 등록하고 각 캐릭터의 기쁨·슬픔·분노를 같은 문장으로 만들었다. 기존 검증 기록에는 기준 음성 20개와 감정 샘플 60개, 고정 참조 조건의 재사용과 파일 검사가 남아 있다. 이번 집필에서는 그 기록과 검사 코드를 읽었으며 음성을 새로 생성하거나 청취하지 않았다.
감정 프리셋 60종과 비교 음성 60개는 서로 다른 숫자다. 비교 음성은 20명에게 세 감정을 적용한 결과다. 20명 모두에게 60종의 감정을 적용한 1,200개 조합을 확인한 기록으로 바꾸어 읽으면 안 된다. 연령 이름도 합성 목소리를 설계한 범주이며 청취로 판정한 실제 나이가 아니다.
같은 원고를 사용하면 문장 내용과 길이까지 함께 달라지는 비교를 피할 수 있다. 다음은 이 글을 위해 새로 쓴 독립적인 연기 지시 예시다. 등록된 실제 캐릭터명이나 실행 명령이 아니며 음성으로 생성하지 않았다. 같은 캐릭터·같은 문장을 두고 지시만 어떻게 바꿀지 보여 준다.
코드와 구현 살펴보기
독립 집필 예시 · 음성 생성/청취 없음
고정할 것: 안내자 A의 기준 음성과 같은 원고
원고: 오늘은 여기서 잠시 쉬어 가도 괜찮아요.
차분한 안내: 낮은 에너지, 고른 속도, 문장 끝을 부드럽게.
기쁘지만 조심스러운 안내: 처음은 밝게, 뒤로 갈수록 힘을 덜어내기.
서운함을 누르는 말: 짧게 숨을 고른 뒤 말하고, 끝을 크게 올리지 않기.파일 검사 뒤에 남는 것은 듣고 고를 일이다
기존 자동 검사는 기준 파일과 캐시가 유지됐는지, 예상한 캐릭터와 감정이 기록됐는지, 음성 파일이 유효한지 확인한다. 최종 검사 코드는 같은 비교 원고, 참조 해시, 실제 생성 장치와 생성 종료 상태까지 대조한다. 재생 화면에 필요한 파일이 연결됐는지도 검사한다.
이런 검사를 통과하면 무엇을 비교하는지 추적하기 쉬워진다. 그러나 자연스러운 호흡인지, 같은 캐릭터로 들리는지, 감정이 과장되거나 약한지까지 파일 해시로 판단할 수는 없다. 기존 결과 문서도 지각적인 음색·연령·감정 검수는 별도로 남겼다.
다른 작업에 적용할 때는 짧은 동일 문장으로 캐릭터와 감정의 방향을 고른 뒤, 사용할 긴 원고로 다시 들어 보는 순서가 적절하다. 단어 발음, 문장 사이의 호흡, 감정 전환과 전체 음량을 살핀다. 여기까지는 적용 제안이며, 이번 집필에서 긴 원고를 청취한 것은 아니다.
다음 편의 목소리를 고를 수 있게 기록을 남긴다
홈페이지 소개 영상이나 연속 안내 음성을 기획한다면 ‘따뜻한 목소리’라는 말만으로 다음 제작을 시작하지 않게 하고 싶다. 어떤 캐릭터의 기준을 썼는지, 원고와 감정 지시는 무엇이었는지, 어떤 결과를 골랐고 무엇이 아쉬웠는지 함께 남기는 방식이다. 이 사례의 생성 JSON도 캐릭터 기준·감정 계획·원고·실제 지시·결과 해시를 구별해 저장한다.
다시 만들 때는 먼저 캐릭터와 원고를 유지하고 수정할 연기 지시를 좁힌다. 음색 자체가 마음에 들지 않으면 캐릭터 설계로 돌아갈 수 있지만, 감정 하나를 바꾸려다 기준 음성까지 교체하지는 않는다. 이전에 고른 결과를 보관해야 새 결과와 비교하고 되돌릴 수 있다.
이 구조는 기준 음성을 보존하며 연기를 바꿔 보는 로컬 제작 방식이다. 모든 감정을 검수한 성우 라이브러리는 아니다. 원래 기준 음성·샘플·화자 자료는 이 글에 첨부하지 않았고, 다른 홈페이지의 음성 기능이나 공개 시연을 구현한 결과도 아니다.