Skip to content

Commit 8cb5a47

Browse files
author
cw
committed
Merge branch 'feat/web-ui-complete' into beta
36 commits: Colab GPU inference, episode generation, pipeline executor, full-width layout, asset registration, and Web UI improvements.
2 parents 7a13e6b + 4e97832 commit 8cb5a47

File tree

257 files changed

+28656
-2899
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

257 files changed

+28656
-2899
lines changed

.claude/instructions.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@
1515

1616
**No exceptions.** Even if the user writes in Chinese or another language, all code, documentation, and generated files MUST be written in English.
1717

18+
## Web UI Layout Rules
19+
20+
- **All pages must use full-width layout** matching `/create` page style: `padding: 20px 32px 24px; max-width: 100%`. Do NOT use constrained `max-width` (e.g. 1000px, 1200px) or `margin: 0 auto` centering on page containers. Content should fill the available width uniformly across all pages.
21+
1822
## Code Style
1923

2024
- Follow Dart style guide for daemon code

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,10 @@ test_audio.aiff
1515
.vscode/
1616
.idea/
1717

18+
# Python
19+
.venv/
20+
__pycache__/
21+
*.pyc
22+
1823
# OS
1924
.DS_Store
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
{
2+
"id": "template_anime_episode",
3+
"name": "Anime Episode (3 Scenes)",
4+
"description": "Generate a mini anime episode with 3 scenes: opening, conflict, resolution. Each scene gets AI image generation, video animation, TTS voice acting, and subtitle overlay.",
5+
"parameters": [
6+
{
7+
"name": "narrative_text",
8+
"type": "string",
9+
"description": "Novel text or story synopsis to convert into an anime episode",
10+
"required": true
11+
},
12+
{
13+
"name": "language",
14+
"type": "string",
15+
"description": "Language for dialogue and TTS (zh-CN, ja-JP, en-US)",
16+
"defaultValue": "zh-CN"
17+
},
18+
{
19+
"name": "style",
20+
"type": "string",
21+
"description": "Visual style preset (anime, cinematic, epic)",
22+
"defaultValue": "anime"
23+
}
24+
],
25+
"nodes": [
26+
{
27+
"id": "img_0",
28+
"type": "media_ai_generate_image",
29+
"domain": "media_creation",
30+
"label": "Scene 1: Opening Image",
31+
"position": { "x": 100, "y": 50 },
32+
"params": {
33+
"prompt": "{{params.narrative_text}} - Opening scene, anime style, establishing shot, cinematic lighting, 16:9",
34+
"style": "anime",
35+
"aspect_ratio": "16:9",
36+
"provider": "pollinations"
37+
}
38+
},
39+
{
40+
"id": "img_1",
41+
"type": "media_ai_generate_image",
42+
"domain": "media_creation",
43+
"label": "Scene 2: Conflict Image",
44+
"position": { "x": 100, "y": 200 },
45+
"params": {
46+
"prompt": "{{params.narrative_text}} - Dramatic conflict scene, anime style, intense action, dynamic composition, 16:9",
47+
"style": "anime",
48+
"aspect_ratio": "16:9",
49+
"provider": "pollinations"
50+
}
51+
},
52+
{
53+
"id": "img_2",
54+
"type": "media_ai_generate_image",
55+
"domain": "media_creation",
56+
"label": "Scene 3: Resolution Image",
57+
"position": { "x": 100, "y": 350 },
58+
"params": {
59+
"prompt": "{{params.narrative_text}} - Resolution scene, anime style, emotional moment, beautiful lighting, 16:9",
60+
"style": "anime",
61+
"aspect_ratio": "16:9",
62+
"provider": "pollinations"
63+
}
64+
},
65+
{
66+
"id": "vid_0",
67+
"type": "media_ai_generate_video",
68+
"domain": "media_creation",
69+
"label": "Scene 1: Video",
70+
"position": { "x": 400, "y": 50 },
71+
"params": {
72+
"image_base64": "{{img_0.image_base64}}",
73+
"custom_prompt": "Gentle camera pan, anime opening scene, soft lighting",
74+
"style": "cinematic",
75+
"duration": 5
76+
}
77+
},
78+
{
79+
"id": "vid_1",
80+
"type": "media_ai_generate_video",
81+
"domain": "media_creation",
82+
"label": "Scene 2: Video",
83+
"position": { "x": 400, "y": 200 },
84+
"params": {
85+
"image_base64": "{{img_1.image_base64}}",
86+
"custom_prompt": "Dynamic camera movement, action scene, intense energy",
87+
"style": "epic",
88+
"duration": 5
89+
}
90+
},
91+
{
92+
"id": "vid_2",
93+
"type": "media_ai_generate_video",
94+
"domain": "media_creation",
95+
"label": "Scene 3: Video",
96+
"position": { "x": 400, "y": 350 },
97+
"params": {
98+
"image_base64": "{{img_2.image_base64}}",
99+
"custom_prompt": "Slow zoom, emotional resolution, warm lighting",
100+
"style": "calmAesthetic",
101+
"duration": 5
102+
}
103+
},
104+
{
105+
"id": "tts_0",
106+
"type": "media_tts_synthesize",
107+
"domain": "media_creation",
108+
"label": "Scene 1: Narration",
109+
"position": { "x": 400, "y": 100 },
110+
"params": {
111+
"text": "The story begins...",
112+
"voice": "zh-CN-YunjianNeural"
113+
}
114+
},
115+
{
116+
"id": "output",
117+
"type": "output",
118+
"domain": "system",
119+
"label": "Final Episode",
120+
"position": { "x": 700, "y": 200 },
121+
"params": {
122+
"format": "mp4"
123+
}
124+
}
125+
],
126+
"edges": [
127+
{ "id": "e1", "source": "img_0", "source_port": "output", "target": "vid_0", "target_port": "input" },
128+
{ "id": "e2", "source": "img_1", "source_port": "output", "target": "vid_1", "target_port": "input" },
129+
{ "id": "e3", "source": "img_2", "source_port": "output", "target": "vid_2", "target_port": "input" },
130+
{ "id": "e4", "source": "vid_0", "source_port": "output", "target": "output", "target_port": "input" },
131+
{ "id": "e5", "source": "vid_1", "source_port": "output", "target": "output", "target_port": "input" },
132+
{ "id": "e6", "source": "vid_2", "source_port": "output", "target": "output", "target_port": "input" },
133+
{ "id": "e7", "source": "tts_0", "source_port": "output", "target": "output", "target_port": "input" }
134+
]
135+
}
Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
{
2+
"id": "template_cultivation_anime",
3+
"name": "Cultivation Anime (Xianxia)",
4+
"description": "Film-quality xianxia cultivation anime pipeline. Uses Animagine XL for keyframes, AnimateDiff V3 + ControlNet lineart_anime for video, Edge TTS for Chinese dialogue, anime_cinematic LUT, YouTube 1080p encoding. Optimized for genres like A Record of a Mortal's Journey to Immortality.",
5+
"parameters": [
6+
{
7+
"name": "quality",
8+
"type": "string",
9+
"description": "Quality tier: draft (fast), standard (Real-ESRGAN + RIFE), cinematic (full post-processing)",
10+
"default": "standard"
11+
}
12+
],
13+
"nodes": [
14+
{
15+
"id": "scene_0_keyframe",
16+
"type": "media_local_generate_image",
17+
"domain": "media_creation",
18+
"label": "S1 Keyframe: Cultivation Awakening",
19+
"position": { "x": 100, "y": 0 },
20+
"params": {
21+
"prompt": "1boy, young cultivator, flowing white robes, spiritual_energy, mountain landscape, ancient Chinese architecture, xianxia, cinematic lighting, masterpiece, best quality, highly detailed, anime style, dramatic sky, qi aura glowing around body",
22+
"model": "animagine_xl",
23+
"width": 1280,
24+
"height": 720
25+
}
26+
},
27+
{
28+
"id": "scene_0_video",
29+
"type": "media_local_controlnet_video",
30+
"domain": "media_creation",
31+
"label": "S1 Video: Awakening",
32+
"position": { "x": 400, "y": 0 },
33+
"params": {
34+
"prompt": "1boy cultivator meditating, spiritual energy swirling, camera slowly zooming in, flowing robes moving in wind, qi particles floating upward, cinematic anime",
35+
"reference_image_base64": "{{scene_0_keyframe.image_base64}}",
36+
"control_type": "lineart_anime",
37+
"controlnet_scale": 0.8
38+
}
39+
},
40+
{
41+
"id": "scene_0_tts",
42+
"type": "media_tts_synthesize",
43+
"domain": "media_creation",
44+
"label": "S1 TTS: Narration",
45+
"position": { "x": 100, "y": 150 },
46+
"params": {
47+
"text": "在这片修仙大陆之上,灵气充盈天地之间。一位少年,即将踏上他的修仙之路。",
48+
"voice": "zh-CN-YunjianNeural",
49+
"provider": "edge_tts"
50+
}
51+
},
52+
{
53+
"id": "assembly_0",
54+
"type": "media_scene_assembly",
55+
"domain": "media_creation",
56+
"label": "S1 Assembly",
57+
"position": { "x": 700, "y": 0 },
58+
"params": {
59+
"video_path": "{{scene_0_video.path}}",
60+
"audio_path": "{{scene_0_tts.path}}"
61+
}
62+
},
63+
{
64+
"id": "scene_1_keyframe",
65+
"type": "media_local_generate_image",
66+
"domain": "media_creation",
67+
"label": "S2 Keyframe: Battle",
68+
"position": { "x": 100, "y": 300 },
69+
"params": {
70+
"prompt": "1boy, cultivator in battle stance, sword qi, energy slash, dramatic action pose, dark cave background, spiritual beasts, xianxia combat, dynamic composition, masterpiece, best quality, anime style, cinematic, epic lighting, particle effects",
71+
"model": "animagine_xl",
72+
"width": 1280,
73+
"height": 720
74+
}
75+
},
76+
{
77+
"id": "scene_1_video",
78+
"type": "media_local_controlnet_video",
79+
"domain": "media_creation",
80+
"label": "S2 Video: Battle",
81+
"position": { "x": 400, "y": 300 },
82+
"params": {
83+
"prompt": "cultivator fighting, sword energy burst, dynamic camera movement, intense action, spiritual energy explosion, anime battle scene",
84+
"reference_image_base64": "{{scene_1_keyframe.image_base64}}",
85+
"control_type": "lineart_anime",
86+
"controlnet_scale": 0.8
87+
}
88+
},
89+
{
90+
"id": "scene_1_tts",
91+
"type": "media_tts_synthesize",
92+
"domain": "media_creation",
93+
"label": "S2 TTS: Battle",
94+
"position": { "x": 100, "y": 450 },
95+
"params": {
96+
"text": "面对凶猛的妖兽,他毫不畏惧,挥剑斩出一道凌厉的剑气。这一战,将决定他的命运。",
97+
"voice": "zh-CN-YunjianNeural",
98+
"provider": "edge_tts"
99+
}
100+
},
101+
{
102+
"id": "assembly_1",
103+
"type": "media_scene_assembly",
104+
"domain": "media_creation",
105+
"label": "S2 Assembly",
106+
"position": { "x": 700, "y": 300 },
107+
"params": {
108+
"video_path": "{{scene_1_video.path}}",
109+
"audio_path": "{{scene_1_tts.path}}"
110+
}
111+
},
112+
{
113+
"id": "scene_2_keyframe",
114+
"type": "media_local_generate_image",
115+
"domain": "media_creation",
116+
"label": "S3 Keyframe: Breakthrough",
117+
"position": { "x": 100, "y": 600 },
118+
"params": {
119+
"prompt": "1boy, cultivator achieving breakthrough, ascending to next cultivation level, heavenly tribulation lightning, golden qi pillar, mountain peak, clouds parting, ethereal glow, xianxia apotheosis, masterpiece, best quality, anime style, epic scale, heavenly light",
120+
"model": "animagine_xl",
121+
"width": 1280,
122+
"height": 720
123+
}
124+
},
125+
{
126+
"id": "scene_2_video",
127+
"type": "media_local_controlnet_video",
128+
"domain": "media_creation",
129+
"label": "S3 Video: Breakthrough",
130+
"position": { "x": 400, "y": 600 },
131+
"params": {
132+
"prompt": "cultivator breakthrough moment, golden qi erupting skyward, heavenly tribulation lightning, clouds swirling, camera pulling back to reveal epic scale, anime cinematic",
133+
"reference_image_base64": "{{scene_2_keyframe.image_base64}}",
134+
"control_type": "lineart_anime",
135+
"controlnet_scale": 0.8
136+
}
137+
},
138+
{
139+
"id": "scene_2_tts",
140+
"type": "media_tts_synthesize",
141+
"domain": "media_creation",
142+
"label": "S3 TTS: Breakthrough",
143+
"position": { "x": 100, "y": 750 },
144+
"params": {
145+
"text": "天地之力汇聚于他身上,一道金色光柱冲天而起。他终于突破了,踏入了筑基期!",
146+
"voice": "zh-CN-YunjianNeural",
147+
"provider": "edge_tts"
148+
}
149+
},
150+
{
151+
"id": "assembly_2",
152+
"type": "media_scene_assembly",
153+
"domain": "media_creation",
154+
"label": "S3 Assembly",
155+
"position": { "x": 700, "y": 600 },
156+
"params": {
157+
"video_path": "{{scene_2_video.path}}",
158+
"audio_path": "{{scene_2_tts.path}}"
159+
}
160+
},
161+
{
162+
"id": "post_concat",
163+
"type": "media_video_assembly",
164+
"domain": "media_creation",
165+
"label": "Concat All Scenes",
166+
"position": { "x": 1000, "y": 300 },
167+
"params": {
168+
"clips": [
169+
"{{assembly_0.path}}",
170+
"{{assembly_1.path}}",
171+
"{{assembly_2.path}}"
172+
]
173+
}
174+
},
175+
{
176+
"id": "post_upscale",
177+
"type": "media_upscale_video",
178+
"domain": "media_creation",
179+
"label": "Real-ESRGAN 4x Upscale",
180+
"position": { "x": 1250, "y": 300 },
181+
"params": {
182+
"video_path": "{{post_concat.path}}"
183+
}
184+
},
185+
{
186+
"id": "post_colorgrade",
187+
"type": "media_lut_colorgrade",
188+
"domain": "media_creation",
189+
"label": "Anime Cinematic LUT",
190+
"position": { "x": 1500, "y": 300 },
191+
"params": {
192+
"video_path": "{{post_upscale.path}}",
193+
"lut_name": "anime_cinematic"
194+
}
195+
},
196+
{
197+
"id": "post_encode",
198+
"type": "media_platform_encode",
199+
"domain": "media_creation",
200+
"label": "YouTube 1080p",
201+
"position": { "x": 1750, "y": 300 },
202+
"params": {
203+
"video_path": "{{post_colorgrade.path}}",
204+
"platform": "youtube"
205+
}
206+
}
207+
],
208+
"edges": [
209+
{ "id": "e_s0_kf_vid", "source": "scene_0_keyframe", "source_port": "output", "target": "scene_0_video", "target_port": "input" },
210+
{ "id": "e_s0_vid_asm", "source": "scene_0_video", "source_port": "output", "target": "assembly_0", "target_port": "input" },
211+
{ "id": "e_s0_tts_asm", "source": "scene_0_tts", "source_port": "output", "target": "assembly_0", "target_port": "audio" },
212+
{ "id": "e_s1_kf_vid", "source": "scene_1_keyframe", "source_port": "output", "target": "scene_1_video", "target_port": "input" },
213+
{ "id": "e_s1_vid_asm", "source": "scene_1_video", "source_port": "output", "target": "assembly_1", "target_port": "input" },
214+
{ "id": "e_s1_tts_asm", "source": "scene_1_tts", "source_port": "output", "target": "assembly_1", "target_port": "audio" },
215+
{ "id": "e_s2_kf_vid", "source": "scene_2_keyframe", "source_port": "output", "target": "scene_2_video", "target_port": "input" },
216+
{ "id": "e_s2_vid_asm", "source": "scene_2_video", "source_port": "output", "target": "assembly_2", "target_port": "input" },
217+
{ "id": "e_s2_tts_asm", "source": "scene_2_tts", "source_port": "output", "target": "assembly_2", "target_port": "audio" },
218+
{ "id": "e_asm0_concat", "source": "assembly_0", "source_port": "output", "target": "post_concat", "target_port": "input" },
219+
{ "id": "e_asm1_concat", "source": "assembly_1", "source_port": "output", "target": "post_concat", "target_port": "input" },
220+
{ "id": "e_asm2_concat", "source": "assembly_2", "source_port": "output", "target": "post_concat", "target_port": "input" },
221+
{ "id": "e_concat_up", "source": "post_concat", "source_port": "output", "target": "post_upscale", "target_port": "input" },
222+
{ "id": "e_up_grade", "source": "post_upscale", "source_port": "output", "target": "post_colorgrade", "target_port": "input" },
223+
{ "id": "e_grade_enc", "source": "post_colorgrade", "source_port": "output", "target": "post_encode", "target_port": "input" }
224+
]
225+
}

0 commit comments

Comments
 (0)