LLM멀티모달 AI · 4중급

오디오 처리 — Whisper 음성 인식과 TTS

LLMWhisperTTS음성인식음성합성오디오

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.createwhisper-1
음성 번역 (→영어)audio.translations.createwhisper-1
텍스트 → 음성audio.speech.createtts-1, tts-1-hd

다음 편에서는 멀티모달 실전 프로젝트 — 이미지 분석 + 음성 처리를 결합한 접근성 앱을 만듭니다.

궁금한 점이 있으신가요?

협업·의뢰는 아래로, 가벼운 소통은 인스타그램 @bluefox._.hi도 환영이에요.