|
|
""" |
|
|
Audio processing utilities |
|
|
""" |
|
|
|
|
|
import logging |
|
|
from pathlib import Path |
|
|
import librosa |
|
|
import numpy as np |
|
|
|
|
|
logger = logging.getLogger(__name__) |
|
|
|
|
|
TARGET_SAMPLE_RATE = 16000 |
|
|
|
|
|
|
|
|
def load_audio(audio_path: Path, sr: int = TARGET_SAMPLE_RATE) -> np.ndarray: |
|
|
""" |
|
|
Загрузить аудио файл. |
|
|
|
|
|
Args: |
|
|
audio_path: Путь к аудио файлу |
|
|
sr: Целевая частота дискретизации |
|
|
|
|
|
Returns: |
|
|
Аудио данные как numpy array |
|
|
""" |
|
|
try: |
|
|
logger.debug(f"Loading audio: {audio_path}") |
|
|
audio, original_sr = librosa.load(str(audio_path), sr=None) |
|
|
|
|
|
|
|
|
if original_sr != sr: |
|
|
logger.debug(f"Resampling from {original_sr}Hz to {sr}Hz") |
|
|
audio = librosa.resample(audio, orig_sr=original_sr, target_sr=sr) |
|
|
|
|
|
logger.info(f"Audio loaded: {len(audio)} samples, {sr}Hz") |
|
|
return audio |
|
|
|
|
|
except Exception as e: |
|
|
logger.error(f"Error loading audio: {e}") |
|
|
raise |
|
|
|
|
|
|
|
|
def resample_audio(audio: np.ndarray, orig_sr: int, target_sr: int) -> np.ndarray: |
|
|
""" |
|
|
Изменить частоту дискретизации аудио. |
|
|
|
|
|
Args: |
|
|
audio: Аудио данные |
|
|
orig_sr: Исходная частота |
|
|
target_sr: Целевая частота |
|
|
|
|
|
Returns: |
|
|
Обработанные аудио данные |
|
|
""" |
|
|
if orig_sr == target_sr: |
|
|
return audio |
|
|
|
|
|
logger.debug(f"Resampling: {orig_sr}Hz -> {target_sr}Hz") |
|
|
return librosa.resample(audio, orig_sr=orig_sr, target_sr=target_sr) |
|
|
|
|
|
|
|
|
def get_audio_duration(audio: np.ndarray, sr: int = TARGET_SAMPLE_RATE) -> float: |
|
|
""" |
|
|
Получить длительность аудио в секундах. |
|
|
|
|
|
Args: |
|
|
audio: Аудио данные |
|
|
sr: Частота дискретизации |
|
|
|
|
|
Returns: |
|
|
Длительность в секундах |
|
|
""" |
|
|
return len(audio) / sr |
|
|
|
|
|
|
|
|
def validate_audio(audio_path: Path) -> bool: |
|
|
""" |
|
|
Проверить валидность аудио файла. |
|
|
|
|
|
Args: |
|
|
audio_path: Путь к файлу |
|
|
|
|
|
Returns: |
|
|
True если файл валиден |
|
|
""" |
|
|
try: |
|
|
audio = load_audio(audio_path) |
|
|
return len(audio) > 0 |
|
|
except Exception as e: |
|
|
logger.error(f"Audio validation failed: {e}") |
|
|
return False |
|
|
|