MIF_E31231708/ml/audio_utils.py

84 lines
2.3 KiB
Python

from pathlib import Path
import shutil
import subprocess
import imageio_ffmpeg
TARGET_SAMPLE_RATE = 22050
SUPPORTED_AUDIO_EXTENSIONS = {".wav", ".mp3", ".m4a", ".ogg", ".flac", ".webm", ".aac"}
def configure_ffmpeg():
"""
Mengambil path ffmpeg dari imageio-ffmpeg.
Jika ffmpeg gagal tersedia, error dibuat lebih mudah dipahami.
"""
try:
return imageio_ffmpeg.get_ffmpeg_exe()
except Exception as error:
raise RuntimeError(
"ffmpeg belum tersedia. Jalankan `pip install imageio-ffmpeg` "
"atau install ffmpeg di sistem operasi."
) from error
def convert_to_wav(input_path, output_path):
"""
Mengubah WAV, MP3, M4A, OGG, FLAC, WEBM, atau AAC menjadi WAV.
Output selalu:
- WAV
- mono
- sample rate 22050 Hz
"""
input_path = Path(input_path)
output_path = Path(output_path)
extension = input_path.suffix.lower()
if not input_path.exists():
raise FileNotFoundError(f"File audio tidak ditemukan: {input_path}")
if extension not in SUPPORTED_AUDIO_EXTENSIONS:
allowed = ", ".join(sorted(SUPPORTED_AUDIO_EXTENSIONS))
raise ValueError(f"Format audio tidak didukung: {extension}. Format yang didukung: {allowed}")
output_path.parent.mkdir(parents=True, exist_ok=True)
if extension == ".wav":
if input_path.resolve() != output_path.resolve():
shutil.copyfile(input_path, output_path)
return output_path
command = [
configure_ffmpeg(),
"-y",
"-i",
str(input_path),
"-vn",
"-ac",
"1",
"-ar",
str(TARGET_SAMPLE_RATE),
"-f",
"wav",
str(output_path),
]
try:
result = subprocess.run(command, capture_output=True, text=True, check=False)
except FileNotFoundError as error:
raise RuntimeError(
"ffmpeg tidak bisa dijalankan. Pastikan dependency `imageio-ffmpeg` "
"sudah terpasang atau install ffmpeg secara manual."
) from error
if result.returncode != 0:
error_message = result.stderr.strip() or "Tidak ada detail error dari ffmpeg."
raise RuntimeError(f"Konversi audio gagal: {error_message}")
if not output_path.exists():
raise RuntimeError("Konversi audio gagal: file WAV output tidak terbentuk.")
return output_path