"""
Audio class for FMUS-VID.
This module provides the Audio class for handling audio operations.
"""
from typing import Union, Optional, Dict, Any, Callable
from pathlib import Path
import logging
logger = logging.getLogger(__name__)
[docs]
class Audio:
"""
Class for handling audio operations.
This class provides methods for manipulating audio.
"""
[docs]
def __init__(self, audio_data: Any, backend: Any):
"""
Initialize an Audio object.
Args:
audio_data: Backend-specific audio data
backend: Backend instance
"""
self._audio_data = audio_data
self._backend = backend
[docs]
def save(self, path: Union[str, Path], **kwargs) -> None:
"""
Save audio to file.
Args:
path: Output file path
**kwargs: Save options
- codec: Audio codec (e.g., "mp3", "aac")
- bitrate: Audio bitrate (e.g., "192k")
Example:
>>> audio.save("output.mp3", codec="mp3", bitrate="192k")
"""
self._backend.save_audio(self._audio_data, path, **kwargs)
[docs]
def trim(self, start: float, end: Optional[float] = None) -> 'Audio':
"""
Trim audio to specified time range.
Args:
start: Start time in seconds
end: End time in seconds (None means until the end)
Returns:
New Audio object
Example:
>>> intro = audio.trim(0, 10) # First 10 seconds
"""
new_audio_data = self._backend.trim_audio(self._audio_data, start, end)
return Audio(new_audio_data, self._backend)
[docs]
def volume(self, level: float) -> 'Audio':
"""
Set audio volume.
Args:
level: Volume level (1.0 = original, 0.5 = 50%, 2.0 = 200%)
Returns:
New Audio object
Example:
>>> quieter = audio.volume(0.8) # Reduce volume to 80%
"""
new_audio_data = self._backend.volume_audio(self._audio_data, level)
return Audio(new_audio_data, self._backend)
[docs]
def fade_in(self, duration: float) -> 'Audio':
"""
Add fade-in effect.
Args:
duration: Fade duration in seconds
Returns:
New Audio object
Example:
>>> with_fade = audio.fade_in(2) # 2-second fade in
"""
new_audio_data = self._backend.fade_in_audio(self._audio_data, duration)
return Audio(new_audio_data, self._backend)
[docs]
def fade_out(self, duration: float) -> 'Audio':
"""
Add fade-out effect.
Args:
duration: Fade duration in seconds
Returns:
New Audio object
Example:
>>> with_fade = audio.fade_out(2) # 2-second fade out
"""
new_audio_data = self._backend.fade_out_audio(self._audio_data, duration)
return Audio(new_audio_data, self._backend)
[docs]
def normalize(self, target_db: float = -3) -> 'Audio':
"""
Normalize audio levels.
Args:
target_db: Target peak level in dB
Returns:
New Audio object
Example:
>>> normalized = audio.normalize(-3) # Normalize to -3 dB
"""
new_audio_data = self._backend.normalize_audio(self._audio_data, target_db)
return Audio(new_audio_data, self._backend)
[docs]
def mix(self, other: 'Audio', weight: float = 0.5) -> 'Audio':
"""
Mix with another audio track.
Args:
other: Audio to mix with
weight: Weight of the other audio (0.5 = equal mix)
Returns:
New Audio object
Example:
>>> mixed = voice.mix(music, weight=0.3) # Mix voice with background music
"""
new_audio_data = self._backend.mix_audio(
self._audio_data,
other._audio_data,
weight
)
return Audio(new_audio_data, self._backend)
[docs]
def info(self) -> Dict[str, Any]:
"""
Get audio information.
Returns:
Dictionary with audio information
- duration: Duration in seconds
- channels: Number of channels
- sample_rate: Sample rate in Hz
- codec: Audio codec
- bitrate: Audio bitrate
Example:
>>> info = audio.info()
>>> print(f"Duration: {info['duration']} seconds")
"""
return self._backend.get_audio_info(self._audio_data)
[docs]
def __repr__(self) -> str:
"""String representation of the Audio object."""
try:
info = self.info()
return (f"Audio(duration={info['duration']:.2f}s, "
f"channels={info['channels']}, "
f"sample_rate={info['sample_rate']}Hz)")
except Exception:
return "Audio(unknown info)"