Munaf1987 commited on
Commit
05104b1
Β·
verified Β·
1 Parent(s): 1ab3619

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +629 -1
app.py CHANGED
@@ -1 +1,629 @@
1
- 14,21
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import torch
3
+ import numpy as np
4
+ import cv2
5
+ from PIL import Image
6
+ import json
7
+ import os
8
+ from typing import List, Dict, Any
9
+ import tempfile
10
+ import subprocess
11
+ from pathlib import Path
12
+ import spaces
13
+ import gc
14
+
15
+ # All open-source HuggingFace models
16
+ from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
17
+ from diffusers import (
18
+ StableDiffusionPipeline,
19
+ StableDiffusionXLPipeline,
20
+ StableVideoDiffusionPipeline,
21
+ AnimateDiffPipeline,
22
+ MotionAdapter,
23
+ DDIMScheduler,
24
+ DPMSolverMultistepScheduler
25
+ )
26
+ from diffusers.utils import export_to_video
27
+ import soundfile as sf
28
+
29
+ class CartoonFilmGenerator:
30
+ def __init__(self):
31
+ self.device = "cuda" if torch.cuda.is_available() else "cpu"
32
+ self.temp_dir = tempfile.mkdtemp()
33
+
34
+ # Model configurations for ZeroGPU optimization
35
+ self.models_loaded = False
36
+
37
+ @spaces.GPU
38
+ def load_models(self):
39
+ """Load models on-demand for ZeroGPU efficiency"""
40
+ if self.models_loaded:
41
+ return
42
+
43
+ print("πŸš€ Loading open-source models...")
44
+
45
+ try:
46
+ # 1. Image generation - Using SD 1.5 for better compatibility
47
+ print("πŸ“· Loading image generator...")
48
+ self.image_generator = StableDiffusionPipeline.from_pretrained(
49
+ "runwayml/stable-diffusion-v1-5",
50
+ torch_dtype=torch.float16,
51
+ use_safetensors=True,
52
+ safety_checker=None,
53
+ requires_safety_checker=False
54
+ ).to(self.device)
55
+
56
+ # Enable memory optimizations
57
+ self.image_generator.enable_vae_slicing()
58
+ if hasattr(self.image_generator, 'enable_vae_tiling'):
59
+ self.image_generator.enable_vae_tiling()
60
+
61
+ print("βœ… Image generator loaded successfully")
62
+
63
+ except Exception as e:
64
+ print(f"❌ Image generator failed: {e}")
65
+ self.image_generator = None
66
+
67
+ try:
68
+ # 2. Video generation - Simplified AnimateDiff setup
69
+ print("πŸŽ₯ Loading video generator...")
70
+
71
+ # Use a more stable motion adapter
72
+ adapter = MotionAdapter.from_pretrained(
73
+ "guoyww/animatediff-motion-adapter-v1-5-2",
74
+ torch_dtype=torch.float16
75
+ )
76
+
77
+ self.video_generator = AnimateDiffPipeline.from_pretrained(
78
+ "runwayml/stable-diffusion-v1-5",
79
+ motion_adapter=adapter,
80
+ torch_dtype=torch.float16,
81
+ safety_checker=None,
82
+ requires_safety_checker=False
83
+ ).to(self.device)
84
+
85
+ # Use DPM solver for better stability
86
+ self.video_generator.scheduler = DPMSolverMultistepScheduler.from_pretrained(
87
+ "runwayml/stable-diffusion-v1-5",
88
+ subfolder="scheduler"
89
+ )
90
+
91
+ # Enable memory optimizations
92
+ self.video_generator.enable_vae_slicing()
93
+ if hasattr(self.video_generator, 'enable_vae_tiling'):
94
+ self.video_generator.enable_vae_tiling()
95
+
96
+ print("βœ… Video generator loaded successfully")
97
+
98
+ except Exception as e:
99
+ print(f"❌ Video generator failed: {e}")
100
+ self.video_generator = None
101
+
102
+ # 3. Skip TTS for now due to loading issues
103
+ print("πŸ”‡ Skipping TTS model due to loading issues")
104
+ self.tts_model = None
105
+
106
+ self.models_loaded = True
107
+ print("🎬 Model loading completed!")
108
+
109
+ def clear_gpu_memory(self):
110
+ """Clear GPU memory between operations"""
111
+ if torch.cuda.is_available():
112
+ torch.cuda.empty_cache()
113
+ gc.collect()
114
+
115
+ def create_structured_script(self, original: str) -> Dict[str, Any]:
116
+ """Create structured script data from user input"""
117
+
118
+ # Extract key elements from the script
119
+ words = original.lower().split()
120
+
121
+ # Determine main character and setting
122
+ if any(word in words for word in ['boy', 'man', 'hero', 'prince', 'knight']):
123
+ main_char = "brave young hero"
124
+ elif any(word in words for word in ['girl', 'woman', 'princess', 'heroine']):
125
+ main_char = "brave young heroine"
126
+ elif any(word in words for word in ['robot', 'android', 'machine']):
127
+ main_char = "friendly robot"
128
+ elif any(word in words for word in ['animal', 'cat', 'dog', 'fox']):
129
+ main_char = "cute animal character"
130
+ else:
131
+ main_char = "friendly protagonist"
132
+
133
+ # Determine setting
134
+ if any(word in words for word in ['forest', 'woods', 'trees', 'jungle']):
135
+ setting = "magical forest"
136
+ elif any(word in words for word in ['city', 'town', 'urban', 'street']):
137
+ setting = "bustling city"
138
+ elif any(word in words for word in ['space', 'stars', 'planet', 'galaxy']):
139
+ setting = "cosmic space adventure"
140
+ elif any(word in words for word in ['ocean', 'sea', 'underwater', 'beach']):
141
+ setting = "underwater world"
142
+ elif any(word in words for word in ['mountain', 'cave', 'valley']):
143
+ setting = "mountain landscape"
144
+ else:
145
+ setting = "colorful fantasy world"
146
+
147
+ # Determine story theme
148
+ if any(word in words for word in ['treasure', 'gold', 'find', 'search']):
149
+ theme = "treasure hunting adventure"
150
+ elif any(word in words for word in ['friend', 'friendship', 'help', 'together']):
151
+ theme = "friendship and teamwork"
152
+ elif any(word in words for word in ['magic', 'magical', 'spell', 'wizard']):
153
+ theme = "magical discovery"
154
+ elif any(word in words for word in ['save', 'rescue', 'danger', 'protect']):
155
+ theme = "heroic rescue mission"
156
+ else:
157
+ theme = "exciting adventure"
158
+
159
+ # Create 6 scenes for faster processing
160
+ scenes = []
161
+ scene_templates = [
162
+ f"Introduction - Meet our {main_char} in the {setting}",
163
+ f"Discovery - {main_char} discovers the {theme}",
164
+ f"Journey begins - Starting the adventure in {setting}",
165
+ f"Challenge - Facing obstacles during the {theme}",
166
+ f"Resolution - {main_char} succeeds in the {theme}",
167
+ f"Celebration - Happy ending in the {setting}"
168
+ ]
169
+
170
+ for i, template in enumerate(scene_templates):
171
+ scenes.append({
172
+ "scene_number": i + 1,
173
+ "description": template,
174
+ "characters_present": [main_char] if i % 2 == 0 else [main_char, "supporting friend"],
175
+ "dialogue": [
176
+ {"character": main_char, "text": f"This is an exciting moment in scene {i+1}!"}
177
+ ],
178
+ "background": f"{setting} with {['morning', 'day', 'afternoon', 'evening', 'sunset', 'twilight'][i]} lighting",
179
+ "mood": ["cheerful", "curious", "adventurous", "determined", "triumphant", "joyful"][i],
180
+ "duration": "25" # Shorter scenes
181
+ })
182
+
183
+ return {
184
+ "title": f"The {theme.title()} of the {main_char.title()}",
185
+ "characters": [
186
+ {
187
+ "name": main_char,
188
+ "description": f"Cartoon-style {main_char} with big expressive eyes, bright colorful outfit, friendly smile, 2D animation style",
189
+ "personality": "brave, kind, determined, adventurous"
190
+ },
191
+ {
192
+ "name": "supporting friend",
193
+ "description": "Helpful cartoon companion with warm bright colors, friendly appearance, loyal sidekick, 2D animation style",
194
+ "personality": "loyal, wise, encouraging, funny"
195
+ }
196
+ ],
197
+ "scenes": scenes,
198
+ "setting": setting,
199
+ "theme": theme,
200
+ "style": "Bright and colorful 2D cartoon animation, family-friendly, expressive characters, Disney-Pixar inspired"
201
+ }
202
+
203
+ @spaces.GPU
204
+ def generate_character_images(self, characters: List[Dict]) -> Dict[str, str]:
205
+ """Generate character images"""
206
+ self.load_models()
207
+ character_images = {}
208
+
209
+ if not self.image_generator:
210
+ print("❌ No image generator available")
211
+ return character_images
212
+
213
+ for character in characters:
214
+ prompt = f"cartoon character design, {character['description']}, character sheet, multiple poses, white background, 2D animation style, high quality, colorful, Disney style"
215
+ negative_prompt = "realistic, 3D render, dark, scary, blurry, low quality, inappropriate"
216
+
217
+ try:
218
+ print(f"🎨 Generating character: {character['name']}")
219
+ image = self.image_generator(
220
+ prompt=prompt,
221
+ negative_prompt=negative_prompt,
222
+ num_inference_steps=20,
223
+ guidance_scale=7.5,
224
+ height=512,
225
+ width=512
226
+ ).images[0]
227
+
228
+ char_path = f"{self.temp_dir}/character_{character['name'].replace(' ', '_')}.png"
229
+ image.save(char_path)
230
+ character_images[character['name']] = char_path
231
+ print(f"βœ… Generated character: {character['name']}")
232
+
233
+ self.clear_gpu_memory()
234
+
235
+ except Exception as e:
236
+ print(f"❌ Error generating character {character['name']}: {e}")
237
+
238
+ return character_images
239
+
240
+ @spaces.GPU
241
+ def generate_background_images(self, scenes: List[Dict]) -> Dict[int, str]:
242
+ """Generate background images for each scene"""
243
+ self.load_models()
244
+ background_images = {}
245
+
246
+ if not self.image_generator:
247
+ print("❌ No image generator available")
248
+ return background_images
249
+
250
+ for scene in scenes:
251
+ prompt = f"cartoon background scene, {scene['background']}, {scene['mood']} atmosphere, no characters, detailed environment, bright vibrant colors, 2D animation style, Disney background art"
252
+ negative_prompt = "characters, people, realistic, dark, scary, low quality, blurry"
253
+
254
+ try:
255
+ print(f"πŸ–ΌοΈ Generating background for scene {scene['scene_number']}")
256
+ image = self.image_generator(
257
+ prompt=prompt,
258
+ negative_prompt=negative_prompt,
259
+ num_inference_steps=18,
260
+ guidance_scale=7.0,
261
+ height=384, # 16:10 aspect ratio
262
+ width=640
263
+ ).images[0]
264
+
265
+ bg_path = f"{self.temp_dir}/background_scene_{scene['scene_number']}.png"
266
+ image.save(bg_path)
267
+ background_images[scene['scene_number']] = bg_path
268
+ print(f"βœ… Generated background for scene {scene['scene_number']}")
269
+
270
+ self.clear_gpu_memory()
271
+
272
+ except Exception as e:
273
+ print(f"❌ Error generating background for scene {scene['scene_number']}: {e}")
274
+
275
+ return background_images
276
+
277
+ @spaces.GPU
278
+ def generate_scene_videos(self, scenes: List[Dict], character_images: Dict, background_images: Dict) -> List[str]:
279
+ """Generate videos for each scene"""
280
+ self.load_models()
281
+ scene_videos = []
282
+
283
+ for scene in scenes:
284
+ try:
285
+ if self.video_generator:
286
+ print(f"🎬 Generating video for scene {scene['scene_number']}")
287
+
288
+ # Create prompt for scene animation
289
+ characters_text = ", ".join(scene['characters_present'])
290
+ prompt = f"cartoon animation, {characters_text} in {scene['background']}, {scene['mood']} mood, 2D animated style, smooth gentle motion, Disney animation, family friendly"
291
+ negative_prompt = "realistic, 3D, static, blurry, low quality, scary, violent"
292
+
293
+ # Generate animated video
294
+ video_frames = self.video_generator(
295
+ prompt=prompt,
296
+ negative_prompt=negative_prompt,
297
+ num_frames=8, # Short clips for memory efficiency
298
+ guidance_scale=7.5,
299
+ num_inference_steps=12, # Reduced steps for speed
300
+ height=384,
301
+ width=640
302
+ ).frames[0]
303
+
304
+ # Save video
305
+ video_path = f"{self.temp_dir}/scene_{scene['scene_number']}.mp4"
306
+ export_to_video(video_frames, video_path, fps=4) # Slow FPS for smooth motion
307
+ scene_videos.append(video_path)
308
+ print(f"βœ… Generated video for scene {scene['scene_number']}")
309
+
310
+ self.clear_gpu_memory()
311
+
312
+ else:
313
+ # Fallback: create static video with effects
314
+ if scene['scene_number'] in background_images:
315
+ print(f"πŸ“Ή Creating static video for scene {scene['scene_number']}")
316
+ video_path = self.create_enhanced_static_video(
317
+ Image.open(background_images[scene['scene_number']]),
318
+ int(scene.get('duration', 25)),
319
+ scene['scene_number'],
320
+ scene['mood']
321
+ )
322
+ if video_path:
323
+ scene_videos.append(video_path)
324
+ print(f"βœ… Created static video for scene {scene['scene_number']}")
325
+
326
+ except Exception as e:
327
+ print(f"❌ Error in scene {scene['scene_number']}: {e}")
328
+ # Create simple fallback video
329
+ if scene['scene_number'] in background_images:
330
+ try:
331
+ video_path = self.create_simple_static_video(
332
+ Image.open(background_images[scene['scene_number']]),
333
+ int(scene.get('duration', 25)),
334
+ scene['scene_number']
335
+ )
336
+ if video_path:
337
+ scene_videos.append(video_path)
338
+ print(f"βœ… Created fallback video for scene {scene['scene_number']}")
339
+ except Exception as e2:
340
+ print(f"οΏ½οΏ½οΏ½ Fallback video failed: {e2}")
341
+
342
+ return scene_videos
343
+
344
+ def create_enhanced_static_video(self, image: Image.Image, duration: int, scene_num: int, mood: str) -> str:
345
+ """Create enhanced static video with mood-based effects"""
346
+ video_path = f"{self.temp_dir}/scene_{scene_num}.mp4"
347
+
348
+ try:
349
+ # Convert PIL to OpenCV
350
+ img_array = np.array(image.resize((640, 384)))
351
+ img_array = cv2.cvtColor(img_array, cv2.COLOR_RGB2BGR)
352
+
353
+ # Create video writer
354
+ fourcc = cv2.VideoWriter_fourcc(*'mp4v')
355
+ fps = 12
356
+ out = cv2.VideoWriter(video_path, fourcc, fps, (640, 384))
357
+
358
+ total_frames = duration * fps
359
+
360
+ for i in range(total_frames):
361
+ frame = img_array.copy()
362
+ progress = i / total_frames
363
+
364
+ # Apply mood-based effects
365
+ if mood in ['cheerful', 'joyful']:
366
+ # Gentle zoom in
367
+ scale = 1.0 + progress * 0.05
368
+ elif mood in ['adventurous', 'determined']:
369
+ # Slight pan effect
370
+ shift_x = int(np.sin(progress * 2 * np.pi) * 10)
371
+ M = np.float32([[1, 0, shift_x], [0, 1, 0]])
372
+ frame = cv2.warpAffine(frame, M, (640, 384))
373
+ scale = 1.0
374
+ elif mood in ['curious']:
375
+ # Zoom out slightly
376
+ scale = 1.05 - progress * 0.03
377
+ else:
378
+ # Default gentle zoom
379
+ scale = 1.0 + progress * 0.02
380
+
381
+ # Apply scaling
382
+ if scale != 1.0:
383
+ h, w = frame.shape[:2]
384
+ center_x, center_y = w // 2, h // 2
385
+ M = cv2.getRotationMatrix2D((center_x, center_y), 0, scale)
386
+ frame = cv2.warpAffine(frame, M, (w, h))
387
+
388
+ out.write(frame)
389
+
390
+ out.release()
391
+ return video_path
392
+
393
+ except Exception as e:
394
+ print(f"❌ Enhanced static video creation failed: {e}")
395
+ return None
396
+
397
+ def create_simple_static_video(self, image: Image.Image, duration: int, scene_num: int) -> str:
398
+ """Create simple static video as fallback"""
399
+ video_path = f"{self.temp_dir}/scene_{scene_num}.mp4"
400
+
401
+ try:
402
+ img_array = np.array(image.resize((640, 384)))
403
+ img_array = cv2.cvtColor(img_array, cv2.COLOR_RGB2BGR)
404
+
405
+ fourcc = cv2.VideoWriter_fourcc(*'mp4v')
406
+ fps = 12
407
+ out = cv2.VideoWriter(video_path, fourcc, fps, (640, 384))
408
+
409
+ # Simple static video
410
+ for _ in range(duration * fps):
411
+ out.write(img_array)
412
+
413
+ out.release()
414
+ return video_path
415
+
416
+ except Exception as e:
417
+ print(f"❌ Simple static video creation failed: {e}")
418
+ return None
419
+
420
+ def merge_videos_with_ffmpeg(self, scene_videos: List[str]) -> str:
421
+ """Merge videos using ffmpeg"""
422
+ if not scene_videos:
423
+ print("❌ No videos to merge")
424
+ return None
425
+
426
+ final_video_path = f"{self.temp_dir}/final_cartoon_film.mp4"
427
+
428
+ try:
429
+ print("🎞️ Merging videos...")
430
+
431
+ # Create concat file
432
+ concat_file = f"{self.temp_dir}/concat_list.txt"
433
+ with open(concat_file, 'w') as f:
434
+ for video in scene_videos:
435
+ if os.path.exists(video):
436
+ f.write(f"file '{os.path.abspath(video)}'\n")
437
+
438
+ # Merge videos
439
+ cmd = [
440
+ 'ffmpeg', '-f', 'concat', '-safe', '0', '-i', concat_file,
441
+ '-c:v', 'libx264', '-preset', 'fast', '-crf', '23',
442
+ '-y', final_video_path
443
+ ]
444
+
445
+ result = subprocess.run(cmd, capture_output=True, text=True)
446
+ if result.returncode == 0:
447
+ print("βœ… Video merging successful")
448
+ return final_video_path
449
+ else:
450
+ print(f"❌ FFmpeg error: {result.stderr}")
451
+ return None
452
+
453
+ except Exception as e:
454
+ print(f"❌ Video merging failed: {e}")
455
+ return None
456
+
457
+ @spaces.GPU
458
+ def generate_cartoon_film(self, script: str) -> tuple:
459
+ """Main function to generate complete cartoon film"""
460
+ try:
461
+ print("🎬 Starting cartoon film generation...")
462
+
463
+ # Step 1: Process script
464
+ print("πŸ“ Creating story structure...")
465
+ processed_script = self.create_structured_script(script)
466
+
467
+ # Step 2: Generate characters
468
+ print("πŸ‘₯ Creating character designs...")
469
+ character_images = self.generate_character_images(processed_script['characters'])
470
+
471
+ # Step 3: Generate backgrounds
472
+ print("🏞️ Creating scene backgrounds...")
473
+ background_images = self.generate_background_images(processed_script['scenes'])
474
+
475
+ # Step 4: Generate scene videos
476
+ print("πŸŽ₯ Creating animated scenes...")
477
+ scene_videos = self.generate_scene_videos(
478
+ processed_script['scenes'],
479
+ character_images,
480
+ background_images
481
+ )
482
+
483
+ # Step 5: Merge final video
484
+ print("🎞️ Creating final film...")
485
+ final_video = self.merge_videos_with_ffmpeg(scene_videos)
486
+
487
+ if final_video and os.path.exists(final_video):
488
+ print("βœ… Cartoon film generation complete!")
489
+ return final_video, processed_script, "βœ… Cartoon film generated successfully!"
490
+ else:
491
+ print("⚠️ Partial success - some components may be missing")
492
+ return None, processed_script, "⚠️ Generation completed with some issues"
493
+
494
+ except Exception as e:
495
+ print(f"❌ Generation failed: {e}")
496
+ error_info = {
497
+ "error": True,
498
+ "message": str(e),
499
+ "characters": [],
500
+ "scenes": [],
501
+ "style": "Error occurred during generation"
502
+ }
503
+ return None, error_info, f"❌ Generation failed: {str(e)}"
504
+
505
+ # Initialize generator
506
+ generator = CartoonFilmGenerator()
507
+
508
+ @spaces.GPU
509
+ def create_cartoon_film(script):
510
+ """Gradio interface function"""
511
+ if not script.strip():
512
+ empty_response = {
513
+ "error": True,
514
+ "message": "No script provided",
515
+ "characters": [],
516
+ "scenes": [],
517
+ "style": "Please enter a script"
518
+ }
519
+ return None, empty_response, "❌ Please enter a script"
520
+
521
+ return generator.generate_cartoon_film(script)
522
+
523
+ # Gradio Interface
524
+ with gr.Blocks(
525
+ title="🎬 AI Cartoon Film Generator",
526
+ theme=gr.themes.Soft(),
527
+ css="""
528
+ .gradio-container {
529
+ max-width: 1200px !important;
530
+ }
531
+ """
532
+ ) as demo:
533
+
534
+ gr.Markdown("""
535
+ # 🎬 AI Cartoon Film Generator (Optimized & Fixed)
536
+
537
+ Transform your script into a complete cartoon film using stable open-source models!
538
+
539
+ **πŸ”₯ Features:**
540
+ - **Stable Diffusion 1.5** for reliable image generation
541
+ - **AnimateDiff** for smooth video animation (when available)
542
+ - **Enhanced static videos** with mood-based effects as fallback
543
+ - **6 scenes** for optimal processing time (2.5 minutes total)
544
+ - **ZeroGPU optimized** with robust error handling
545
+
546
+ **βœ… Fixed Issues:**
547
+ - Removed problematic TTS model
548
+ - Updated MotionAdapter configuration
549
+ - Better memory management
550
+ - Stable fallback options
551
+ """)
552
+
553
+ with gr.Row():
554
+ with gr.Column(scale=1):
555
+ script_input = gr.Textbox(
556
+ label="πŸ“ Your Story Script",
557
+ placeholder="Enter your story idea! Examples:\n\nβ€’ A brave explorer finds a magical forest\nβ€’ A robot learns about friendship in the city\nβ€’ Two friends help an alien return home\nβ€’ A young artist's drawings come to life",
558
+ lines=6,
559
+ max_lines=10
560
+ )
561
+
562
+ generate_btn = gr.Button(
563
+ "🎬 Generate Cartoon Film",
564
+ variant="primary",
565
+ size="lg"
566
+ )
567
+
568
+ gr.Markdown("""
569
+ **⏱️ Processing Time:** 3-5 minutes
570
+ **πŸŽ₯ Output:** 2.5 minute MP4 film (6 scenes)
571
+ **πŸ“± Models:** SD 1.5 + AnimateDiff + Enhanced Effects
572
+ """)
573
+
574
+ with gr.Column(scale=1):
575
+ video_output = gr.Video(
576
+ label="🎬 Generated Cartoon Film",
577
+ height=400
578
+ )
579
+
580
+ status_output = gr.Textbox(
581
+ label="πŸ“Š Generation Status",
582
+ lines=2
583
+ )
584
+
585
+ script_details = gr.JSON(
586
+ label="πŸ“‹ Story Structure",
587
+ visible=True
588
+ )
589
+
590
+ # Event handlers
591
+ generate_btn.click(
592
+ fn=create_cartoon_film,
593
+ inputs=[script_input],
594
+ outputs=[video_output, script_details, status_output],
595
+ show_progress=True
596
+ )
597
+
598
+ # Example scripts
599
+ gr.Examples(
600
+ examples=[
601
+ ["A brave young explorer discovers a magical forest where talking animals help find a lost treasure."],
602
+ ["Two best friends go on a space adventure to help a friendly alien return to its home planet."],
603
+ ["A small robot in a big city learns about emotions and friendship from a lonely child."],
604
+ ["A young artist discovers that their drawings come to life and need help solving magical problems."],
605
+ ["A curious cat and clever mouse team up to save their neighborhood from a mischievous wizard."],
606
+ ["A kind-hearted dragon who just wants to make friends learns to overcome fear and prejudice."]
607
+ ],
608
+ inputs=[script_input],
609
+ label="πŸ’‘ Try these example stories:"
610
+ )
611
+
612
+ gr.Markdown("""
613
+ ---
614
+ **πŸ› οΈ Technical Stack:**
615
+ - **Image Generation:** Stable Diffusion 1.5 (reliable & fast)
616
+ - **Video Animation:** AnimateDiff with DPM scheduler
617
+ - **Fallback Effects:** Enhanced static videos with mood-based animation
618
+ - **Memory Management:** Optimized for ZeroGPU constraints
619
+ - **Error Handling:** Robust fallbacks at every step
620
+
621
+ **πŸ’‘ Tips for best results:**
622
+ - Keep scripts simple and clear
623
+ - Include character types (hero, robot, animal, etc.)
624
+ - Mention the setting (forest, city, space, etc.)
625
+ - Add emotion words (brave, curious, friendly, etc.)
626
+ """)
627
+
628
+ if __name__ == "__main__":
629
+ demo.queue(max_size=3).launch()