返回 Pixelle-Video
storyboard.py
根目录 / pixelle_video / models / storyboard.py
1 # Copyright (C) 2025 AIDC-AI
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 # http://www.apache.org/licenses/LICENSE-2.0
7 # Unless required by applicable law or agreed to in writing, software
8 # distributed under the License is distributed on an "AS IS" BASIS,
9 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 # See the License for the specific language governing permissions and
11 # limitations under the License.
12
13 """
14 Storyboard data models for video generation
15 """
16
17 from dataclasses import dataclass, field
18 from datetime import datetime
19 from typing import List, Optional, Dict, Any
20
21
22 @dataclass
23 class StoryboardConfig:
24 """Storyboard configuration parameters"""
25
26 # Required parameters (must come first in dataclass)
27 media_width: int # Media width (image or video, required)
28 media_height: int # Media height (image or video, required)
29
30 # Task isolation
31 task_id: Optional[str] = None # Task ID for file isolation (auto-generated if None)
32
33 n_storyboard: int = 5 # Number of storyboard frames
34 min_narration_words: int = 5 # Min narration word count
35 max_narration_words: int = 20 # Max narration word count
36 min_image_prompt_words: int = 30 # Min image prompt word count
37 max_image_prompt_words: int = 60 # Max image prompt word count
38
39 # Video parameters (fps only, size is determined by frame template)
40 video_fps: int = 30 # Frame rate
41
42 # Audio parameters
43 tts_inference_mode: str = "local" # TTS inference mode: "local" or "comfyui"
44 voice_id: Optional[str] = None # Voice ID (for local: Edge TTS voice ID; for comfyui: workflow-specific)
45 tts_workflow: Optional[str] = None # TTS workflow filename (for ComfyUI mode, None = use default)
46 tts_speed: Optional[float] = None # TTS speed multiplier (0.5-2.0, 1.0 = normal)
47 ref_audio: Optional[str] = None # Reference audio for voice cloning (ComfyUI mode only)
48
49 # Media workflow
50 media_workflow: Optional[str] = None # Media workflow filename (image or video, None = use default)
51 api_video_params: Optional[Dict[str, Any]] = None # Extra direct API video generation parameters
52
53 # Frame template (includes size information in path)
54 frame_template: str = "1080x1920/default.html" # Template path with size (e.g., "1080x1920/default.html")
55 template_params: Optional[Dict[str, Any]] = None # Custom template parameters (e.g., {"accent_color": "#ff0000"})
56
57
58 @dataclass
59 class StoryboardFrame:
60 """Single storyboard frame"""
61 index: int # Frame index (0-based)
62 narration: str # Narration text
63 image_prompt: str # Image generation prompt (can be None for text-only or video)
64
65 # Generated resource paths
66 audio_path: Optional[str] = None # Audio file path (narration)
67 media_type: Optional[str] = None # Media type: "image" or "video" (None if no media)
68 image_path: Optional[str] = None # Original image path (for image type)
69 video_path: Optional[str] = None # Original video path (for video type, before composition)
70 composed_image_path: Optional[str] = None # Composed image path (with subtitles, for image type)
71 video_segment_path: Optional[str] = None # Final video segment path
72
73 # Metadata
74 duration: float = 0.0 # Frame duration (seconds, from audio or video)
75 created_at: Optional[datetime] = None
76
77 def __post_init__(self):
78 if self.created_at is None:
79 self.created_at = datetime.now()
80
81
82 @dataclass
83 class ContentMetadata:
84 """Content metadata for visual display and narration generation"""
85 title: str # Content title
86 author: Optional[str] = None # Author/creator
87 subtitle: Optional[str] = None # Subtitle
88 genre: Optional[str] = None # Genre/category
89 summary: Optional[str] = None # Content summary
90 publication_year: Optional[str] = None # Publication year
91 cover_url: Optional[str] = None # Cover/thumbnail image URL
92
93
94 @dataclass
95 class Storyboard:
96 """Complete storyboard"""
97 title: str # Video title
98 config: StoryboardConfig # Configuration
99 frames: List[StoryboardFrame] = field(default_factory=list)
100
101 # Content metadata (optional)
102 content_metadata: Optional[ContentMetadata] = None
103
104 # Final output
105 final_video_path: Optional[str] = None
106 total_duration: float = 0.0
107
108 # Metadata
109 created_at: Optional[datetime] = None
110 completed_at: Optional[datetime] = None
111
112 def __post_init__(self):
113 if self.created_at is None:
114 self.created_at = datetime.now()
115
116 @property
117 def is_completed(self) -> bool:
118 """Check if all frames are processed"""
119 return all(
120 frame.video_segment_path is not None
121 for frame in self.frames
122 )
123
124 @property
125 def progress(self) -> float:
126 """Return processing progress (0.0-1.0)"""
127 if not self.frames:
128 return 0.0
129 completed = sum(
130 1 for frame in self.frames
131 if frame.video_segment_path is not None
132 )
133 return completed / len(self.frames)
134
135
136 @dataclass
137 class VideoGenerationResult:
138 """Video generation result"""
139 video_path: str # Final video path
140 storyboard: Storyboard # Complete storyboard
141 duration: float # Total duration
142 file_size: int # File size (bytes)
143 created_at: datetime = field(default_factory=datetime.now)
144
144 lines PYTHON