55 lines
2.1 KiB
Python
55 lines
2.1 KiB
Python
import os
|
|
import tempfile
|
|
import subprocess
|
|
from app.core.exceptions import AudioFileNotFoundError, STTError
|
|
|
|
class AudioParser:
|
|
"""
|
|
모든 형식(m4a, mp3, mp4 등)의 오디오/비디오 파일을
|
|
whisper.cpp가 요구하는 16kHz 16-bit Mono WAV 포맷으로 변환하는 파서 클래스.
|
|
"""
|
|
@staticmethod
|
|
def preprocess_audio(file_path: str, sample_rate: int = 16000) -> str:
|
|
if not os.path.exists(file_path):
|
|
raise AudioFileNotFoundError(file_path)
|
|
|
|
try:
|
|
# 임시 파일로 wav 저장 경로 설정
|
|
temp_dir = tempfile.gettempdir()
|
|
filename = os.path.basename(file_path)
|
|
base_name, _ = os.path.splitext(filename)
|
|
wav_path = os.path.join(temp_dir, f"{base_name}_16kHz.wav")
|
|
|
|
# 파이썬 번들 ffmpeg.exe 사용
|
|
import imageio_ffmpeg
|
|
ffmpeg_exe = imageio_ffmpeg.get_ffmpeg_exe()
|
|
|
|
# 16kHz, 1채널(Mono), wav 형태로 강제 변환
|
|
command = [
|
|
ffmpeg_exe,
|
|
"-y", # 이미 있으면 덮어쓰기
|
|
"-i", file_path, # 원본 파일
|
|
"-ac", "1", # 채널 수를 1 (Mono)
|
|
"-ar", str(sample_rate), # 16kHz
|
|
wav_path
|
|
]
|
|
|
|
subprocess.run(command, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
|
|
return wav_path
|
|
|
|
except subprocess.CalledProcessError as e:
|
|
err_msg = e.stderr.decode("utf-8", errors="ignore")
|
|
raise STTError(f"오디오 파일 변환 실패 ({file_path}): ffmpeg 오류 - {err_msg}")
|
|
except Exception as e:
|
|
raise STTError(f"오디오 파일 처리 중 예기치 않은 오류 발생: {str(e)}")
|
|
|
|
@staticmethod
|
|
def cleanup(file_path: str):
|
|
"""사용한 임시 wav 파일을 삭제하는 유틸"""
|
|
if os.path.exists(file_path):
|
|
try:
|
|
os.remove(file_path)
|
|
except OSError:
|
|
pass
|