Tiny Audio: $25로 학습 가능한 음성-텍스트 시스템
요약
Tiny Audio는 적은 데이터와 파라미터만으로도 높은 성능의 음성-텍스트(STT) 시스템을 구현하는 방법을 제시합니다. 고정된 사전 학습 인코더에 작은 학습 가능한 프로젝터를 연결하고 LLM과 결합하여, 8천만 개 파라미터 학습만으로 LibriSpeech에서 1.8% WER을 달성했습니다.
핵심 포인트
- 적은 데이터($25)와 적은 파라미터로 고성능 STT 구현 가능
- 고정된 인코더 + 작은 프로젝터 조합의 효율성 입증
- LibriSpeech test-clean에서 1.8% WER 달성이라는 우수한 성능 제시
Tiny Audio
<div align="center"> <img src="https://raw.githubusercontent.com/alexkroman/tiny-audio/main/public/logo.png" alt="Tiny Audio Logo" /> </div>25달러로 학습할 수 있는 음성-텍스트(speech-to-text) 시스템.
Tiny Audio는 고정된 사전 학습 음성 인코더(frozen, pretrained speech encoder)를 작은 학습 가능한 프로젝터(small trainable projector)와 사전 학습된 대규모 언어 모델(pretrained LLM)에 연결합니다. 이 저장소에서 공개한 모델은 약 8천만 개의 파라미터만 학습했음에도 불구하고 LibriSpeech test-clean에서 1.8%의 WER을, 그리고 12개 벤치마크 전반에 걸쳐 **7.4%**를 달성합니다 (11,822개의 샘플 풀링). 코드베이스는 오후 안에 읽을 수 있을 만큼 작으며, 노트북에서 약 5분 만에 학습 루프(training loop)를 실행할 수 있습니다.
30초 만에 사용해 보기
설치 불필요: **라이브 데모**를 열고, 본인의 목소리를 녹음하거나 파일을 업로드하여 전사(transcript) 결과를 얻으세요.
Python에서 사용하기:
pip install "transformers>=5.0" peft torch torchaudio librosa
from transformers import pipeline
pipe = pipeline(
...
출력 결과는 후처리(post-processing) 단계 없이 구두점(punctuated), 대문자 처리(capitalized), 숫자 형식 지정이 되어 있습니다. 입력은 파일 경로, URL 또는 16 kHz의 numpy 배열일 수 있습니다. 가중치(weights)가 bf16이므로 약 6 GB의 GPU 또는 Apple Silicon 메모리가 필요합니다.
일반 텍스트 그 이상
# 단어별 타임스탬프 (forced alignment)
pipe("audio.wav", return_timestamps=True)
# {"text": "hello world", "words": [{"word": "hello", "start": 0.0, "end": 0.5}, ...]}
...
Nemotron-3-Diarization이 찾아낸 각 화자는 다른 모든 사람이 침묵한 오디오 복사본에서 개별적으로 전사되며, 각 단어는 자신이 온 스트림에 속합니다. 이는 NeMo의 masked_asr 레시피를 포팅(port)한 것으로, 두 스트림 모두가 한 번에 들은 단어는 한 번만 유지됩니다. 각 화자는 ASR에서 대략 자신의 발화 시간만큼 비용이 들며, 단일 화자 오디오는 마스킹되지 않은 상태로 전사됩니다. 중첩된 부분(overlap) 처리는 부분적으로만 이루어지는데, 다른 사람의 말이 특정 화자의 차례에 포함되어 있어도 그 화자의 스트림 안에 남아 있습니다.
화자 분리(Speaker diarization)를 위해서는 다음 릴리즈까지 main에서 transformers가 설치되어야 합니다 (pip install git+https://github.com/huggingface/transformers). 토큰별 스트리밍 출력을 보려면 ASRModel.generate_streaming을 참조하세요. 배치 처리 및 GPU 설정은 모델 카드에서 다룹니다.
RunPod에서 HTTP API로 사용하기
ta serve는 모델을 배치(batched) HTTP 서버 뒤에 배치합니다: 요청들이 함께 도착하면 GPU 배치를 공유하므로, 부하가 증가함에 따라 처리량도 증가합니다 (RTX 4090에서 동시 요청 128개 기준 약 460배). RunPod GPU에서 실행하려면 다음을 사용하세요:
poetry run ta runpod up --serve # 추론(inference) 파드를 생성하고 <POD_ID>를 출력합니다.
poetry run ta runpod wait <POD_ID> # <HOST>와 <PORT>를 출력합니다.
poetry run ta runpod deploy <HOST> <PORT> # 프로젝트를 동기화하고 빠른 커널(fast kernels)을 설치합니다.
...
TINY_AUDIO_API_KEY가 없으면 서버는 URL만 가진 누구에게나 열려 있습니다. ta serve는 또한 로컬에서 CUDA, Apple Silicon 또는 CPU에서 실행됩니다.
요청 본문으로 오디오를 보내고, 쿼리 문자열에 옵션을 포함하세요:
curl -X POST
- **옵션(Options):** 파이프라인에서와 같이 `return_timestamps`, `return_speakers`, `num_speakers` 및 `max_speakers`를 반환할 수 있습니다. 응답은 파이프라인이 반환하는 것과 동일한 딕셔너리입니다.
- **JSON 본문(JSON body):** JSON을 전송하려면 `{"inputs": "<base64 오디오>", "parameters": {...}}`를 사용하십시오.
- **오디오 형식(Audio formats):** FFmpeg가 읽을 수 있는 모든 형식이 가능합니다.
- **오류(Errors):** 잘못된 오디오 또는 옵션의 경우 `400`과 함께 `{"error": ...}`이 반환되며, 잘못된 키는 `401` 오류를 발생시킵니다.
- **긴 요청(Long requests):** `POST /jobs`는 동일한 본문과 옵션을 사용하지만 즉시 `202` 상태 코드와 함께 `{"id": ...}`를 응답합니다. 작업이 진행되는 동안에는 `GET /jobs/<id>`로 폴링(poll)해야 하며, 이 요청은 여전히 `202`를 반환하고 최종 응답은 원래의 `POST /`가 제공했을 내용입니다. 프록시의 100초 제한을 초과할 수 있는 모든 경우(예: `return_speakers`를 사용하는 전체 회의 녹화)에 사용하십시오. `ta eval --endpoint`는 화자 데이터셋의 경우 이 방식을 따릅니다.
- **기타 엔드포인트(Other endpoints):** `GET /health`와 `GET /stats`(배치 크기 및 GPU 시간)가 있습니다.
RunPod의 HTTP 프록시는 500 MiB를 초과하는 요청 본문을 거부하며, 100초 이상 걸리는 모든 요청은 드롭(drop)됩니다. 긴 녹음 파일의 경우, 16 kHz 모노 FLAC 형식을 전송하십시오:
```bash
ffmpeg -i recording.wav -ac 1 -ar 16000 recording.flac
이는 오디오 분당 약 1 MB이며, 서버가 모든 것을 어차피 16 kHz 모노로 변환하기 때문에 정확도에 비용이 들지 않습니다. RTX 4090에서 오디오 45분은 약 10초가 소요되며, 화자 레이블이 추가되면 21초가 걸립니다. demo Space는 이 방식으로 서버를 호출합니다.
성능은 어느 정도인가요?
Word Error Rate (WER) (%, 낮을수록 좋음): 11,822개의 샘플(데이터셋당 최대 1,000개)에 대해 본 리포지토리의 ta eval을 사용하여 RTX 4090에서 ta serve HTTP API와 비교하여 측정한 결과입니다.
| 데이터셋 | WER |
|---|---|
| LibriSpeech test-clean | 1.84 |
| ... | |
| † 제외된 데이터: 이 출처의 데이터는 학습에 사용되지 않았습니다. |
동일한 샘플을 사용하여 상용 API와 비교하고 싶다면 직접 수치를 확인해 볼 수 있습니다.
작동 방식
오디오 (16 kHz) → 음성 인코더 (고정) → MLP 프로젝터 (학습됨) → LLM 디코더 → 텍스트
- 사전 학습된 **음성 인코더(speech encoder)**는 오디오를 프레임 임베딩 시퀀스로 변환합니다.
- 작은 **MLP 프로젝터(MLP projector)**는 이웃한 프레임을 쌓고 이를 LLM의 임베딩 공간으로 매핑합니다. 이 부분만이 처음부터 학습됩니다.
- LLM은 이 투영된 프레임들을 마치 토큰인 것처럼 읽어 전사본을 작성합니다.
인코더, 프로젝터, 디코더는 각각 설정(config)에서 교체할 수 있습니다. 저장소에는 두 가지 레시피가 포함되어 있습니다:
| 레시피 | 인코더 | 디코더 | 학습된 부분 |
|---|---|---|---|
게시된 모델 (granite_qwen_frozen) | Granite Speech 470M | Qwen3.5, 고정 + LoRA | 프로젝터 + LoRA (~80M) |
기본/강좌 레시피 (stage_1) | GLM-ASR-Nano (635M) | Qwen3-0.6B, 미세 조정됨 | 프로젝터 + 디코더 |
자신만의 모델 학습하기
무료로 노트북에서 시작하고, 파이프라인이 작동하는 것을 확인한 후에만 GPU를 임대하세요.
| 등급 | 데이터 | 하드웨어 | 비용 |
|---|---|---|---|
| 스모크 테스트 | 73 LibriSpeech 클립 | 사용자의 노트북 (CPU, MPS, CUDA) | 무료, 약 5분 |
| ... |
모든 설정은 Hydra 오버라이드(override)가 될 수 있습니다. 예를 들어, model.projector_hidden_dim=2048 또는 training.use_lora=true와 같습니다. 모델에 만족하면, ta push를 사용하여 Hugging Face Hub에 게시하고 ta deploy를 통해 위와 같은 데모를 Space에 배포할 수 있습니다.
RunPod에서 학습하기
poetry run ta runpod up -e stage_1 # 설정에 맞는 충분한 GPU로 pod 생성
poetry run ta runpod wait <POD_ID> # <HOST> <PORT> 출력
poetry run ta runpod deploy <HOST> <PORT> # 프로젝트 동기화 및 종속성 설치
...
직접 구축하며 배우기
**무료 3.5시간 과정**에서는 전체 루프를 안내합니다: 인코더(encoder), 프로젝터(projector), 디코더(decoder)가 어떻게 결합되는지 (실제 텐서 형태와 함께), 모델 학습, 상용 API와의 평가, 그리고 라이브 데모로 게시하는 방법입니다. Python, 명령줄 인터페이스(command line), git이 필요합니다. 이 과정은 공개된 모델이 아닌 더 작은 stage_1 레시피를 학습하므로, WER(Word Error Rate)이 위의 표보다 높을 것입니다.
새로운 프로젝터 아키텍처를 시도하거나, 데이터셋을 추가하거나, 코드베이스를 변경하고 싶으신가요? CLI 참조, 설정 레이아웃 및 품질 게이트는 CONTRIBUTING.md를 참고하세요.
감사의 말씀 (Acknowledgments)
- 오디오 인코딩: Granite Speech 및 GLM-ASR
- 언어 모델링: Qwen3.5 및 Qwen3
- 기본 평가 세트: LoquaciousSet
라이선스
MIT
AI 자동 생성 콘텐츠
본 콘텐츠는 개발 자료 GitHub · 0da57016의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기