다국어 TTS 4종을 같은 GPU에서 재봤습니다: 12배 차이와, 채점기가 거짓말한 세 번
한국어와 일본어까지 서빙해야 하는 음성합성 엔드포인트를 고르고 있다면, 모델 카드에 적힌 자연성 점수보다 RTF와 유휴 전력 비중을 먼저 보시는 편이 낫습니다. 같은 B200 한 장에서 VoxCPM2는 Qwen3-TTS보다 12배 빨랐고, Qwen3-TTS가 소비한 전력의 86.7%는 합성과 아무 상관이 없는 유휴분이었습니다.
네 개 모델을 한국어, 영어, 중국어, 일본어에서 같은 하네스로 돌렸습니다. 본문 셋은 평문부터 숫자, 외래어, 전문용어, 의문문, 복합문까지 여섯 범주로 나눴고, 감정 셋은 감정중립 문장을 여섯 가지 감정으로 각각 합성했습니다. 다섯 축을 쟀습니다. 속도, 전력, 명료도, 자연성, 그리고 감정 표현력입니다.
속도에서 갈립니다
RTF는 낮을수록 빠릅니다. 1.0이면 1초짜리 음성을 만드는 데 정확히 1초가 걸린다는 뜻입니다.
| 모델 | 하드웨어 | RTF 중앙값 | 오디오 1초당 전력 | GPU 유휴비중 |
|---|---|---|---|---|
| VoxCPM2 | B200 | 0.100 | 25.8 J | 43.4% |
| Kokoro-82M | CPU 32코어 | 0.640 | 7.5 J | 해당없음 |
| Qwen3-TTS-1.7B | B200 | 1.196 | 40.1 J | 86.7% |
| Supertonic-3 | CPU 32코어 | 2.498 | 50.4 J | 해당없음 |
Qwen3-TTS는 실시간보다 느립니다. B200 한 장으로 한 스트림도 못 따라간다는 뜻이라, 실시간 대화형 서비스에 그대로 얹으면 첫 발화부터 밀립니다. 같은 카드에서 VoxCPM2는 0.100이니 열 스트림을 여유 있게 감당합니다.
전력에서 더 중요한 숫자는 유휴비중입니다. Qwen3-TTS 엔드포인트는 배치를 채우지 못하면 전력의 86.7%를 그냥 태웁니다. GPU를 통째로 임대하는 서빙에서는 이 유휴분도 우리가 내는 돈이라, 원가 계산은 순증분이 아니라 절대값으로 해야 맞습니다. 반대로 VoxCPM2의 43.4%는 같은 카드가 훨씬 촘촘하게 일하고 있다는 뜻입니다.
Kokoro-82M은 CPU 32코어에서 오디오 1초당 7.5J로 가장 적게 썼습니다. 영어와 중국어만 필요하고 지연에 여유가 있다면 GPU를 아예 안 쓰는 선택지가 있습니다.
다만 표의 CPU 두 줄에서 전력 값은 신뢰하지 마시기 바랍니다. 같은 설정을 세 번 반복해 보니 Supertonic의 전력이 50.4, 44.0, 133.6으로 178% 흔들렸습니다. 같은 실행의 RTF는 7.9%만 움직였는데도요. 원인은 공유 노드의 유휴 기준선이었습니다. 노드가 조용할 때 기준선을 잡으면 합성 도중 도착한 이웃 작업의 전력이 전부 우리 몫으로 계산됩니다. 절대값으로 보면 같은 세 번이 1581, 1449, 1440으로 9.7% 안에 들어옵니다. GPU 전용 노드에서는 순증분도 안정적이라 VoxCPM2와 Qwen3-TTS의 전력 비교는 그대로 유효하고, CPU 쪽은 속도만 비교하는 편이 맞습니다.
명료도는 전부 통과했지만, 통과 지점이 다릅니다
합성한 음성을 Whisper-large-v3로 다시 받아쓰고 원문과 대조했습니다. 네 모델 모두 중앙값 기준으로는 임계를 통과했습니다. 한국어와 영어는 사실상 오류가 없었습니다.
갈리는 곳은 상위 10%입니다. Qwen3-TTS의 일본어 p90은 0.413, VoxCPM2의 일본어는 0.438로 꽤 크게 깨집니다. 범주별로 쪼개 보면 원인이 분명해집니다. 평문과 의문문, 복합문은 오류가 0에 가깝고 숫자와 전문용어에서만 실패가 몰립니다. 기사를 읽어주는 용도라면 무해하지만 금액과 일시, 제품 코드를 읽어야 한다면 바로 그 두 범주가 사고 지점입니다.
감정은 속도와 함께 오지 않았습니다
감정 축은 EFI라는 결정론 지표로 쟀습니다. 같은 문장을 여섯 감정으로 합성한 뒤 F0와 에너지, 포즈 등 아홉 개 프로소디 특징이 조건마다 얼마나 흔들리는지를 0에서 1 사이로 정규화합니다. 0에 가까우면 감정을 지시해도 소리가 안 바뀐다는 뜻입니다.
Qwen3-TTS가 0.408, Supertonic-3이 0.255, Kokoro-82M이 0.024였습니다.
마지막 값이 나머지를 읽는 기준을 줍니다. Kokoro-82M에는 감정 조절 API가 아예 없습니다. 어댑터가 감정 인자를 받기는 하지만 쓰지 않으니 여섯 조건이 사실상 같은 입력이고, 따라서 0.024는 감정에 반응하지 않는 모델의 점수가 아니라 조건이 걸리지 않았을 때 이 지표가 내는 값입니다. 샘플링 비결정성만으로 생기는 바닥인 셈입니다.
바닥을 알고 나면 해석이 달라집니다. Supertonic-3 영어의 0.157은 절대값으로 보면 낮지만 바닥의 6.5배이니 얕게나마 실재하는 반응이고, Qwen3-TTS의 0.408은 17배입니다. 바닥 없이 0.157만 보면 거의 안 움직인다고 읽히지만, 비교 기준을 두면 움직이긴 하는데 얕다는 쪽이 정확합니다.
여기까지는 소리가 얼마나 달라지느냐입니다. 요청한 감정으로 실제로 들리는지는 별개라서, 감정 분류기로 한 번 더 쟀습니다. 요청한 감정과 분류 결과가 맞는 비율은 Qwen3-TTS 0.403, Supertonic-3 0.222, Kokoro-82M 0.167이었습니다.
마지막 숫자를 보시면 좋겠습니다. 여섯 감정을 균등하게 찍었을 때의 우연 확률이 0.167인데 Kokoro가 정확히 거기 앉았습니다. 감정 조절 API가 없다는 사실을 프로소디 분산과 감정 분류라는 서로 다른 두 관측이 각각 확인한 셈입니다.
동시에 절대 수준은 낮게 읽는 편이 정확합니다. 가장 잘한 Qwen3-TTS조차 0.403이니 요청한 감정이 분류기까지 전달되는 비율이 절반을 넘지 못합니다. TTS의 감정 지시는 켜면 그 감정이 되는 스위치가 아니라 그쪽으로 조금 기울이는 손잡이에 가깝습니다.
속도에서 압도적이던 VoxCPM2는 이 표에 아예 올리지 못했습니다. 스타일 지시를 레퍼런스 오디오와 쌍으로만 받기 때문에, 텍스트 지시만 주면 합성 자체가 실패합니다. 여기서 조용히 중립 음성으로 대체했다면 EFI는 “이 모델은 감정 변화가 없다”고 읽혔을 텐데, 실제로는 조건이 걸리지도 않은 것이라 정직하게 제외했습니다.
쌍별 분리도를 보면 두 모델이 서로 다른 감정을 뭉갭니다. Qwen3-TTS는 놀람이 문제입니다. 가장 안 갈리는 네 쌍 중 셋이 놀람 조합이라, 놀람을 중립이나 기쁨과 잘 구분하지 못합니다. Supertonic-3은 각성도가 높은 감정끼리 뭉쳐서 공포와 기쁨, 분노와 기쁨을 흐리게 만듭니다.
Supertonic-3에서 하나 더 눈에 띈 것은 영어 EFI가 0.157로 유독 낮았다는 점입니다. 같은 모델의 일본어가 0.354이니 모델 전체가 약한 게 아니라 영어 경로에서만 감정 지시가 약하게 먹는 셈입니다.
그런데 채점기가 세 번 거짓말했습니다
여기까지가 결과이고, 실은 이쪽이 더 값비싼 교훈이었습니다. 측정 도중 성공을 보고하면서 실제로는 0건을 채점하던 평가기를 세 개 찾았습니다.
첫 번째는 자연성 채점기였습니다. UTMOS 모델은 GPU에 올려놓고 입력 텐서는 CPU에 둬서 120건이 전부 죽었는데, 원장에는 실패 0건으로 적혔습니다. 결정론 폴백 지표가 대신 채워져 있었기 때문에 겉보기에는 멀쩡한 결과처럼 보였습니다.
두 번째는 감정 채점기였습니다. 특징 추출 결과의 유효성 플래그를 만드는 쪽은 ok라는 키를
쓰는데, 그걸 읽는 쪽은 _ok를 보고 있었습니다. 밑줄 하나 차이로 열두 그룹이 전부 무효 처리됐고,
감정 발화 72건을 멀쩡히 합성해 놓고도 감정 축 전체가 조용히 0이 됐습니다.
세 번째는 그 위에 있던 스모크 게이트였습니다. 감정 합성이 60건 실패하고 12건만 성공했는데도 통과 판정이 나왔습니다. 판정식이 “성공한 감정 레코드가 하나도 없으면 실패”였기 때문에, 중립 조건 12건이 성공한 것만으로 게이트를 넘어간 겁니다.
세 사례의 공통점은 부분 성공이 완전 성공으로 미끄러졌다는 것입니다. 그래서 위험도는 이 순서로 올라갑니다. 게이트가 아예 없는 것보다 게이트가 있는데 아무것도 안 보는 쪽이 위험하고, 그보다 더 위험한 것은 게이트가 보고는 있는데 판정식이 느슨한 경우입니다. 마지막은 숫자까지 나와서 진짜처럼 보이기 때문입니다.
처방은 셋 다 같았습니다. 기대치 대비로 판정하는 것입니다. 감정 발화가 존재하는데 채점된 그룹이 0이면 그건 감정이 없는 모델이 아니라 채점기 고장이므로, 이제 명시적으로 실패를 내고 종료 코드를 0이 아닌 값으로 돌려줍니다.
유휴 전력을 언제 재느냐가 결과를 8배 바꿉니다
전력 측정에서도 비슷한 함정을 밟았습니다. 같은 모델을 같은 노드에서 같은 코드로 재는데 순증분 전력이 61W와 7.6W로 갈렸습니다. 차이는 단 하나, 유휴 베이스라인을 언제 쟀느냐였습니다.
모델을 올리기 전 차가운 상태에서 재면 유휴가 190W로 잡히고, 워밍업 직후 뜨거운 상태에서 재면 261W로 잡힙니다. 뒤쪽으로 재면 이미 데워진 상태를 유휴로 간주하는 셈이라 순증분이 거의 사라집니다. 기존 오염 감지 플래그는 GPU 사용률 5% 초과를 봤는데 이때가 4%여서 걸리지도 않았습니다.
세 가지를 고쳤습니다. 베이스라인 측정 전에 30초를 쉬어 클럭이 내려갈 시간을 주고, 잔열 전용 플래그를 오염 플래그와 별도로 뒀으며, 절대값을 1차 지표로 승격했습니다. 절대값은 베이스라인 선택에 둔감하고, GPU를 통째로 임대하는 서빙 원가 관점에서도 그쪽이 맞는 질문입니다.
아직 못 잰 것
정직하게 남깁니다. 계획 단계에서 1차 자연성 지표로 잡았던 TTSDS2를 측정하지 못했습니다. 합성 집합과 실음성 레퍼런스 집합을 분포로 비교하는 지표인데 언어별 레퍼런스 코퍼스를 확보하지 못했습니다. 그래서 이 글의 자연성 관련 언급은 2차 지표인 UTMOS에 기대고 있고, UTMOS는 영어로 학습된 예측기라 한중일 값은 보정되지 않았습니다. 같은 언어 안에서 모델을 줄 세우는 데는 쓸 수 있지만 언어 사이를 비교하는 데는 쓰면 안 됩니다.
감정도 절반만 쟀습니다. EFI는 “얼마나 달라지는가”를 재지 “그 감정답게 들리는가”를 재지 않습니다. 후자를 담당할 음성감정인식 축은 의존성 문제로 돌리지 못했습니다.
로스터에 올린 열두 모델 중 여덟은 완주하지 못했습니다. 파이썬 API 계약이 확인되지 않아 추측으로 구현하기를 거부한 것이 둘, 설치와 버전 충돌이 둘, 나머지는 미착수입니다. Kokoro의 일본어는 형태소 분석기 초기화가 파드 환경에서 실패했는데, 이건 모델의 한계가 아니라 환경 제약이라 로스터에 “지원한다고 주장하는 언어”와 “우리가 실제로 잰 언어”를 따로 기록해 뒀습니다.
정리하면
실시간 대화형 서비스라면 VoxCPM2의 RTF 0.100이 매력적이지만 감정 조건을 레퍼런스 오디오 없이 못 받는다는 제약을 함께 받아야 합니다. 감정 표현이 필요하다면 Qwen3-TTS가 EFI 0.408로 앞서지만 실시간보다 느리고 유휴 전력을 크게 버립니다. 영어와 중국어만 필요하고 지연에 여유가 있다면 Kokoro-82M을 CPU에 얹는 선택이 전력에서 가장 쌉니다.
그리고 어떤 모델을 고르든, 채점기가 정말로 채점하고 있는지부터 확인하시길 권합니다. 저희는 세 번 속았습니다.
측정 원장과 하네스는 사내 저장소에 있고, 합성 오디오는 모델당 16MB에서 44MB 규모로 함께 보관합니다. 오디오를 남겨두면 채점 로직을 고친 뒤 GPU 없이 다시 채점할 수 있습니다. 이번에 그걸 안 해둔 모델 하나는 버그를 고친 뒤 120발화를 GPU에서 통째로 다시 합성해야 했습니다.