67 lines
2.0 KiB
Python
67 lines
2.0 KiB
Python
"""Audio file utility functions shared across audio processing services."""
|
|
|
|
import hashlib
|
|
from pathlib import Path
|
|
from typing import TYPE_CHECKING
|
|
|
|
import ffmpeg # type: ignore[import-untyped]
|
|
|
|
from app.core.logging import get_logger
|
|
|
|
if TYPE_CHECKING:
|
|
from app.models.sound import Sound
|
|
|
|
logger = get_logger(__name__)
|
|
|
|
|
|
def get_file_hash(file_path: Path) -> str:
|
|
"""Calculate SHA-256 hash of a file."""
|
|
hash_sha256 = hashlib.sha256()
|
|
with file_path.open("rb") as f:
|
|
for chunk in iter(lambda: f.read(4096), b""):
|
|
hash_sha256.update(chunk)
|
|
return hash_sha256.hexdigest()
|
|
|
|
|
|
def get_file_size(file_path: Path) -> int:
|
|
"""Get file size in bytes."""
|
|
return file_path.stat().st_size
|
|
|
|
|
|
def get_audio_duration(file_path: Path) -> int:
|
|
"""Get audio duration in milliseconds using ffmpeg."""
|
|
try:
|
|
probe = ffmpeg.probe(str(file_path))
|
|
duration = float(probe["format"]["duration"])
|
|
return int(duration * 1000) # Convert to milliseconds
|
|
except (ffmpeg.Error, KeyError, ValueError, TypeError, Exception) as e: # noqa: BLE001
|
|
logger.warning("Failed to get duration for %s: %s", file_path, e)
|
|
return 0
|
|
|
|
|
|
def get_sound_file_path(sound: "Sound") -> Path:
|
|
"""Get the file path for a sound based on its type and normalization status.
|
|
|
|
Args:
|
|
sound: The Sound object to get the path for
|
|
|
|
Returns:
|
|
Path: The full path to the sound file
|
|
|
|
"""
|
|
# Determine the correct subdirectory based on sound type
|
|
if sound.type.upper() == "EXT":
|
|
subdir = "extracted"
|
|
elif sound.type.upper() == "SDB":
|
|
subdir = "soundboard"
|
|
elif sound.type.upper() == "TTS":
|
|
subdir = "text_to_speech"
|
|
else:
|
|
# Fallback to lowercase type
|
|
subdir = sound.type.lower()
|
|
|
|
# Use normalized file if available, otherwise original
|
|
if sound.is_normalized and sound.normalized_filename:
|
|
return Path("sounds/normalized") / subdir / sound.normalized_filename
|
|
return Path("sounds/originals") / subdir / sound.filename
|