Whisper 코드 리뷰 — Open AI STT 모델의 내부 구조 해부
OpenAI의 Whisper는 오픈소스로 공개된 음성 인식(STT, Speech-to-Text) 모델입니다. 겉으로는 “그냥 음성을 텍스트로 바꿔주는 모델”처럼 보이지만, 실제로 코드를 들여다보면 Transformer 기반 멀티모달 인퍼런스 엔진에 가깝습니다. 이번 글에서는 Whisper의 코드를 직접 뜯어보며 구조를 해부해보겠습니다.

🎯 1. 전체 구조 개요
Whisper 레포지토리의 핵심은 단 3개의 파일에 있습니다.
- model.py — 모델 정의 (Transformer encoder-decoder)
- audio.py — 오디오 전처리 (FFT, mel spectrogram)
- transcribe.py — 실제 inference 파이프라인
이 단순한 구조 덕분에 Whisper는 PyTorch 모델 중 가장 읽기 쉬운 코드 중 하나입니다.
🎧 2. 오디오 처리 파이프라인 (audio.py)
먼저 오디오를 처리하는 부분을 봅시다.
def load_audio(file: str, sr: int = 16000):
out = subprocess.run(
["ffmpeg", "-i", file, "-f", "s16le", "-ac", "1", "-acodec", "pcm_s16le", "-ar", str(sr), "-"],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
check=True,
)
return np.frombuffer(out.stdout, np.int16).astype(np.float32) / 32768.0
핵심 포인트:
- Whisper는 모든 입력 오디오를 16kHz mono float32로 맞춥니다.
- ffmpeg를 직접 호출해 다양한 포맷을 호환합니다.
- 출력은 [-1, 1] 범위의 float32 numpy array입니다.
다음은 멜 스펙트로그램 변환 부분입니다.
def log_mel_spectrogram(audio):
spec = librosa.feature.melspectrogram(
y=audio, sr=16000, n_fft=400, hop_length=160, n_mels=80
)
return np.log10(np.maximum(spec, 1e-10))
여기서 중요한 건 80채널 Mel spectrogram을 생성한다는 점입니다. 이는 Whisper의 인코더 입력 토큰 역할을 합니다 — 즉, 오디오를 “이미지처럼” 본다는 개념이죠.
🧠 3. 모델 정의 (model.py)
Whisper의 핵심은 Transformer입니다. 코드를 보면 거의 GPT 스타일의 디코더와, BERT 스타일의 인코더가 짝을 이룹니다.
class Whisper(nn.Module):
def __init__(self, dims):
super().__init__()
self.encoder = AudioEncoder(dims)
self.decoder = TextDecoder(dims)
🎙️ 인코더
AudioEncoder는 Mel spectrogram을 입력받아 latent representation을 만듭니다.
class AudioEncoder(nn.Module):
def __init__(self, dims):
super().__init__()
self.conv1 = Conv1d(80, dims.n_audio_state, kernel_size=3, stride=1, padding=1)
self.blocks = nn.ModuleList([ResidualAttentionBlock(...) for _ in range(dims.n_audio_layer)])
이 구조는 Conv → Self-Attention 반복으로, 시간축의 특징을 추출하며 “음성 문맥 벡터”를 만듭니다.
✍️ 디코더
TextDecoder는 GPT와 거의 동일합니다. 차이점은 Cross-Attention으로 오디오 인코딩을 참조한다는 점입니다.
class TextDecoder(nn.Module):
def forward(self, tokens, audio_features):
for block in self.blocks:
x = block(x, cross_kv=audio_features)
return self.ln(x)
즉, Whisper는 “오디오를 보고 문장을 예측하는 GPT”입니다.
⚙️ 4. 추론 파이프라인 (transcribe.py)
전체 파이프라인은 이렇게 단순합니다.
def transcribe(model, audio):
mel = log_mel_spectrogram(audio)
mel = torch.from_numpy(mel).to(model.device)
result = model.decode(mel)
return decode_tokens(result)
단 세 단계입니다:
- 오디오 로드 + Mel 변환
- Transformer 인코딩 + 디코딩
- 토큰을 텍스트로 디코딩
여기에 beam search, temperature, language detection 등의 옵션이 붙으면 Whisper CLI에서 사용하는 --task translate, --temperature 0.2 같은 기능이 됩니다.
🌍 5. 다국어 지원
Whisper STT의 가장 큰 장점 중 하나는 다국어 인식입니다. 모델은 98개 이상의 언어를 지원하며, 자동 언어 감지 기능도 탑재되어 있습니다. 즉, 입력 오디오 언어를 미리 지정하지 않아도 모델이 판단하여 텍스트로 변환합니다.
코드 레벨에서는 language 파라미터와 --task transcribe 옵션이 이를 가능하게 합니다. 모델이 학습한 멀티링구얼 데이터 덕분에, 영어 외에도 스페인어, 중국어, 한국어 등 다양한 언어에서 높은 정확도를 보여줍니다.
⚡ 6. Whisper.cpp 포팅
Whisper 모델은 PyTorch 기반이지만, C++로 포팅된 Whisper.cpp 프로젝트가 있습니다. 주요 장점:
- CPU 환경에서도 빠른 추론 가능
- 모바일 및 임베디드 기기에서도 실행 가능
- PyTorch 설치 없이 사용 가능
실제로 Whisper.cpp는 quantization, 메모리 최적화 등 다양한 기법을 적용해 속도와 효율을 극대화했습니다. Whisper STT를 서버가 아닌 로컬 장치에서 활용하고자 할 때 훌륭한 대안이 됩니다.
💡 7. Whisper의 설계 철학
코드를 읽다 보면 Whisper 팀의 철학이 느껴집니다:
- Simple > Clever — 복잡한 트릭보다 일관된 설계
- 모듈화된 파이프라인 — 오디오 → 멜 → 인코더 → 디코더 → 텍스트
- End-to-End Differentiable — 전처리까지 포함한 end-to-end 설계
Whisper는 “거대한 모델을 단순한 구조로 구현하는 방법”의 모범 사례입니다. 덕분에 모델 크기에 비해 읽기 쉽고 유지보수가 쉬운 코드베이스가 되었죠.
🏁 8. 마무리
Whisper STT의 코드는 “STT의 표준 교과서”라고 할 수 있습니다. Transformer를 이용해 음성을 텍스트로 변환하는 전체 과정이 간결하고 직관적으로 담겨 있기 때문입니다. 다국어 지원과 Whisper.cpp 포팅 덕분에 활용 범위도 넓습니다.
📚 더 깊이 보고 싶다면:
- Beam Search가 Whisper에서 어떻게 구현되어 있는가
- Whisper 모델의 다국어 처리 방식
- Whisper.cpp나 MLX 포팅 버전의 최적화 비교

