"""
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 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