Anonymusmee commited on
Commit
af0b5a4
·
verified ·
1 Parent(s): fb283b1

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +198 -0
app.py ADDED
@@ -0,0 +1,198 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from PIL import Image, ImageDraw
3
+ import numpy as np
4
+ import imageio
5
+ import tempfile
6
+ from gtts import gTTS
7
+ import torch
8
+ from diffusers import DiffusionPipeline, DPMSolverMultistepScheduler
9
+
10
+ # ========== AI MODEL SETUP (Done once on startup) ==========
11
+ # This part loads the AI model that creates the videos.
12
+ try:
13
+ device = "cuda" if torch.cuda.is_available() else "cpu"
14
+ video_pipe = DiffusionPipeline.from_pretrained(
15
+ "cerspense/zeroscope_v2_576w",
16
+ torch_dtype=torch.float16
17
+ )
18
+ video_pipe.scheduler = DPMSolverMultistepScheduler.from_config(video_pipe.scheduler.config)
19
+ video_pipe.to(device)
20
+ model_loaded = True
21
+ except Exception as e:
22
+ print(f"Error loading model: {e}")
23
+ model_loaded = False
24
+
25
+ # ========== UI & STYLING ==========
26
+ # This is where we design the beautiful, child-friendly interface!
27
+ custom_css = """
28
+ /* --- Import a fun, rounded font from Google Fonts --- */
29
+ @import url('https://fonts.googleapis.com/css2?family=Mali:wght@400;700&display=swap');
30
+
31
+ /* --- Overall page style --- */
32
+ .gradio-container {
33
+ background: linear-gradient(135deg, #a0c4ff 0%, #c4f5ff 100%); /* Sky blue gradient */
34
+ font-family: 'Mali', cursive; /* Use our fun, new font */
35
+ }
36
+
37
+ /* --- Main Title: Big, colorful, and magical! --- */
38
+ #main-title {
39
+ font-size: 48px;
40
+ font-weight: 700;
41
+ color: #ff6b6b; /* Playful coral color */
42
+ text-align: center;
43
+ text-shadow: 2px 2px 4px rgba(0,0,0,0.2);
44
+ padding-top: 20px;
45
+ }
46
+
47
+ #subtitle {
48
+ font-size: 24px;
49
+ color: #4a4a4a;
50
+ text-align: center;
51
+ margin-top: -10px;
52
+ }
53
+
54
+ /* --- The main button: Looks like a magic wand button! --- */
55
+ #animate-btn {
56
+ background: linear-gradient(45deg, #ffd700, #ff8c00); /* Golden-orange gradient */
57
+ color: white;
58
+ border: none;
59
+ border-radius: 50px; /* Fully rounded */
60
+ padding: 15px 30px;
61
+ font-size: 22px;
62
+ font-weight: bold;
63
+ box-shadow: 0 5px 15px rgba(255, 165, 0, 0.4);
64
+ transition: transform 0.2s, box-shadow 0.2s;
65
+ }
66
+ #animate-btn:hover {
67
+ transform: scale(1.05); /* Grow on hover */
68
+ box-shadow: 0 8px 20px rgba(255, 165, 0, 0.6);
69
+ }
70
+
71
+ /* --- Text input box: Looks like a story scroll --- */
72
+ #story-input textarea {
73
+ background-color: #ffffff;
74
+ border: 3px solid #ffca7a; /* Warm, friendly border */
75
+ border-radius: 15px;
76
+ font-size: 18px;
77
+ padding: 15px;
78
+ line-height: 1.5;
79
+ }
80
+
81
+ /* --- Output containers: Framed like a picture book --- */
82
+ .output-box {
83
+ border: 8px solid #8B4513; /* Wooden frame border */
84
+ border-image: url('https://www.publicdomainpictures.net/pictures/120000/velka/wooden-frame-texture.jpg') 20 stretch;
85
+ border-radius: 15px;
86
+ padding: 10px;
87
+ background: #fdf6e3; /* Parchment paper background */
88
+ box-shadow: 5px 5px 15px rgba(0,0,0,0.3);
89
+ }
90
+
91
+ /* --- Explainer character image: A friendly round guide --- */
92
+ .explainer-img img {
93
+ border-radius: 50% !important;
94
+ border: 5px solid #ff6b6b;
95
+ object-fit: cover;
96
+ }
97
+ """
98
+
99
+ # ========== BACKEND LOGIC (The "How it Works" part) ==========
100
+
101
+ def create_animation(story):
102
+ """Takes the story and creates the video."""
103
+ if not model_loaded:
104
+ # Create a dummy error output if the model failed to load
105
+ blank_image = np.zeros((320, 576, 3), dtype=np.uint8)
106
+ with tempfile.NamedTemporaryFile(suffix=".mp4", delete=False) as temp_file:
107
+ imageio.mimsave(temp_file.name, [blank_image for _ in range(3)], fps=3)
108
+ return "AI model not loaded.", "Error: AI model failed to load.", blank_image, temp_file.name
109
+
110
+ if not story:
111
+ return "Please write a story first!", "", np.zeros((320, 576, 3), dtype=np.uint8), None
112
+
113
+ prompt = f"{story.strip()}, beautiful animation, storybook style, vibrant colors, for children"
114
+
115
+ # Generate the video
116
+ video_frames = video_pipe(prompt, num_inference_steps=25, height=320, width=576, num_frames=24).frames
117
+
118
+ with tempfile.NamedTemporaryFile(suffix=".mp4", delete=False) as temp_file:
119
+ video_path = temp_file.name
120
+ imageio.mimsave(video_path, video_frames, fps=12)
121
+
122
+ final_frame_image = video_frames[-1]
123
+
124
+ code_explanation = f"""
125
+ ### 📜 The Magic Spell (Prompt) We Used:
126
+ The AI was told to create a video based on this magic spell:
127
+ **"{prompt}"**
128
+ """
129
+
130
+ story_explanation = f"Hooray! ✨ Our AI artist read your story about '{story}' and drew this wonderful movie for you!"
131
+
132
+ # Generate audio
133
+ with tempfile.NamedTemporaryFile(suffix=".mp3", delete=False) as temp_audio:
134
+ tts = gTTS(story_explanation, lang='en')
135
+ tts.save(temp_audio.name)
136
+ audio_path = temp_audio.name
137
+
138
+ return story_explanation, audio_path, code_explanation, final_frame_image, video_path
139
+
140
+ # ========== THE GRADIO APP INTERFACE ==========
141
+
142
+ with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as app:
143
+ gr.Markdown("# 🏰 Storybook Animator 🏰", elem_id="main-title")
144
+ gr.Markdown("Let's bring your imagination to life!", elem_id="subtitle")
145
+
146
+ with gr.Row():
147
+ # --- LEFT SIDE: INPUT ---
148
+ with gr.Column(scale=2):
149
+ gr.Markdown("### ✍️ Write Your Magical Story Here:")
150
+ story_input = gr.Textbox(
151
+ label="Story",
152
+ placeholder="A happy little fox making friends with a butterfly...",
153
+ lines=5,
154
+ elem_id="story-input",
155
+ show_label=False
156
+ )
157
+ animate_btn = gr.Button("✨ Create My Animation! ✨", elem_id="animate-btn")
158
+
159
+ gr.Examples(
160
+ examples=[
161
+ ["A friendly dragon flying over a candy castle."],
162
+ ["A little robot planting a flower on the moon."],
163
+ ["A curious squirrel having a tea party with a gnome."],
164
+ ["A mermaid discovering a sunken treasure chest filled with glowing pearls."]
165
+ ],
166
+ inputs=story_input,
167
+ label="🌟 Or Try These Fun Ideas:"
168
+ )
169
+
170
+ # --- RIGHT SIDE: OUTPUT ---
171
+ with gr.Column(scale=3):
172
+ with gr.Tabs():
173
+ with gr.TabItem("🎬 Your Movie!"):
174
+ output_video = gr.Video(label="Your Story Comes Alive", elem_classes="output-box")
175
+
176
+ with gr.TabItem("🖼️ Picture Preview"):
177
+ output_image = gr.Image(label="A Snapshot from Your Story", elem_classes="output-box")
178
+
179
+ with gr.TabItem("💡 How It Works"):
180
+ story_explanation_text = gr.Textbox(label="What Happened", interactive=False, elem_classes="output-box")
181
+ explainer_audio = gr.Audio(label="Listen to the Story", type="filepath")
182
+ code_explanation_output = gr.Markdown(elem_classes="output-box")
183
+
184
+ # --- Connect the button to the function ---
185
+ animate_btn.click(
186
+ fn=create_animation,
187
+ inputs=story_input,
188
+ outputs=[
189
+ story_explanation_text,
190
+ explainer_audio,
191
+ code_explanation_output,
192
+ output_image,
193
+ output_video
194
+ ]
195
+ )
196
+
197
+ if __name__ == "__main__":
198
+ app.launch()