File size: 3,619 Bytes
345855e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5d782cc
 
345855e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5d782cc
345855e
 
 
 
 
 
5d782cc
 
 
345855e
 
 
5d782cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
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
    callback_url: str | None = None
    export_target: str | None = None


@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
    job_type: str = "task"
    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
    callback_attempts: int = 0
    callback_delivered_at: float | None = None
    callback_last_error: 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)
    metadata: dict[str, Any] = field(default_factory=dict)