트렌딩 딥다이브 · 2026-07-18 · OSSInsight #28

supertone-inc/supertonic 딥다이브
— 99M짜리 작은 모델로 클라우드·GPU 없이 31개 언어를 말하는 온디바이스 TTS

supertonic텍스트를 사람 목소리로 바꾸는 TTS(음성 합성)를, 클라우드·API·GPU 없이 내 기기의 CPU에서 돌리는 오픈 음성 엔진이다. 한국의 음성 AI 기업 Supertone Inc.(supertone.ai)가 만든 99M(약 1억) 파라미터짜리 작은 open-weight 모델을, ONNX Runtime 위에서 4개의 그래프로 나눠 돌려 텍스트 → 44.1kHz WAV 오디오를 만든다. 먼저 오해를 풀자 — 이건 ElevenLabs·OpenAI TTS 같은 클라우드 서비스가 아니다. 네트워크가 끊긴 라즈베리파이·전자책 단말기에서도 도는 완전 온디바이스 엔진이다. 두 번째로 각인할 것 — 이 저장소의 진짜 매력은 "하나의 모델, 11개 언어(런타임)"다. Python·Node·브라우저(WebGPU)·Java·C++·C#·Go·Swift·iOS·Rust·Flutter 각각에서 같은 4개 ONNX 모델을 로드해 돌리는 예제가 전부 완성돼 있다. 이 문서는 소스를 직접 클론해 "이 저장소에서 무엇을 배울 수 있는가"를 파고든다. (저장소: supertone-inc/supertonic · ONNX Runtime · MIT(코드) / OpenRAIL-M(모델) · Supertonic 3(≈99M 파라미터·31개 언어) · 최신 커밋 2026-05-22 · 별 13,242 · 이번 회차는 TrendShift Daily·Weekly·Monthly가 모두 기분석 소진되어 OSSInsight 순위로 폴백)
목차
  1. 프로젝트 한 줄 요약
  2. 왜 지금 주목받는가
  3. 기술 스택 전체 지도
  4. 아키텍처 심화 분석
  5. 디렉토리 구조 해부
  6. 학습 포인트
  7. 하드웨어 · 시스템 요구사항
  8. 직접 해볼 수 있는 실습 과제
  9. 관련 기술 심화 학습 로드맵
  10. 핵심 키워드 사전
  11. 참고 링크

1프로젝트 한 줄 요약

"텍스트 → 목소리"를, 클라우드 없이 내 기기에서 — ONNX로 돌리는 99M짜리 31개 언어 온디바이스 TTS

supertone-inc/supertonic텍스트를 음성으로 읽어 주는(Text-to-Speech, TTS) 모델을 내 컴퓨터·휴대폰·브라우저에서 직접 돌리는 오픈소스 저장소다. 핵심은 세 가지 — ① 모델이 아주 작다(약 99M 파라미터), ② 클라우드가 필요 없다(CPU만으로 실시간), ③ 31개 언어를 하나의 모델로 말한다. 저장소가 내건 한 줄은 이것 — "Lightning-Fast, On-Device, Multilingual TTS — running natively via ONNX."(번개처럼 빠른, 온디바이스, 다국어 TTS — ONNX로 네이티브 실행).

가장 먼저 풀어야 할 오해 — supertonic은 서버에 요청을 보내는 API가 아니다. ElevenLabs·OpenAI TTS·Gemini TTS처럼 "인터넷 너머 GPU 서버가 대신 만들어 주는" 방식이 아니라, 모델 파일 몇 개를 내 기기에 두고 그 자리에서 직접 계산한다. 그래서 비행기 모드의 전자책 단말기(Onyx Boox)에서도, 라즈베리파이에서도 소리가 난다. 이렇게 서버 없이 기기 안에서 AI를 돌리는 걸 온디바이스(on-device) 추론이라 한다.

핵심 용어 · 이게 뭐냐
TTS(Text-to-Speech, 음성 합성) — 글자를 소리 파형으로
TTS는 "안녕하세요"라는 텍스트를 받아 실제로 들리는 오디오 파형(WAV)을 만드는 기술이다. 옛날 방식은 (1) 글자를 발음기호로 바꾸고 → (2) 음향 특징(멜 스펙트로그램)을 예측하고 → (3) 보코더로 파형을 만드는 여러 단계였다. supertonic은 이 골격을 현대적으로 다시 짰다 — 발음기호 변환(G2P) 단계를 아예 없애고, 대신 유니코드 글자를 그대로 숫자로 바꿔 넣는다(뒤에서 상술). 덕분에 언어를 늘리기가 쉽다.
핵심 용어 · supertonic의 실행 토대
ONNX · ONNX Runtime — "언어 안 가리는 AI 실행 포맷 + 실행기"
ONNX(Open Neural Network Exchange)는 학습된 신경망을 프레임워크·언어에 독립적으로 저장하는 표준 파일 포맷이다(.onnx). ONNX Runtime은 그 파일을 Python이든 Swift든 Rust든 브라우저든 똑같이 로드해 실행해 주는 엔진이다. supertonic이 "11개 언어에서 동일하게 동작"하는 비결이 바로 이것 — 모델은 .onnx 4개로 고정하고, 언어별로는 그 파일을 로드해 입력·출력 텐서를 맞춰 주는 얇은 코드만 다시 쓴다.
한 문장 비유

"세계 어느 나라 악보든 읽어 연주하는, 주머니에 들어가는 작은 오르골"

클라우드 TTS가 멀리 있는 거대한 콘서트홀에 전화로 곡을 신청하는 것이라면(연결이 끊기면 아무 소리도 못 듣는다), supertonic은 내 주머니 속 작은 오르골이다. 인터넷이 없어도, 전기(GPU)를 많이 안 써도, 태엽만 감으면(CPU만으로) 그 자리에서 소리를 낸다.

게다가 이 오르골은 특별하다 — 발음기호라는 "번역 악보"를 거치지 않고, 세계 어느 나라 글자든 유니코드 숫자 그대로 받아 연주한다. 그래서 한국어·영어·독일어·터키어… 31개 언어를, 그리고 "언어를 특정하지 않는" 모드(na)까지 하나의 작은 통 안에서 소화한다.

2왜 지금 주목받는가

OSSInsight 트렌딩 — "작고, 오프라인이고, 숫자·기호까지 제대로 읽는" 오픈 TTS의 등장

supertonic이 8개월 만에 별 1.3만+를 모으며 트렌딩에 오른 이유는 "또 하나의 TTS"여서가 아니다. 상용 클라우드 TTS의 벽(비용·프라이버시·오프라인 불가)과, 기존 오픈 TTS의 약점(영어 편중·기호 오독)을 동시에 겨냥했기 때문이다. 핵심 셀링 포인트는 "작은 모델로 온디바이스", "발음기 없이 다국어", 그리고 의외로 "숫자·통화·전화번호를 정확히 읽는 텍스트 정규화"다.

포인트내용
정체온디바이스 멀티링구얼 TTS. Supertonic 3 모델(≈99M)을 ONNX Runtime으로 구동, 텍스트를 44.1kHz 16-bit WAV로. 11개 언어 바인딩(Py·Node·Web·Java·C++·C#·Go·Swift·iOS·Rust·Flutter) 예제 완비.
차별점 ①모델이 작다(≈99M). 0.7B~2B급 오픈 TTS의 일부 크기(참고: Kokoro ~82M과 동급). 다운로드·콜드스타트·메모리에서 유리 → 엣지·모바일 친화.
차별점 ②발음기(G2P) 없음. espeak-ng 같은 발음기호 변환을 안 쓰고 유니코드 글자를 직접 넣는다 → 언어 확장이 쉬워 31개 언어 + 언어무관 na 모드.
차별점 ③텍스트 정규화가 강하다. $5.2M, (212) 555-0142, 2.3h, 30kph 같은 통화·전화번호·기술단위를 별도 전처리 없이 정확히 발음(README 비교표에서 ElevenLabs/OpenAI/Gemini가 ❌인 케이스).
제작자 · 라이선스Supertone Inc.(한국 음성 AI 기업, supertone.ai). 코드 MIT · 모델 OpenRAIL-M — 라이선스가 이원화돼 있으니 상업적 사용 시 주의(뒤에서 상술).

주목 포인트 1 — "작은 모델 + CPU"로 상용급 품질을 노린다

supertonic의 서사는 "큰 모델을 클라우드에서 돌려야 좋은 음성이 나온다"는 통념에 대한 반례다. README는 저사양 기기 사례를 전면에 내세운다 — 라즈베리파이 실시간, Onyx Boox 전자책 단말기(비행기 모드)에서 평균 RTF 0.3배. 정확도 벤치마크(Minimax-MLS-test, WER/CER)에서도 VoxCPM2·OmniVoice·Qwen3-TTS 같은 대형 모델과 경쟁 범위 안에 든다(예: 영어 WER 2.06, 독일어 0.86, 한국어 CER 3.26).

핵심 용어 · 속도의 단위
RTF(Real-Time Factor, 실시간 계수) — 낮을수록 빠르다
RTF(오디오를 만드는 데 걸린 시간) ÷ (만들어진 오디오의 길이)다. 10초 분량 음성을 만드는 데 3초가 걸렸다면 RTF = 0.3. RTF가 1보다 작으면 "실시간보다 빠르다"(재생 속도를 못 따라잡을 걱정이 없다)는 뜻이다. supertonic이 전자책 단말기에서 RTF 0.3을 냈다는 건, 저사양 CPU에서도 말하는 속도의 3배 여유로 음성을 뽑는다는 의미다.

주목 포인트 2 — "발음기 없는 다국어"라는 설계 결정

대부분의 오픈 TTS(Piper 등)는 espeak-ng 같은 G2P(자소→음소) 엔진으로 글자를 발음기호로 바꾼 뒤 모델에 넣는다. 이 방식은 발음이 정밀하지만, 언어를 늘리려면 그 언어의 발음 규칙 사전을 새로 붙여야 한다. supertonic은 이 단계를 통째로 버리고 유니코드 글자를 그대로 숫자(코드포인트)로 바꿔 모델에 넣는다. 발음의 부담을 모델이 데이터로 학습해 떠안는 대신, 언어 확장은 극도로 쉬워졌다 — 그래서 31개 언어, 나아가 언어를 지정하지 않는 na 모드까지 가능하다.

주목 포인트 3 — "하나의 모델, 11개 런타임"의 실전 이식성

supertonic이 학습 표본으로 훌륭한 진짜 이유는 동일한 4개 ONNX 모델을 11개 언어에서 로드해 돌리는 완성된 예제가 한 저장소에 모여 있기 때문이다. Python 원본(py/helper.py)을 기준으로, 같은 파이프라인(텍스트 전처리 → 유니코드 토크나이즈 → 4개 세션 실행 → 플로우매칭 루프 → WAV 저장)을 Swift·Rust·Go·Java·C++·C#·브라우저까지 그대로 재현했다. "같은 신경망을 여러 플랫폼에 이식하는 법"을 언어별로 비교하며 배울 수 있는 드문 자료다.

균형 잡힌 시각
과대평가 금물 — "오픈 가중치 = 상업적 무제한"이 아니고, 음성 클로닝도 빠져 있다

냉정히 보자. ① 모델 라이선스는 코드와 다르다. 코드는 관대한 MIT지만 모델 가중치는 OpenRAIL-M(용도 제한 조항이 있는 Responsible-AI 라이선스)이다. "전부 MIT"로 오해하면 안 된다. ② 공개 가중치는 고정 화자(fixed-voice) 전용이고, 임의 목소리 복제(zero-shot voice cloning)나 다양한 상업용 프리셋은 유료 Supertone Play/API로 안내된다. ③ 일부 언어는 약하다(예: 베트남어·일본어 CER이 상대적으로 높음). ④ 벤치마크 수치는 제작사 자체 측정이니 참고로만. 즉 "만능 무료 음성 생성기"가 아니라 "작고 이식성 좋은, 잘 만든 온디바이스 TTS 엔진(고정 화자)"로 보는 게 정확하다.

3기술 스택 전체 지도

핵심 = 4개 ONNX 그래프로 나눈 TTS 파이프라인 · 실행 = ONNX Runtime · 표면 = 11개 언어 바인딩

supertonic의 스택은 두 층으로 나눠 봐야 한다. ① 모델 층 — 학습된 신경망이 4개의 .onnx 파일로 쪼개져 있고, 언어 불문 이 파일들이 "진짜 두뇌"다. ② 바인딩 층 — 각 언어(Python·Swift·Rust…)가 그 파일들을 로드해 입출력을 맞춰 주는 얇은 코드다. Python 원본 py/helper.py가 기준 구현이고, 나머지 10개는 이걸 포팅한 것이다(전부 스텁 아닌 완전 구현, 합쳐 약 1만 줄).

① 모델 층 — TTS를 4개 그래프로 분해

supertonic은 "발음기호 → 멜 스펙트로그램 → 보코더"라는 전통 구조가 아니라, 잠재 공간에서 플로우매칭(flow-matching)으로 음성을 그려 내는 구조다(SupertonicTTS 논문). 실행 시 로드되는 파일은 다음과 같다.

파일역할 · 입력 → 출력
duration_predictor.onnx발화 총 길이(초)를 예측. (text_ids, style_dp, text_mask) → dur. dur/speed로 말 속도 조절
text_encoder.onnx텍스트를 임베딩으로. (text_ids, style_ttl, text_mask) → text_emb
vector_estimator.onnx플로우매칭 속도장(velocity field) 추정기. ODE 적분을 위해 total_step반복 호출되는 핵심
vocoder.onnx잠재 표현(latent) → 파형(wav). 44.1kHz. ISTFT가 그래프 내부에 포함돼 호스트 쪽 FFT가 불필요
보조 자산tts.json(설정: sample_rate=44100 등) · unicode_indexer.json(글자→토큰 매핑) · voice_styles/*.json(화자 임베딩, M1–M5·F1–F5 10종)
핵심 용어 · 왜 반복 호출인가
Flow Matching · NFE(=total_step) — "노이즈에서 음성으로 여러 걸음에 걸쳐 이동"
디퓨전 계열 생성모델처럼, supertonic은 무작위 노이즈에서 출발해 조금씩 "진짜 음성 잠재값" 쪽으로 이동한다. 그 한 걸음의 방향을 알려 주는 게 vector_estimator.onnx(속도장)이고, 몇 걸음을 걸을지가 NFE(Number of Function Evaluations) = total_step이다(기본 8, 범위 5~12). 걸음을 늘리면 품질↑·속도↓, 줄이면 반대. iOS 예제는 이 값을 그대로 nfe 파라미터로 노출한다. "학습 epoch"가 아니라 추론 시 반복 횟수라는 점이 함정이다.

② 바인딩 층 — 같은 모델, 11개 런타임

각 폴더가 하나의 언어/런타임 예제다. 모두 동일한 4개 ONNX를 로드하지만, 의존성·실행 제공자(EP)는 제각각이다.

바인딩런타임 · 버전 · 특기
Python (py/)onnxruntime 1.23.1 · numpy·soundfile·librosa · uv 관리. 기준(원본) 구현
Node.js (nodejs/)onnxruntime-node ^1.19.2 · Node≥16 · ESM
Web (web/)onnxruntime-web ^1.17.0 · WebGPU→WASM 폴백 · Vite ^5. 브라우저 데모
Java (java/)onnxruntime 1.23.1 · Jackson · JTransforms · JDK 11 · Maven shade
C++ (cpp/)시스템 ONNX Runtime C++ API · C++17 · OpenMP · -O3 -ffast-math · CMake≥3.15
C# (csharp/)Microsoft.ML.OnnxRuntime 1.20.1 · .NET 9 · System.Text.Json
Go (go/)yalue/onnxruntime_go 1.11.0 · ORT C 라이브러리 필요 · go 1.21
Swift (swift/)onnxruntime-swift-package-manager from 1.16.0 · macOS v13 CLI
iOS (ios/)OnnxRuntimeBindings(pod) · SwiftUI 앱 · XcodeGen(project.yml)
Rust (rust/)ort 2.0.0-rc.7 · ndarray · hound(WAV) · clap · rayon
Flutter (flutter/)flutter_onnxruntime ^1.6.0 · Dart ^3.5.0 · just_audio (레포엔 macOS 러너만)
함정 · 스택을 읽을 때 헷갈리는 것
fft.js·rustfft·JTransforms는 "구버전 잔재" — v3 추론엔 거의 안 쓴다

여러 바인딩에 FFT 라이브러리(Node의 fft.js, Rust의 rustfft, Java의 JTransforms, Go의 go-dsp, Python의 librosa)가 딸려 있어 "STFT/멜 스펙트로그램을 직접 계산하나?"라고 오해하기 쉽다. 하지만 현재(v3) 추론 경로에서는 대부분 미사용이다 — vocoder.onnx가 파형을 직접 뱉고 ISTFT를 그래프 안에서 처리하기 때문이다. 특히 nodejs/README의 "Preprocessor STFT/Mel" 설명은 오래된(stale) 문서다.

4아키텍처 심화 분석

텍스트 → 유니코드 토큰 → (길이·임베딩) → 노이즈에서 플로우매칭 → 보코더 → WAV

supertonic의 핵심 질문은 하나다 — "발음기호도 없이, 어떻게 텍스트가 소리가 되나?" 답은 6단계 파이프라인이다. Python 원본 py/helper.py를 기준으로 흐름을 그리면 이렇다.

┌──────────────────────────────────────────────────────────────┐ │ supertonic 텍스트 → 음성 파이프라인 │ └──────────────────────────────────────────────────────────────┘ 입력: text + lang("ko"/"en"/…/"na") + voice_style(style_ttl, style_dp) │ ▼ [1] 텍스트 전처리 UnicodeProcessor._preprocess_text NFKD 정규화 · 이모지 제거 · 대시/따옴표 치환 · 문장부호 간격 · 끝에 마침표 언어 태그로 감싸기: <ko> ... </ko> │ ▼ [2] 유니코드 토크나이즈 (G2P/발음기 없음!) 글자 → ord(char)(uint16) → unicode_indexer.json → token id ⇒ text_ids[B,T], text_mask[B,1,T] │ ├──────► [3a] duration_predictor.onnx : (text_ids, style_dp, text_mask) │ → dur(초); dur /= speed │ └──────► [3b] text_encoder.onnx : (text_ids, style_ttl, text_mask) → text_emb │ ▼ [4] sample_noisy_latent(dur) → xt ~ N(0, I), latent_mask │ ▼ [5] 플로우매칭 ODE 루프 (total_step = NFE 회, 기본 8) for step in range(total_step): xt = vector_estimator.onnx(noisy_latent=xt, text_emb, style_ttl, text_mask, latent_mask, current_step, total_step) │ ▼ [6] vocoder.onnx : latent(xt) → wav_tts (44.1kHz 파형, ISTFT 내장) │ ▼ 출력: 44.1kHz 16-bit PCM WAV (+ 샘플별 duration) [장문] chunk_text()로 분할(기본 300자, ko/ja 120자) → 청크별 합성 → 0.3초 무음 삽입 후 이어붙임

핵심 설계 ① — 발음기 대신 "유니코드 코드포인트" 토크나이제이션

가장 특징적인 부분이다. 보통 TTS는 "cat"을 /kæt/ 같은 발음기호로 바꿔 넣지만, supertonic은 글자 하나하나를 유니코드 번호(ord(char), 16비트)로 바꾼 뒤 unicode_indexer.json으로 토큰 id에 매핑한다. 발음 규칙 사전이 없으니 새 언어를 붙이는 비용이 거의 없다 — 그 언어의 글자 코드포인트만 인덱서에 있으면 된다. 언어는 <ko>...</ko>처럼 태그로 감싸 알려 주고, 특정 언어를 지정하기 어려우면 na(language-agnostic) 모드를 쓴다.

비유 · G2P를 없앤다는 것

발음기(G2P)를 쓰는 TTS는 "모든 나라 글자를 한 번 국제음성기호(IPA)로 번역한 뒤 읽는 성우"다. 정확하지만, 새 언어를 맡기려면 그 언어의 번역 규칙을 성우에게 통째로 가르쳐야 한다. supertonic은 다른 성우다 — 글자 모양(코드포인트)을 그대로 보고 소리를 떠올리도록 방대한 데이터로 훈련된 성우다. 번역 사전이 필요 없으니, 새 언어의 글자만 보여 주면 바로 흉내 낸다. 대신 발음 정밀도는 "얼마나 잘 배웠나(데이터·모델)"에 달려 있다.

핵심 설계 ② — 화자를 두 경로에 나눠 주입(style_dp / style_ttl)

목소리 정체성(화자)은 voice_styles/M1.json 같은 파일에 두 개의 임베딩으로 들어 있다 — style_dp(duration predictor용)와 style_ttl(text-to-latent용). 즉 "얼마나 빠르게/길게 말하나"와 "어떤 음색으로 말하나"를 서로 다른 경로에 각각 주입한다. 프리셋은 남성 5·여성 5(M1–M5, F1–F5) 총 10종이다. 임의의 새 목소리를 만드는 voice cloning은 이 오픈 레포에 없고, 외부 Voice Builder나 유료 API를 거쳐 이 JSON을 얻는 구조다.

핵심 설계 ③ — 플로우매칭 ODE 루프: 품질/속도의 손잡이

4단계에서 무작위 노이즈 xt를 만든 뒤, 5단계에서 vector_estimator.onnxtotal_step번 반복 호출해 노이즈를 점점 "진짜 음성 잠재값"으로 밀어 간다. 이게 ODE(상미분방정식) 적분이다 — 매 스텝 속도장을 구해 한 걸음 이동한다. 이 반복 횟수(NFE)가 유일한 품질/속도 손잡이다. 논문이 쓰는 기법들 — LARoPE(Length-Aware RoPE, 텍스트-음성 정렬), Self-Purifying Flow Matching(노이즈 라벨에도 견고한 학습), RobustSpeechFlow — 이 루프의 안정성·정렬을 담당한다.

# py/helper.py — 플로우매칭 추론 루프(요지)
xt, latent_mask = sample_noisy_latent(dur)     # 노이즈에서 출발
for step in range(total_step):                 # NFE 회 반복(기본 8)
    xt = vector_estimator.run(
        noisy_latent=xt, text_emb=text_emb, style=style_ttl,
        text_mask=text_mask, latent_mask=latent_mask,
        current_step=step, total_step=total_step,
    )
wav = vocoder.run(latent=xt)                    # 잠재값 → 파형(ISTFT 내장)

핵심 설계 ④ — 보코더가 파형을 "직접" 뱉는다(ISTFT 내장)

많은 TTS는 모델이 스펙트로그램(주파수 그림)을 내놓고, 호스트 코드가 역-STFT(ISTFT)로 파형을 복원한다. supertonic의 vocoder.onnxISTFT를 그래프 안에 넣어 wav_tts(파형)를 바로 출력한다. 덕분에 각 언어 바인딩은 별도 FFT 라이브러리 없이도 오디오를 얻는다(위 "함정"에서 본 fft.js 등이 실은 잉여인 이유). 이런 "전처리·후처리를 모델 그래프 안으로 흡수"하는 설계는 이식성을 극대화하는 현대적 패턴이다.

핵심 설계 ⑤ — 장문은 청킹 + 무음 이어붙이기

긴 텍스트는 한 번에 합성하지 않는다. chunk_text()기본 300자(한국어·일본어는 120자) 단위로 잘라 청크별로 합성한 뒤 0.3초 무음을 사이에 넣어 이어 붙인다. 언어별 청크 길이가 다른 건 문자당 정보 밀도(CJK가 높음) 때문이다. 배치 모드(--batch)를 켜면 자동 청킹이 꺼지므로, 입력 개수와 출력 개수가 어긋나지 않게 주의해야 한다.

5디렉토리 구조 해부

추적 파일 115개 · py/가 기준 구현 · 나머지 10개 폴더는 언어별 포팅 · 모델은 별도 다운로드

저장소는 의외로 단출하다(파일 115개). 뼈대는 "언어별 폴더 11개 + 공용 문서·테스트"다. 각 언어 폴더는 거의 같은 골격 — helper.*(파이프라인 본체) + example_onnx.*(실행 예제) + 매니페스트다. Python py/helper.py를 읽고 다른 언어를 대조하면 "같은 로직을 이 언어에선 이렇게 쓰는구나"가 한눈에 들어온다.

supertonic/ ├── README.md ← 27KB, 벤치마크·언어·라이선스·논문 인용 ├── LICENSE ← MIT (코드에 한함) ├── test_all.sh ← 전 언어 통합 테스트 러너(web 제외) ├── img/ ← 히어로 이미지 + metrics/*.png(벤치마크 그래프) ├── py/ helper.py(429) example_onnx.py example_pypi.py pyproject.toml │ └ ★ 기준(원본) 구현. 여기부터 읽는다 ├── nodejs/ helper.js(559) example_onnx.js package.json ├── web/ helper.js main.js(WebGPU) index.html vite.config.js ← 브라우저 데모 ├── java/ Helper.java(954) ExampleONNX.java pom.xml ├── cpp/ helper.cpp(1186) helper.h example_onnx.cpp CMakeLists.txt ├── csharp/ Helper.cs(861) ExampleONNX.cs Supertonic.csproj ├── go/ helper.go(1077) example_onnx.go go.mod ├── swift/ Sources/Helper.swift(835) ExampleONNX.swift Package.swift ← macOS CLI ├── ios/ ExampleiOSApp/*.swift (App/ContentView/TTSService/…) project.yml ├── rust/ src/helper.rs(838) src/example_onnx.rs Cargo.toml ├── flutter/ lib/helper.dart(695) lib/main.dart pubspec.yaml macos/ └── (각 언어)/assets → ../assets ← 심볼릭 링크(모델 clone 전엔 broken) assets/ (gitignore — 저장소에 없음, HuggingFace에서 별도 다운로드) ├── onnx/ duration_predictor.onnx text_encoder.onnx │ vector_estimator.onnx vocoder.onnx ├── tts.json ← 설정(sample_rate=44100 등) ├── unicode_indexer.json ← 글자(코드포인트) → 토큰 id └── voice_styles/ M1..M5.json F1..F5.json ← 화자 임베딩 10종

읽는 순서는 이렇다. ① README.md(벤치마크·언어·라이선스 지도) → ② py/helper.py(전처리·토크나이즈·4개 세션·플로우매칭 루프의 원본) → ③ py/example_onnx.py(CLI 진입점, 인자 파싱) → ④ 관심 언어의 helper.*를 Python과 대조(예: rust/src/helper.rs, swift/Sources/Helper.swift) → ⑤ web/main.js(브라우저 WebGPU 폴백) 또는 ios/ExampleiOSApp(모바일 통합). 한 언어만 깊게 읽고, 나머지는 "차이점"만 훑는 것이 효율적이다.

함정 · 클론 직후 "왜 안 도나"
모델(.onnx)은 저장소에 없다 — HuggingFace에서 별도로 받아야 한다

.gitignoreassets/·*.onnx를 제외하므로, git clone만 하면 모델이 없어 각 assets 심볼릭 링크가 깨진 상태다. HuggingFace에서 Git LFS로 모델을 받아 assets/로 넣어야 한다(git clone https://huggingface.co/Supertone/supertonic-3 assets). 참고로 pip용 SDK(supertonic-py)는 첫 실행 시 자동 다운로드하지만, 그건 이 저장소의 py/다른 별도 레포다(뒤 함정 참고).

6학습 포인트

이 저장소 하나에 밀집한 "온디바이스 ML + TTS 아키텍처 + 크로스플랫폼 이식" — 기술별로 무엇을 배울 수 있나

supertonic이 학습 표본으로 훌륭한 이유는 ONNX Runtime 크로스플랫폼 추론, 플로우매칭 TTS 구조, 발음기 없는 토크나이제이션, 온디바이스 최적화, 그리고 "같은 모델의 11개 언어 이식"이 한 저장소에 모여 있기 때문이다. 관심사별로 배울 것을 짚어 보자.

① ONNX Runtime으로 "한 모델, 여러 플랫폼" 돌리기

이 저장소의 최대 교육 가치다. 동일한 4개 .onnx를 Python·Node·브라우저·Java·C++·C#·Go·Swift·iOS·Rust·Flutter에서 로드해 입출력 텐서 이름 계약(text_ids·style_*·…·wav_tts)이 언어 불문 동일하다는 걸 눈으로 확인할 수 있다. "학습은 PyTorch, 배포는 ONNX"라는 실무 패턴, 그리고 실행 제공자(EP: CPU/WebGPU/WASM) 추상화를 배운다.

② 플로우매칭 TTS 아키텍처

멜 스펙트로그램+보코더의 전통을 벗어나, 잠재 공간에서 속도장을 반복 적분(ODE)해 음성을 생성하는 최신 구조를 코드로 본다. 디퓨전/CNF(연속 정규화 흐름)의 감을 잡고, "스텝 수(NFE)와 품질의 트레이드오프"를 실측할 수 있다. 학술 논문(SupertonicTTS 등)과 실제 추론 코드를 함께 대조하기 좋은 자료다.

③ 발음기(G2P) 없는 다국어 토크나이제이션

helper.py의 유니코드 코드포인트 방식은 "발음 정밀도 vs 언어 확장성"이라는 설계 트레이드오프를 생생히 보여 준다. espeak 기반(Piper)과 비교하며 "왜 어떤 프로젝트는 발음기를 쓰고 어떤 건 안 쓰는가"를 이해하게 된다.

④ 온디바이스 최적화 기법

작은 모델(99M) 설계, C++의 -O3 -ffast-math+OpenMP, 그래프 슬리밍(OnnxSlim), ISTFT를 그래프에 흡수해 후처리를 없앤 것까지 — "저사양 기기에서 실시간을 뽑기 위한" 실전 최적화가 곳곳에 있다. RTF를 직접 측정해 보며 최적화 효과를 체감할 수 있다.

⑤ 모바일·브라우저 통합의 실제

ios/는 SwiftUI 앱에서 번들 리소스로 .onnx를 로드하고 NFE를 nfe 파라미터로 노출하는 통합 예시, web/main.jsonnxruntime-web의 WebGPU→WASM 폴백 전략과 대용량 모델 서빙(Vite)을 보여 준다. "AI를 앱·웹에 실제로 넣는 법"의 축소판이다.

실습 아이디어 · 작게 시작하기
지금 당장 손에 익힐 3가지
① HuggingFace에서 모델을 받아 cd py && uv run example_onnx.py로 첫 WAV를 만들어 본다. ② --lang·--voice-style을 바꿔 한국어/영어, 남/여 화자를 비교한다. ③ --total-step을 5·8·12로 바꿔 "스텝 수 ↔ 품질 ↔ 생성 시간" 관계를 귀와 시계로 확인한다. 이 세 가지만 해 봐도 "이 엔진이 안에서 뭘 하는지" 손에 잡힌다.

7하드웨어 · 시스템 요구사항

GPU 불필요 · CPU만으로 실시간 · 모델 ≈99M · 라즈베리파이·전자책까지

supertonic은 특별한 가속기가 필요 없다. 모든 예제가 기본적으로 CPU 실행 제공자(CPUExecutionProvider)로 돈다. 오히려 "저사양에서 얼마나 잘 도는가"가 셀링 포인트다. 정리하면 다음과 같다.

항목요구 / 설명
가속기GPU 불필요 — 전 예제 기본 CPU. Python --use-gpu는 현재 미구현(예외 발생), 브라우저만 WebGPU 가속
검증된 기기데스크탑 · 모바일 · 브라우저 · 라즈베리파이(실시간) · Onyx Boox 전자책(비행기 모드, RTF 0.3배)
모델 크기99M 파라미터(4개 ONNX 합계). 개별 파일 크기는 HuggingFace에서 확인(저장소 미포함)
OSmacOS · Linux · Windows(Py·Node·Java·C++·C#·Go·Rust) · iOS 네이티브 · macOS(Swift CLI·Flutter) · 브라우저
실행 제공자(EP)CPUExecutionProvider(기본) · WebGPU/WASM(web). iOS의 CoreML EP는 예제에 미배선(기본 CPU)
출력44.1kHz 16-bit PCM WAV (+ 샘플별 duration 정보)
모델 취득HuggingFace Supertone/supertonic-3를 Git LFS로 assets/에 clone(코드와 별도)
정리 · 준비물의 정확한 경계
"클라우드·GPU·API 키 0개" — 대신 모델 다운로드와 언어별 툴체인은 필요

서버·GPU·API 키가 전혀 필요 없다는 건 사실이다. 다만 실제로 돌리려면 ① 모델(.onnx)을 HuggingFace에서 받아 assets/에 넣고, ② 쓰려는 언어의 툴체인(Python+uv / Node / .NET 9 / JDK 11 / Rust / Xcode 등)을 갖춰야 한다. 저사양 기기에서도 돌지만, 스텝 수(NFE)를 올리면 그만큼 느려지므로 기기 성능에 맞춰 --total-step을 조절하는 게 핵심이다.

8직접 해볼 수 있는 실습 과제

난이도별 5개 — 첫 WAV 만들기부터 RTF 측정·HTTP 서버 래핑까지
난이도 ★☆☆ · 초급

과제 1 — 첫 음성 만들기

HuggingFace에서 모델을 assets/로 clone(Git LFS)한 뒤, cd py && uv sync && uv run example_onnx.pyresults/*.wav를 만들어 재생한다. "텍스트가 실제 파형이 되어 나오는" 전 과정을 눈과 귀로 확인한다. 목표: 온디바이스 TTS 추론의 최소 왕복을 체감.

난이도 ★☆☆ · 초급

과제 2 — 언어·화자 바꿔 보기

--lang ko·--text "한국어 문장"·--voice-style F1.json으로 언어와 화자를 교체하고, 언어를 지정하지 않는 lang="na" 모드와 비교한다. 남/여 프리셋 10종(M1–M5·F1–F5)의 음색 차이를 들어 본다. 목표: "발음기 없는 다국어"와 화자 임베딩의 효과를 체험.

난이도 ★★☆ · 중급

과제 3 — NFE-품질-지연 곡선 그리기

--total-step을 5·8·12로 바꿔 가며 같은 문장의 음질과 생성 시간을 비교한다. --speed도 0.9~1.5로 바꿔 duration predictor의 효과를 관찰한다. 목표: 플로우매칭의 "스텝 수 ↔ 품질 ↔ 속도" 트레이드오프를 정량적으로 이해.

난이도 ★★☆ · 중급

과제 4 — RTF 측정 CLI 만들기

생성 시간 ÷ 오디오 길이로 RTF를 계산해 출력하는 작은 래퍼를 짠다(helper.py의 타이머 활용). 청크 모드·배치 모드, 짧은 문장 vs 장문에서 처리량이 어떻게 달라지는지 표로 정리한다. 목표: 온디바이스 성능을 스스로 벤치마크하는 습관.

난이도 ★★★ · 고급

과제 5 — HTTP 서버로 래핑(또는 다른 언어로 포팅)

Python TextToSpeechFastAPI로 감싸 OpenAI 호환 /v1/audio/speech 엔드포인트를 만들어 본다(공식 supertonic serve 재현). 여유가 되면 rust/go/ 예제를 참고해 단일 바이너리 데몬으로 포팅한다. 목표: "온디바이스 엔진을 서비스로 만드는" 실전 통합.

9관련 기술 심화 학습 로드맵

4주 코스 — 신경망 배포(ONNX) → TTS 파이프라인 → 온디바이스 최적화 → 크로스플랫폼 이식·서비스화
주차주제 · 학습 목표
1주차
신경망 배포 · ONNX
학습과 배포의 분리. PyTorch 모델을 .onnx로 내보내고 ONNX Runtime으로 로드·실행하는 법, 입출력 텐서 이름 계약, 실행 제공자(EP) 개념. 작은 분류 모델을 직접 export해 Python·브라우저에서 같은 결과를 내 본다.
2주차
TTS 파이프라인
텍스트가 소리가 되기까지. 텍스트 정규화, 토크나이제이션(G2P vs 유니코드 방식), 어쿠스틱 모델·보코더, 그리고 flow-matching/디퓨전 생성. supertonic py/helper.py를 줄 단위로 읽고 Piper(espeak)와 구조를 비교.
3주차
온디바이스 최적화
저사양에서 실시간 뽑기. 양자화(quantization)·그래프 슬리밍, EP별 성능(CPU/WASM/WebGPU/CoreML), RTF 측정, C++ 컴파일 최적화·OpenMP. NFE·청킹으로 품질/지연을 조절하는 실험 설계.
4주차
크로스플랫폼 · 서비스화
여러 플랫폼에 얹기. 같은 모델을 Swift/iOS·Flutter·브라우저에 이식, 스트리밍·큐잉, HTTP/OpenAI 호환 서버로 노출. supertonic의 11개 바인딩을 "이식 패턴 카탈로그"로 삼아 자신의 모델을 배포해 본다.

10핵심 키워드 사전

이 문서에서 반드시 챙길 용어 14개
용어 01
TTS(Text-to-Speech)
텍스트를 사람 목소리 파형으로 바꾸는 음성 합성. supertonic은 이걸 온디바이스로, 발음기 없이, 31개 언어로 수행한다.
용어 02
온디바이스(On-Device) 추론
클라우드 서버가 아니라 내 기기(CPU) 안에서 AI를 실행하는 것. 오프라인·프라이버시·저비용이 장점. supertonic의 정체성.
용어 03
ONNX · ONNX Runtime
신경망을 프레임워크·언어 독립적으로 저장하는 포맷(.onnx)과, 이를 어느 언어/플랫폼에서든 실행하는 엔진. supertonic이 11개 언어에서 동일하게 도는 비결.
용어 04
실행 제공자(Execution Provider, EP)
ONNX Runtime이 실제 계산을 위임하는 백엔드. CPU·WebGPU·WASM·CoreML 등. supertonic 예제는 기본 CPU, 브라우저만 WebGPU.
용어 05
Flow Matching · NFE(total_step)
노이즈에서 출발해 여러 걸음에 걸쳐 목표(음성 잠재값)로 이동하는 생성 방식. 걸음 수가 NFE(=total_step, 기본 8). 늘리면 품질↑·속도↓. "학습 epoch"가 아니라 추론 반복 횟수.
용어 06
잠재 표현(Latent) · 보코더 · ISTFT
모델이 다루는 압축된 중간 표현이 latent. 보코더는 이걸 실제 파형으로 바꾸며, supertonic의 vocoder는 ISTFT(역-STFT)를 그래프에 내장해 파형을 직접 출력한다.
용어 07
Duration Predictor
발화의 총 길이(초)를 예측하는 모델. supertonic에선 별도 ONNX 그래프이며, speed 인자로 말 속도를 조절하는 지점이다.
용어 08
G2P(Grapheme-to-Phoneme) · 발음기
글자를 발음기호로 바꾸는 단계(espeak-ng 등). Piper 같은 TTS는 쓰지만 supertonic은 안 쓴다 — 유니코드 코드포인트를 직접 넣어 언어 확장을 쉽게 만들었다.
용어 09
유니코드 코드포인트 토크나이제이션
글자를 ord(char)(유니코드 번호)로 바꾼 뒤 unicode_indexer.json으로 토큰 id에 매핑. 발음 사전 없이 다국어를 처리하고 na(언어무관) 모드를 가능케 하는 핵심.
용어 10
화자 임베딩(Voice Style)
목소리 정체성을 담은 벡터. supertonic은 style_dp(길이)·style_ttl(음색) 두 개를 voice_styles/*.json에 두고 서로 다른 경로에 주입. 프리셋 10종.
용어 11
RTF(Real-Time Factor)
생성 시간 ÷ 오디오 길이. 1보다 작으면 실시간보다 빠름. supertonic이 전자책 단말기에서 RTF 0.3(3배 여유)을 낸 게 셀링 포인트.
용어 12
WER · CER
합성 음성을 다시 인식(ASR)했을 때의 단어/글자 오류율. 낮을수록 발음이 또렷하다는 뜻. supertonic 벤치마크의 정확도 지표(영어 WER 2.06, 한국어 CER 3.26 등).
용어 13
OpenRAIL-M(모델 라이선스)
용도 제한 조항이 있는 Responsible-AI 라이선스. supertonic의 모델 가중치가 이걸 따른다(코드는 MIT). "오픈 가중치=상업적 무제한"이 아님을 명심할 것.
용어 14
Expression Tags · lang="na"
본문에 <laugh>·<breath>·<sigh> 같은 태그를 넣어 뉘앙스를 주는 기능(v3 신규, 10종). lang="na"는 특정 언어를 지정하지 않는 언어무관 모드.

11참고 링크

원본을 직접 열어 확인하는 습관 — 특히 버전(v2/v3)·모델 라이선스는 원본 기준

경쟁 · 유사 도구 대비 위치

도구supertonic과의 관계
Piper가장 익숙한 오픈 온디바이스 TTS. 단 espeak-ng 발음기(G2P) 기반·영어권 중심 vs supertonic은 발음기 없이 유니코드·31개 언어
Kokoro (~82M)비슷한 소형 온디바이스 모델. supertonic(≈99M)과 크기·지향이 가장 가까운 편
Coqui XTTS · VoxCPM훨씬 큰 모델 + voice cloning 강점. supertonic은 작고 빠르지만 오픈판은 고정 화자
ElevenLabs · OpenAI TTS · Gemini TTS클라우드 API(품질↑, 유료·온라인). supertonic은 반대편의 완전 온디바이스·무료·오프라인

저장소 · 제품
· GitHub: github.com/supertone-inc/supertonic (MIT 코드 · 별 13,242 · 최신 커밋 2026-05-22)
· 모델(HuggingFace, OpenRAIL-M): huggingface.co/Supertone/supertonic-3 · 데모 Space
· pip SDK(별도 레포): supertonic-py (pip install supertonic, 모델 자동 다운로드)
· 제작사·제품: supertone.ai · Play · 오디오 샘플 supertonic3.github.io

핵심 파일(클론 후)
· py/helper.py — 전처리·유니코드 토크나이즈·4개 세션·플로우매칭 루프(기준 구현)
· py/example_onnx.py — CLI 진입점(인자 파싱)
· rust/src/helper.rs · swift/Sources/Helper.swift — 대조용 포팅 예
· web/main.js — 브라우저 WebGPU→WASM 폴백
· ios/ExampleiOSApp/ — SwiftUI 모바일 통합

배경 지식 · 논문
· ONNX Runtime 문서 — 크로스플랫폼 추론
· SupertonicTTS arXiv:2503.23108 · LARoPE 2509.11084 · Self-Purifying FM 2509.19091
· Piper · Kokoro — 비교용 오픈 TTS

확인된 함정 모음 · 재확인 필수
읽기 전에 알아 둘 6가지

라이선스 이원화 — 코드는 MIT지만 모델 가중치는 OpenRAIL-M(용도 제한). 오픈판은 고정 화자 전용이고 voice cloning·다양 프리셋은 유료 Play/API. ② 모델은 저장소에 없다.onnx는 gitignore, HuggingFace에서 Git LFS로 별도 다운로드. ③ 발음기 없음 — 유니코드 코드포인트 방식(espeak 아님). ④ 예제는 GPU 미지원 — 기본 CPU, --use-gpu는 예외 발생, 브라우저만 WebGPU. ⑤ 레포 둘 혼동 — 이 저장소=11개 언어 예제, supertonic-py=pip SDK(자동 다운로드·serve). pip install supertonic은 이 저장소의 py/가 아니다. ⑥ 버전-of-truth — main=Supertonic 3(99M·31언어·태그10), v2(66M·5언어)는 release/supertonic-2 브랜치. 또 total_step=NFE(추론 반복, epoch 아님)이고, vocoder가 파형을 직접 뱉으므로 딸려 온 FFT 라이브러리는 대부분 잉여다.