Whisper: 음성 → 텍스트
from openai import OpenAI
from pathlib import Path
client = OpenAI()
# 기본 음성 인식
def transcribe(audio_path: str, language: str = "ko") -> str:
with open(audio_path, "rb") as f:
transcript = client.audio.transcriptions.create(
model="whisper-1",
file=f,
language=language, # 없으면 자동 감지
)
return transcript.text
# 타임스탬프 포함
def transcribe_with_timestamps(audio_path: str) -> dict:
with open(audio_path, "rb") as f:
transcript = client.audio.transcriptions.create(
model="whisper-1",
file=f,
response_format="verbose_json",
timestamp_granularities=["word", "segment"],
)
return {
"text": transcript.text,
"segments": [
{
"text": s.text,
"start": s.start,
"end": s.end,
}
for s in transcript.segments
],
}
지원 형식과 제한
# 지원 형식: mp3, mp4, mpeg, mpga, m4a, wav, webm
# 최대 파일 크기: 25MB
# 긴 파일은 분할 필요
from pydub import AudioSegment
def split_audio(audio_path: str, chunk_ms: int = 10 * 60 * 1000) -> list[str]:
"""10분씩 분할"""
audio = AudioSegment.from_file(audio_path)
chunks = []
for i, start in enumerate(range(0, len(audio), chunk_ms)):
chunk = audio[start:start + chunk_ms]
chunk_path = f"/tmp/chunk_{i}.mp3"
chunk.export(chunk_path, format="mp3")
chunks.append(chunk_path)
return chunks
def transcribe_long_audio(audio_path: str) -> str:
chunks = split_audio(audio_path)
texts = []
for chunk in chunks:
texts.append(transcribe(chunk))
return " ".join(texts)
Whisper 실전 패턴: 회의록 생성
def generate_meeting_minutes(audio_path: str) -> str:
# 1. 음성 인식
transcript = transcribe_with_timestamps(audio_path)
# 2. GPT로 회의록 정리
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{
"role": "system",
"content": "회의 내용을 구조화된 회의록으로 정리해주세요."
},
{
"role": "user",
"content": f"""다음 회의 내용을 회의록으로 정리해주세요:
- 참석자 (추정 가능하면)
- 주요 논의사항
- 결정사항
- Action Items (담당자, 기한 포함)
회의 내용:
{transcript['text']}"""
}
],
)
return response.choices[0].message.content
TTS: 텍스트 → 음성
# 기본 TTS
def text_to_speech(text: str, output_path: str, voice: str = "alloy") -> None:
"""
voices: alloy, echo, fable, onyx, nova, shimmer
"""
response = client.audio.speech.create(
model="tts-1", # tts-1 (빠름) or tts-1-hd (고품질)
voice=voice,
input=text,
response_format="mp3", # mp3, opus, aac, flac, wav, pcm
speed=1.0, # 0.25 ~ 4.0
)
response.stream_to_file(output_path)
# 스트리밍 TTS (실시간 재생)
def stream_speech(text: str) -> bytes:
with client.audio.speech.with_streaming_response.create(
model="tts-1",
voice="nova",
input=text,
) as response:
return b"".join(response.iter_bytes())
음성 챗봇 파이프라인
import sounddevice as sd
import soundfile as sf
import numpy as np
def voice_chatbot():
"""음성 입력 → LLM → 음성 출력"""
conversation = []
while True:
# 1. 음성 녹음
print("말씀하세요... (Enter 눌러 중지)")
recording = []
with sd.InputStream(samplerate=16000, channels=1) as stream:
input()
recording, _ = stream.read(stream.read_frames())
audio_path = "/tmp/input.wav"
sf.write(audio_path, np.array(recording), 16000)
# 2. 음성 인식
user_text = transcribe(audio_path)
print(f"사용자: {user_text}")
# 3. LLM 응답
conversation.append({"role": "user", "content": user_text})
response = client.chat.completions.create(
model="gpt-4o",
messages=conversation,
)
assistant_text = response.choices[0].message.content
conversation.append({"role": "assistant", "content": assistant_text})
print(f"AI: {assistant_text}")
# 4. TTS로 응답
text_to_speech(assistant_text, "/tmp/response.mp3", voice="nova")
# 재생 (macOS: afplay, Linux: aplay, Windows: playsound)
import os
os.system("afplay /tmp/response.mp3")
정리
| 기능 | API | 모델 |
|---|---|---|
| 음성 인식 | audio.transcriptions.create | whisper-1 |
| 음성 번역 (→영어) | audio.translations.create | whisper-1 |
| 텍스트 → 음성 | audio.speech.create | tts-1, tts-1-hd |
다음 편에서는 멀티모달 실전 프로젝트 — 이미지 분석 + 음성 처리를 결합한 접근성 앱을 만듭니다.