87 lines
2.6 KiB
Python
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)
|