Source code for fmusvid.backends.backend

"""
Backend interface for FMUS-VID.

This module defines the abstract base class that all backends must implement.
"""

from abc import ABC, abstractmethod
from typing import Union, List, Tuple, Optional, Dict, Any, Callable
from pathlib import Path
import os
from ..operations.subtitle import SubtitleEntry

[docs] class Backend(ABC): """Abstract base class for all video processing backends."""
[docs] @abstractmethod def load(self, path: Union[str, Path], **kwargs) -> Any: """Load a video file.""" pass
[docs] @abstractmethod def create(self, width: int, height: int, duration: float, fps: float, color: Tuple[int, int, int], **kwargs) -> Any: """Create a blank video.""" pass
[docs] @abstractmethod def save(self, video: Any, output_path: Union[str, Path], progress_callback: Optional[Callable[[float], None]] = None, **kwargs) -> None: """Save video to file.""" pass
[docs] @abstractmethod def get_info(self, video: Any) -> Dict[str, Any]: """Get video information (width, height, duration, etc.).""" pass
[docs] @abstractmethod def trim(self, video: Any, start: float, end: Optional[float] = None) -> Any: """Trim video to specified time range.""" pass
[docs] @abstractmethod def resize(self, video: Any, width: Optional[int] = None, height: Optional[int] = None, keep_aspect: bool = True) -> Any: """Resize video to specified dimensions.""" pass
[docs] @abstractmethod def crop(self, video: Any, x: int, y: int, width: int, height: int) -> Any: """Crop video to specified region.""" pass
[docs] @abstractmethod def rotate(self, video: Any, degrees: float) -> Any: """Rotate video by specified degrees.""" pass
[docs] @abstractmethod def grayscale(self, video: Any) -> Any: """Convert video to grayscale.""" pass
[docs] @abstractmethod def blur(self, video: Any, radius: float) -> Any: """Apply Gaussian blur with specified radius.""" pass
[docs] @abstractmethod def brightness(self, video: Any, factor: float) -> Any: """Adjust video brightness.""" pass
[docs] @abstractmethod def contrast(self, video: Any, factor: float) -> Any: """Adjust video contrast.""" pass
[docs] @abstractmethod def mute(self, video: Any) -> Any: """Remove audio track.""" pass
[docs] @abstractmethod def volume(self, video: Any, level: float) -> Any: """Set audio volume.""" pass
[docs] @abstractmethod def add_audio(self, video: Any, audio_path: Union[str, Path], start: float = 0, volume: float = 1.0) -> Any: """Add audio track starting at specified time.""" pass
[docs] @abstractmethod def extract_frame(self, video: Any, time: float) -> Any: """Extract a single frame at specified time.""" pass
[docs] @abstractmethod def overlay(self, video: Any, overlay_video: Any, position: Tuple[int, int] = (0, 0), start: float = 0, duration: Optional[float] = None, opacity: float = 1.0) -> Any: """Overlay another video (picture-in-picture).""" pass
[docs] @abstractmethod def concat(self, videos: List[Any]) -> Any: """Concatenate multiple videos.""" pass
[docs] @abstractmethod def grid(self, videos: List[Any], rows: int, cols: int) -> Any: """Arrange videos in a grid layout.""" pass
[docs] @abstractmethod def add_subtitles(self, video: Any, entries: List[SubtitleEntry], font: str = "Arial", size: int = 24, color: Union[str, Tuple[int, int, int]] = "white", position: Optional[Tuple[int, int]] = None) -> Any: """Add subtitles from a list of entries.""" pass
[docs] @abstractmethod def add_subtitle_text(self, video: Any, entry: SubtitleEntry, font: str = "Arial", size: int = 24, color: Union[str, Tuple[int, int, int]] = "white") -> Any: """Add a single subtitle entry.""" pass
[docs] @abstractmethod def speed(self, video: Any, factor: float) -> Any: """Change playback speed (factor > 1 = faster, factor < 1 = slower).""" pass
[docs] @abstractmethod def reverse(self, video: Any) -> Any: """Reverse video playback.""" pass
[docs] @abstractmethod def fade_in(self, video: Any, duration: float) -> Any: """Fade video in from black.""" pass
[docs] @abstractmethod def fade_out(self, video: Any, duration: float) -> Any: """Fade video out to black.""" pass
[docs] @abstractmethod def fade_audio_in(self, video: Any, duration: float) -> Any: """Fade audio in.""" pass
[docs] @abstractmethod def fade_audio_out(self, video: Any, duration: float) -> Any: """Fade audio out.""" pass
[docs] @abstractmethod def chroma_key(self, video: Any, color: Tuple[int, int, int], similarity: float = 0.1, blend: float = 0.0) -> Any: """Remove green screen / chroma key.""" pass
[docs] @abstractmethod def normalize_audio(self, video: Any, target_db: float = -16.0) -> Any: """Normalize audio to target dB level.""" pass
[docs] @abstractmethod def crossfade(self, video1: Any, video2: Any, duration: float) -> Any: """Crossfade between two videos.""" pass
[docs] @abstractmethod def replace_audio(self, video: Any, audio_path: Union[str, Path]) -> Any: """Replace audio track with new audio.""" pass
[docs] @abstractmethod def export_gif(self, video: Any, output_path: Union[str, Path], fps: Optional[float] = None, quality: int = 95, loop: int = 0, width: Optional[int] = None) -> None: """Export video as animated GIF.""" pass
[docs] @abstractmethod def export_frames(self, video: Any, output_dir: Union[str, Path], prefix: str = "frame_", format: str = "png", start: Optional[float] = None, end: Optional[float] = None, fps: Optional[float] = None) -> List[Path]: """Export video frames as images.""" pass
[docs] @abstractmethod def add_text(self, video: Any, overlay: Any) -> Any: """Add text overlay to video.""" pass
[docs] @abstractmethod def add_image(self, video: Any, overlay: Any) -> Any: """Add image overlay to video.""" pass
[docs] @staticmethod def is_available() -> bool: """Check if the backend is available on the system.""" return False