from __future__ import annotations from dataclasses import dataclass, field from pathlib import Path from typing import Any, Literal JobState = Literal["PENDING", "RUNNING", "FAILED", "COMPLETED", "CANCEL_REQUESTED", "CANCELLED"] @dataclass class Scene: start: float duration: float media: str caption: str = "" transition: str = "fade" background: str = "blur" layout: str = "fill" effect: str | None = None @dataclass class RenderRequest: scenes: list[Scene] template: str = "tiktok_classic" preset: str | None = None creative_style: str | None = None platform: str | None = None output_name: str = "render.mp4" voiceover: str | None = None background_music: str | None = None music_volume: float = 0.316 music_fade_in: float = 0.0 music_fade_out: float = 0.0 music_loop: bool = True music_start: float = 0.0 music_ducking: bool = True voice_volume: float = 1.0 subtitle_format: Literal["srt", "ass"] = "ass" auto_subtitles: bool = False subtitle_language: str | None = None whisper_model_size: str | None = None preview: bool = False audio_normalize: bool = False watermark: str | None = None watermark_position: str = "bottom-right" intro: str | None = None outro: str | None = None callback_url: str | None = None export_target: str | None = None priority: int = 0 scheduled_at: float | None = None normalize: bool = True metadata: dict[str, Any] = field(default_factory=dict) @dataclass class AIReelsRequest: script: str voiceover: str assets: list[str] template: str = "tiktok_classic" creative_style: str | None = None platform: str | None = None output_name: str = "ai_reel.mp4" background_music: str | None = None music_volume: float = 0.316 music_fade_in: float = 0.0 music_fade_out: float = 0.0 music_loop: bool = True music_start: float = 0.0 music_ducking: bool = True voice_volume: float = 1.0 @dataclass class RenderResult: output_path: Path commands: list[list[str]] metrics: dict[str, Any] logs: list[str] = field(default_factory=list) @dataclass class TaskResult: output_path: Path | None = None commands: list[list[str]] = field(default_factory=list) metrics: dict[str, Any] = field(default_factory=dict) logs: list[str] = field(default_factory=list) @dataclass class AssetMetadata: path: str mime_type: str size_bytes: int mtime: float duration: float = 0.0 width: int | None = None height: int | None = None fps: float | None = None bitrate: int | None = None video_codec: str | None = None audio_codec: str | None = None has_audio: bool = False streams: list[dict[str, Any]] = field(default_factory=list) @dataclass class JobRecord: job_id: str state: JobState created_at: float updated_at: float output_path: str | None = None download_token: str | None = None callback_url: str | None = None export_target: str | None = None export_path: str | None = None failure_reason: str | None = None commands: list[list[str]] = field(default_factory=list) logs: list[str] = field(default_factory=list) metrics: dict[str, Any] = field(default_factory=dict)