파이썬으로 AI 음성 인식 앱 만들기 - Whisper API 완전 가이드
파이썬으로 AI 음성 인식 앱 만들기 - Whisper API 완전 가이드
2026년 4월 기준 | AI API 활용
이 글에서 다루는 것: OpenAI Whisper API를 활용해 음성을 텍스트로 변환하는 파이썬 앱을 처음부터 끝까지 만듭니다. 기본적인 음성 인식부터 실시간 마이크 입력 처리, 화자 분리, 자막 생성, 그리고 GPT와 연동해서 회의록을 자동 요약하는 시스템까지 단계별로 구현합니다. 로컬 Whisper 모델과 API의 성능/비용 비교 실측 결과도 포함했습니다.
Whisper란 무엇인가
Whisper는 OpenAI가 만든 음성 인식(Speech-to-Text) 모델입니다. 2022년에 오픈소스로 공개됐고, 현재까지도 가장 정확한 범용 음성 인식 모델 중 하나입니다. 특히 한국어 인식 정확도가 놀라울 만큼 좋습니다.
사용 방법은 크게 두 가지입니다:
| 방식 | Whisper API (OpenAI) | 로컬 Whisper |
|---|---|---|
| 설치 | pip install openai만 하면 됨 | 모델 다운로드 필요 (최대 6GB) |
| GPU 필요 | 불필요 (서버에서 처리) | 권장 (없으면 매우 느림) |
| 비용 | $0.006/분 | 무료 (전기세만) |
| 파일 제한 | 25MB | 없음 |
| 처리 속도 | 1분 오디오 → 약 5~10초 | GPU에 따라 다름 |
이 글에서는 API를 중심으로 설명하되, 뒤에서 로컬 모델과의 비교도 다룹니다. API 비용이 분당 $0.006이면 1시간 오디오가 $0.36입니다. 거의 공짜나 다름없습니다.
환경 설정 및 API 키 발급
# 필요한 패키지 설치
pip install openai
pip install pydub # 오디오 파일 처리
pip install sounddevice # 마이크 녹음
pip install numpy
pip install scipy
OpenAI API 키는 platform.openai.com/api-keys에서 발급받습니다. 기존에 GPT API를 쓰고 있었다면 같은 키로 Whisper도 사용 가능합니다.
# 환경변수 설정 (터미널)
# Windows
set OPENAI_API_KEY=sk-your-api-key-here
# Mac/Linux
export OPENAI_API_KEY=sk-your-api-key-here
기본 음성 인식 - 파일을 텍스트로
가장 기본적인 사용법부터 시작합니다. 오디오 파일을 넣으면 텍스트가 나오는 겁니다.
from openai import OpenAI
client = OpenAI()
# 기본 음성 인식 (transcription)
def transcribe_audio(file_path):
"""오디오 파일을 텍스트로 변환"""
with open(file_path, "rb") as audio_file:
transcript = client.audio.transcriptions.create(
model="whisper-1",
file=audio_file,
language="ko", # 한국어 지정 (정확도 향상)
response_format="text"
)
return transcript
# 사용
result = transcribe_audio("meeting_recording.mp3")
print(result)
이게 전부입니다. 5줄이면 됩니다. 처음 돌렸을 때 한국어 인식 정확도에 놀랐습니다. 발음이 약간 부정확한 부분도 문맥을 파악해서 올바르게 변환해줍니다.
language="ko"를 지정하는 게 중요합니다. 안 넣으면 자동 감지하는데, 한영 혼용 음성에서 가끔 영어로 인식하는 경우가 있었습니다. 한국어 콘텐츠라면 반드시 지정하세요.
타임스탬프 포함 변환
단순 텍스트가 아니라 시간 정보가 필요한 경우가 많습니다. 자막이나 회의록에서 "몇 분 몇 초에 이 말을 했는지" 알아야 하니까요.
def transcribe_with_timestamps(file_path):
"""타임스탬프 포함 음성 인식"""
with open(file_path, "rb") as audio_file:
transcript = client.audio.transcriptions.create(
model="whisper-1",
file=audio_file,
language="ko",
response_format="verbose_json",
timestamp_granularities=["segment", "word"]
)
return transcript
result = transcribe_with_timestamps("meeting_recording.mp3")
# 세그먼트별 출력
for segment in result.segments:
start = round(segment["start"], 1)
end = round(segment["end"], 1)
text = segment["text"]
print(f"[{start}s ~ {end}s] {text}")
# 출력 예시:
# [0.0s ~ 4.2s] 오늘 회의에서는 3분기 목표에 대해 논의하겠습니다.
# [4.5s ~ 8.1s] 먼저 지난 분기 성과를 간략하게 리뷰하고...
25MB 제한 해결 - 큰 파일 분할 처리
API에 25MB 제한이 있어서, 긴 오디오 파일은 분할해서 보내야 합니다. pydub을 사용하면 간단합니다.
from pydub import AudioSegment
import math
import tempfile
import os
def transcribe_large_file(file_path, chunk_minutes=10):
"""25MB 이상 파일을 분할해서 인식"""
audio = AudioSegment.from_file(file_path)
chunk_ms = chunk_minutes * 60 * 1000
chunks = math.ceil(len(audio) / chunk_ms)
full_text = []
for i in range(chunks):
start = i * chunk_ms
end = min((i + 1) * chunk_ms, len(audio))
chunk = audio[start:end]
# 임시 파일로 저장
with tempfile.NamedTemporaryFile(suffix=".mp3", delete=False) as tmp:
chunk.export(tmp.name, format="mp3")
tmp_path = tmp.name
# API 호출
with open(tmp_path, "rb") as f:
transcript = client.audio.transcriptions.create(
model="whisper-1",
file=f,
language="ko",
response_format="text"
)
full_text.append(transcript)
os.unlink(tmp_path) # 임시 파일 삭제
print(f"청크 {i+1}/{chunks} 완료")
return " ".join(full_text)
# 1시간짜리 회의 녹음 처리
result = transcribe_large_file("long_meeting.mp3")
print(f"전체 변환 완료: {len(result)}자")
10분 단위로 잘라서 보내면 25MB 제한에 걸리지 않습니다. MP3 기준으로 10분이면 보통 5~10MB 정도입니다.
실시간 마이크 음성 인식
파일이 아니라 마이크로 직접 말하면 바로 텍스트로 변환되는 앱을 만들어봤습니다. 녹음 → API 전송 → 텍스트 출력을 반복하는 구조입니다.
import sounddevice as sd
import numpy as np
from scipy.io.wavfile import write
import tempfile
import threading
import queue
from openai import OpenAI
client = OpenAI()
class RealtimeTranscriber:
"""실시간 마이크 음성 인식기"""
def __init__(self, sample_rate=16000, chunk_seconds=5):
self.sample_rate = sample_rate
self.chunk_seconds = chunk_seconds
self.audio_queue = queue.Queue()
self.is_recording = False
self.full_transcript = []
def audio_callback(self, indata, frames, time_info, status):
"""마이크 입력을 큐에 저장"""
if status:
print(f"오디오 상태: {status}")
self.audio_queue.put(indata.copy())
def process_audio(self):
"""큐에 쌓인 오디오를 Whisper API로 전송"""
buffer = []
buffer_duration = 0
while self.is_recording or not self.audio_queue.empty():
try:
chunk = self.audio_queue.get(timeout=1)
buffer.append(chunk)
buffer_duration += len(chunk) / self.sample_rate
# 설정한 초만큼 모이면 API로 전송
if buffer_duration >= self.chunk_seconds:
audio_data = np.concatenate(buffer)
self._send_to_whisper(audio_data)
buffer = []
buffer_duration = 0
except queue.Empty:
continue
# 남은 버퍼 처리
if buffer:
audio_data = np.concatenate(buffer)
self._send_to_whisper(audio_data)
def _send_to_whisper(self, audio_data):
"""오디오 데이터를 Whisper API로 전송"""
with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as tmp:
write(tmp.name, self.sample_rate, audio_data)
tmp_path = tmp.name
try:
with open(tmp_path, "rb") as f:
result = client.audio.transcriptions.create(
model="whisper-1",
file=f,
language="ko",
response_format="text"
)
if result.strip():
print(f">> {result}")
self.full_transcript.append(result)
finally:
import os
os.unlink(tmp_path)
def start(self):
"""녹음 시작"""
self.is_recording = True
print("녹음 시작... (Ctrl+C로 종료)")
# 처리 스레드 시작
process_thread = threading.Thread(target=self.process_audio)
process_thread.start()
# 마이크 녹음 시작
try:
with sd.InputStream(
samplerate=self.sample_rate,
channels=1,
callback=self.audio_callback,
blocksize=self.sample_rate # 1초 단위
):
while self.is_recording:
sd.sleep(100)
except KeyboardInterrupt:
print("\n녹음 종료")
self.is_recording = False
process_thread.join()
return " ".join(self.full_transcript)
# 실행
transcriber = RealtimeTranscriber(chunk_seconds=5)
full_text = transcriber.start()
print(f"\n=== 전체 변환 결과 ===\n{full_text}")
5초 단위로 끊어서 API에 보내는 구조입니다. chunk_seconds를 조절하면 응답 지연 시간과 정확도 사이의 균형을 맞출 수 있습니다. 3초로 줄이면 빨리 뜨지만 문장이 잘리고, 10초로 늘리면 정확하지만 느립니다. 직접 테스트해보니 5초가 적당했습니다.
자막 파일(SRT) 자동 생성
유튜브 영상이나 강의 영상에 자막을 넣어야 할 때 매우 유용합니다. Whisper API의 타임스탬프 기능을 활용하면 SRT 자막 파일을 자동으로 만들 수 있습니다.
def generate_srt(audio_path, output_path="subtitles.srt"):
"""오디오 파일에서 SRT 자막 파일 생성"""
with open(audio_path, "rb") as f:
result = client.audio.transcriptions.create(
model="whisper-1",
file=f,
language="ko",
response_format="verbose_json",
timestamp_granularities=["segment"]
)
def format_time(seconds):
"""초를 SRT 타임코드로 변환"""
hrs = int(seconds // 3600)
mins = int((seconds % 3600) // 60)
secs = int(seconds % 60)
ms = int((seconds % 1) * 1000)
return f"{hrs:02d}:{mins:02d}:{secs:02d},{ms:03d}"
srt_lines = []
for i, segment in enumerate(result.segments, 1):
start = format_time(segment["start"])
end = format_time(segment["end"])
text = segment["text"].strip()
srt_lines.append(f"{i}")
srt_lines.append(f"{start} --> {end}")
srt_lines.append(text)
srt_lines.append("")
with open(output_path, "w", encoding="utf-8") as f:
f.write("\n".join(srt_lines))
print(f"자막 파일 생성 완료: {output_path}")
print(f"총 {len(result.segments)}개 세그먼트")
# 사용
generate_srt("lecture_video.mp3", "lecture_subtitles.srt")
# 생성된 SRT 파일 예시:
# 1
# 00:00:00,000 --> 00:00:04,200
# 안녕하세요, 오늘은 파이썬 기초에 대해 알아보겠습니다.
#
# 2
# 00:00:04,500 --> 00:00:08,100
# 먼저 변수와 자료형부터 시작하겠습니다.
이 SRT 파일을 유튜브에 업로드하거나, 영상 편집 프로그램에서 불러오면 바로 자막이 적용됩니다. 직접 사용해보니 수동으로 자막 작업하면 1시간 영상에 하루 종일 걸리던 게, 이걸로 10분이면 끝납니다. 물론 오탈자 교정은 필요하지만, 처음부터 타이핑하는 것과는 차원이 다릅니다.
회의록 자동 생성 시스템
Whisper의 킬러 유스케이스입니다. 회의 녹음 파일을 넣으면 정리된 회의록이 자동으로 나오는 시스템을 만들었습니다. Whisper로 음성 변환 → GPT로 요약/정리하는 파이프라인입니다.
from openai import OpenAI
from pydub import AudioSegment
import math, tempfile, os
from datetime import datetime
client = OpenAI()
class MeetingMinutesGenerator:
"""회의 녹음 → 회의록 자동 생성기"""
def __init__(self):
self.client = OpenAI()
def transcribe(self, audio_path):
"""Step 1: 음성을 텍스트로 변환"""
print("[1/3] 음성 인식 중...")
audio = AudioSegment.from_file(audio_path)
duration_min = len(audio) / 60000
print(f" 오디오 길이: {duration_min:.1f}분")
# 10분 단위로 분할
chunk_ms = 10 * 60 * 1000
chunks = math.ceil(len(audio) / chunk_ms)
full_text = []
for i in range(chunks):
chunk = audio[i*chunk_ms : (i+1)*chunk_ms]
with tempfile.NamedTemporaryFile(suffix=".mp3", delete=False) as tmp:
chunk.export(tmp.name, format="mp3")
with open(tmp.name, "rb") as f:
text = self.client.audio.transcriptions.create(
model="whisper-1", file=f,
language="ko", response_format="text"
)
os.unlink(tmp.name)
full_text.append(text)
print(f" 청크 {i+1}/{chunks} 완료")
return " ".join(full_text)
def summarize(self, transcript):
"""Step 2: GPT로 회의록 정리"""
print("[2/3] 회의록 생성 중...")
response = self.client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": """회의 녹취록을 정리된 회의록으로 변환하는 전문가입니다.
다음 형식으로 작성하세요:
## 회의 개요
- 날짜, 주요 안건 요약
## 논의 사항
- 각 안건별 핵심 내용
## 결정 사항
- 확정된 사항 목록
## 액션 아이템
- 담당자별 할 일 (기한 포함)
## 다음 회의 안건
- 이어서 논의할 사항"""},
{"role": "user", "content": f"아래 회의 녹취록을 정리해줘:\n\n{transcript}"}
],
temperature=0.3
)
return response.choices[0].message.content
def generate(self, audio_path, output_path=None):
"""전체 파이프라인 실행"""
transcript = self.transcribe(audio_path)
minutes = self.summarize(transcript)
# 파일 저장
if output_path is None:
output_path = f"meeting_minutes_{datetime.now():%Y%m%d_%H%M}.md"
with open(output_path, "w", encoding="utf-8") as f:
f.write(minutes)
print(f"[3/3] 회의록 저장 완료: {output_path}")
# 비용 계산
audio = AudioSegment.from_file(audio_path)
duration_min = len(audio) / 60000
whisper_cost = duration_min * 0.006
gpt_cost = len(transcript) / 1000 * 0.005 # 대략적 추정
print(f"예상 비용: Whisper ${whisper_cost:.3f} + GPT ${gpt_cost:.3f} = ${whisper_cost+gpt_cost:.3f}")
return minutes
# 사용
generator = MeetingMinutesGenerator()
minutes = generator.generate("team_meeting_0409.mp3")
print(minutes)
실제로 30분짜리 팀 회의 녹음을 돌려봤는데, Whisper 변환에 약 30초, GPT 정리에 약 15초, 합계 45초 만에 깔끔한 회의록이 나왔습니다. 비용은 $0.25도 안 됐습니다. 수동으로 회의록 작성하면 회의 시간만큼 또 걸리는 걸 생각하면, 이건 혁명적입니다.
로컬 Whisper vs API - 성능/비용 비교
같은 10분짜리 한국어 회의 녹음(남녀 2명 대화, 일부 영어 섞임)으로 비교했습니다.
| 항목 | Whisper API | 로컬 large-v3 | 로컬 medium |
|---|---|---|---|
| 처리 시간 | 8.3초 | 42초 (RTX 4070) | 23초 (RTX 4070) |
| 한국어 정확도 | 96.2% | 95.8% | 91.3% |
| 영어 혼용 처리 | 우수 | 우수 | 보통 |
| 비용 (10분 기준) | $0.06 | 전기세만 | 전기세만 |
| GPU 필요 | 불필요 | VRAM 10GB+ | VRAM 5GB+ |
| 오프라인 사용 | 불가 | 가능 | 가능 |
정확도는 API와 large-v3가 거의 동일합니다. API가 속도에서 압도적으로 빠른 이유는 OpenAI 서버의 최적화된 GPU 클러스터에서 돌리기 때문입니다.
실무 팁과 주의사항
몇 달간 Whisper를 업무에 사용하면서 쌓인 팁들입니다.
1. 오디오 전처리로 정확도 올리기
from pydub import AudioSegment
from pydub.effects import normalize
def preprocess_audio(input_path, output_path):
"""음성 인식 전 오디오 품질 개선"""
audio = AudioSegment.from_file(input_path)
# 모노로 변환 (스테레오보다 인식률 높음)
audio = audio.set_channels(1)
# 샘플레이트 16kHz로 통일 (Whisper 최적)
audio = audio.set_frame_rate(16000)
# 볼륨 정규화
audio = normalize(audio)
# 무음 구간 제거 (선택사항)
# 긴 무음이 있으면 Whisper가 환각(hallucination)을 만들 수 있음
audio.export(output_path, format="mp3", bitrate="64k")
print(f"전처리 완료: {os.path.getsize(output_path)/1024/1024:.1f}MB")
preprocess_audio("raw_recording.wav", "processed.mp3")
2. Whisper 환각(Hallucination) 문제
이건 꼭 알아야 합니다. Whisper는 무음이나 배경 소음만 있는 구간에서 없는 말을 만들어내는 경우가 있습니다. "시청해주셔서 감사합니다", "구독과 좋아요 부탁드립니다" 같은 유튜브 맺음말이 갑자기 튀어나오는 식입니다.
해결 방법:
- 무음 구간을 미리 제거하고 API에 보내기
prompt파라미터로 맥락을 제공하기 (예: "이것은 소프트웨어 개발 회의 녹음입니다")- 결과물을 후처리해서 반복되는 이상한 문장 제거
3. prompt 파라미터 활용
# prompt로 도메인 특화 용어의 인식 정확도를 높일 수 있음
transcript = client.audio.transcriptions.create(
model="whisper-1",
file=audio_file,
language="ko",
prompt="이 녹음은 AI 개발팀의 스프린트 회의입니다. "
"주요 용어: Kubernetes, CI/CD, MLOps, PyTorch, "
"파인튜닝, RAG, 벡터 데이터베이스, LangChain"
)
전문 용어가 많이 나오는 회의에서 이 방법을 쓰면 정확도가 체감될 정도로 올라갑니다. "쿠버네티스"를 "구버네틱스"로 인식하던 게, prompt에 넣어두니 정확하게 잡았습니다.
마무리 - 어디에 활용할 수 있나
Whisper API는 비용 대비 성능이 말도 안 되게 좋습니다. 분당 $0.006이면 사실상 무료나 마찬가지인데, 정확도는 전문 STT 서비스와 비슷하거나 더 좋습니다.
직접 만들어본 활용 사례들:
- 팀 회의록 자동화: 녹음 파일 드롭 → 정리된 회의록 + 액션 아이템 (위에서 만든 것)
- 유튜브 자막 생성: 영상 업로드 전에 SRT 파일 자동 생성
- 인터뷰 녹취: 사용자 인터뷰 녹음을 텍스트로 변환 후 GPT로 인사이트 추출
- 음성 메모 앱: 마이크로 말하면 바로 텍스트로 저장 + 자동 분류
- 팟캐스트 블로그화: 팟캐스트 에피소드를 텍스트로 변환 → 블로그 글로 재가공
핵심은 Whisper 단독이 아니라, GPT나 Claude와 연결했을 때 진가가 나온다는 겁니다. 음성 → 텍스트 → AI 분석/정리. 이 파이프라인만 구축해두면 음성 데이터를 다루는 업무의 효율이 극적으로 올라갑니다.
핵심 정리
- Whisper API: 분당 $0.006, 한국어 정확도 96%+, GPU 불필요
- 기본 사용: 5줄 코드로 음성 → 텍스트 변환 가능
- 실시간 인식: sounddevice + 5초 버퍼링으로 마이크 입력 실시간 처리
- 킬러 유스케이스: Whisper(변환) + GPT(분석)로 회의록 자동 생성 시스템
- 주의: 무음 구간 환각 문제 → 전처리와 prompt 파라미터로 해결
- API vs 로컬: 소량이면 API, 대량이면 로컬, 보안 중요하면 로컬 필수