MIF_E31231708/cv_app/audio_utils_app.py

87 lines
2.6 KiB
Python

from pathlib import Path
import tempfile
import warnings
with warnings.catch_warnings():
warnings.filterwarnings(
"ignore",
message="Couldn't find ffmpeg or avconv.*",
category=RuntimeWarning,
)
from pydub import AudioSegment
try:
import imageio_ffmpeg
except ImportError:
imageio_ffmpeg = None
TARGET_SAMPLE_RATE = 22050
SUPPORTED_AUDIO_EXTENSIONS = {".wav", ".mp3", ".m4a", ".ogg", ".flac", ".webm", ".aac"}
if imageio_ffmpeg is not None:
AudioSegment.converter = imageio_ffmpeg.get_ffmpeg_exe()
def validate_audio_extension(file_path):
extension = Path(file_path).suffix.lower()
if extension not in SUPPORTED_AUDIO_EXTENSIONS:
allowed = ", ".join(sorted(SUPPORTED_AUDIO_EXTENSIONS)).upper().replace(".", "")
raise ValueError(f"Format audio tidak didukung: {extension}. Format yang didukung: {allowed}")
def save_uploaded_file_to_temp(uploaded_file):
"""
Menyimpan file upload Streamlit ke file sementara.
File ini bukan dataset dan tidak disimpan ke ml/data.
"""
suffix = Path(uploaded_file.name).suffix.lower() or ".wav"
validate_audio_extension(f"audio{suffix}")
temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=suffix)
try:
temp_file.write(uploaded_file.getvalue())
return Path(temp_file.name)
finally:
temp_file.close()
def create_temp_wav_path():
temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".wav")
temp_path = Path(temp_file.name)
temp_file.close()
return temp_path
def convert_audio_to_wav(input_path, output_path=None):
"""
Konversi audio upload ke WAV mono 22050 Hz menggunakan pydub/ffmpeg.
"""
input_path = Path(input_path)
validate_audio_extension(input_path)
if not input_path.exists():
raise FileNotFoundError(f"File audio tidak ditemukan: {input_path}")
output_path = Path(output_path) if output_path else create_temp_wav_path()
output_path.parent.mkdir(parents=True, exist_ok=True)
try:
audio = AudioSegment.from_file(input_path)
except FileNotFoundError as error:
raise RuntimeError(
"ffmpeg tidak ditemukan. Pastikan ffmpeg sudah terpasang dan dapat diakses oleh pydub."
) from error
except Exception as error:
raise RuntimeError(f"Gagal membaca atau mengonversi audio: {error}") from error
audio = audio.set_channels(1).set_frame_rate(TARGET_SAMPLE_RATE)
audio.export(output_path, format="wav")
return output_path
def cleanup_temp_files(*paths):
for path in paths:
if path:
Path(path).unlink(missing_ok=True)