Vo Hoang Minh commited on
Commit
a109271
Β·
1 Parent(s): 65082b7
Files changed (1) hide show
  1. app.py +164 -164
app.py CHANGED
@@ -124,182 +124,182 @@ for template in motion.templates:
124
  tag_choices = ["all"] + sorted(list(all_tags))
125
 
126
  # Interface
127
- app = gr.Blocks(title="Ken Burns Story Creator", css="""
128
  .gradio-container {max-width: 1400px !important}
129
  .compact-group {margin: 5px 0 !important}
130
- """)
131
- gr.Markdown("# 🎬 Ken Burns Story Creator\nCreate motion videos for YouTube, TikTok, Reels with 30+ effects")
132
-
133
- with gr.Tabs():
134
- with gr.Tab("πŸ“Ή Create Video"):
135
- with gr.Row():
136
- with gr.Column(scale=2):
137
- # Input
138
- files_input = gr.File(label="Upload Images/Videos", file_count="multiple",
139
- file_types=["image", "video"])
140
-
141
- # Preview
142
- with gr.Group():
143
- gr.Markdown("### Preview")
144
- preview_img = gr.Image(label="Files Preview", height=200)
145
- preview_info = gr.Textbox(label="Info", interactive=False)
146
-
147
- # Effect Selection
148
- with gr.Group():
149
- gr.Markdown("### 🎭 Effect Selection")
150
 
151
- with gr.Row():
152
- use_random = gr.Checkbox(label="Random Effects", value=True)
 
 
 
 
 
 
 
153
 
154
- with gr.Column(visible=False) as effect_selector:
155
  with gr.Row():
156
- tag_filter = gr.Dropdown(
157
- choices=tag_choices, value="all",
158
- label="Filter by Tag", scale=1
 
 
 
 
 
 
 
 
 
 
 
 
159
  )
160
- search_box = gr.Textbox(
161
- label="Search Effects", placeholder="zoom, pan, dramatic...", scale=2
162
- )
163
-
164
- template_dropdown = gr.Dropdown(
165
- choices=[f"{t['name']} ({', '.join(t.get('tags', []))})" for t in motion.templates],
166
- label="Select Effect"
167
  )
 
168
 
169
- # Settings
170
- with gr.Row():
171
- aspect_ratio = gr.Dropdown(
172
- choices=['reels', 'tiktok', 'youtube', 'square', 'widescreen'],
173
- value='reels',
174
- label="πŸ“± Platform"
175
- )
176
- output_format = gr.Radio(['mp4', 'gif'], value='mp4', label="Format")
177
-
178
- with gr.Column(scale=1):
179
- # Test Effect
180
- with gr.Group():
181
- gr.Markdown("### πŸ§ͺ Test Effect")
182
- test_file = gr.File(label="Test Image", file_types=["image"])
183
- test_btn = gr.Button("🎬 Test Effect", size="sm")
184
- test_result = gr.Video(label="Test Result", height=200)
185
- test_status = gr.Textbox(label="Test Status", interactive=False)
186
-
187
- # Create Video
188
- create_btn = gr.Button("πŸš€ Create Story", variant="primary", size="lg")
189
- status = gr.Textbox(label="Status", interactive=False)
190
- output_video = gr.Video(label="Result", height=300)
191
- download_btn = gr.DownloadButton(label="πŸ“₯ Download", visible=False)
192
-
193
- with gr.Tab("βš™οΈ Advanced Settings"):
194
- gr.Markdown("### Advanced Processing Settings")
195
-
196
- with gr.Row():
197
- workers = gr.Slider(1, 8, value=4, step=1, label="πŸ”„ Parallel Workers")
198
- fps = gr.Slider(15, 60, value=25, step=5, label="🎞️ FPS")
199
-
200
- with gr.Row():
201
- quality = gr.Dropdown(
202
- choices=['ultrafast', 'superfast', 'veryfast', 'faster', 'fast', 'medium', 'slow'],
203
- value='fast',
204
- label="πŸ† Quality Preset"
205
- )
206
-
207
- with gr.Tab("🎭 Templates"):
208
- gr.Markdown("### Motion Templates Manager")
209
 
210
- with gr.Row():
211
- with gr.Column(scale=2):
212
- template_dropdown_edit = gr.Dropdown(
213
- choices=[f"{t['name']} ({', '.join(t.get('tags', []))})" for t in motion.templates],
214
- value=f"{motion.templates[0]['name']} ({', '.join(motion.templates[0].get('tags', []))})",
215
- label="Template"
216
- )
217
-
218
- with gr.Row():
219
- name_input = gr.Textbox(label="Name", placeholder="template_name")
220
- duration_input = gr.Number(label="Duration (s)", value=4, minimum=2, maximum=10)
221
-
222
- with gr.Row():
223
- scale_start = gr.Number(label="Scale Start", value=1.0, step=0.1)
224
- scale_end = gr.Number(label="Scale End", value=1.3, step=0.1)
225
-
226
- with gr.Row():
227
- x1 = gr.Number(label="Pan X1", value=0)
228
- y1 = gr.Number(label="Pan Y1", value=0)
229
- x2 = gr.Number(label="Pan X2", value=0)
230
- y2 = gr.Number(label="Pan Y2", value=0)
231
-
232
- with gr.Row():
233
- rot_start = gr.Number(label="Rotate Start (Β°)", value=0)
234
- rot_end = gr.Number(label="Rotate End (Β°)", value=0)
235
-
236
- tags_input = gr.Textbox(
237
- label="Tags (comma separated)",
238
- placeholder="zoom, left, dramatic",
239
- value=""
240
- )
241
-
242
- desc_input = gr.Textbox(
243
- label="Description",
244
- placeholder="Describe the motion effect...",
245
- lines=2
246
  )
247
-
248
- save_btn = gr.Button("πŸ’Ύ Save Template", variant="primary")
249
- template_status = gr.Textbox(label="Status", interactive=False)
250
 
251
- with gr.Column(scale=1):
252
- gr.Markdown("### πŸ“‹ Available Tags")
253
- gr.Markdown(f"**{len(tag_choices)-1} unique tags:**")
254
- gr.Markdown(", ".join(sorted(tag_choices[1:]))) # Exclude "all"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
255
 
256
- gr.Markdown("### πŸ“– Template Guide")
257
- gr.Markdown("""
258
- **Scale**: Zoom level (1.0 = normal)
259
- **Pan X1,Y1**: Start position
260
- **Pan X2,Y2**: End position
261
- **Duration**: Effect length in seconds
262
- **Tags**: For easy searching
263
- """)
264
-
265
- with gr.Tab("ℹ️ Help"):
266
- gr.Markdown(f"""
267
- ### πŸ“– How to Use
268
- 1. **Upload** your images/videos
269
- 2. **Choose effects**: Random or specific template
270
- 3. **Test effects** on single image first
271
- 4. **Select platform** aspect ratio
272
- 5. **Create** your story video
273
-
274
- ### 🎭 Available Effects ({len(motion.templates)} total)
275
-
276
- **Zoom Effects:**
277
- - Center zoom in/out
278
- - Directional zooms (left, right, top, bottom)
279
- - Dramatic push/pull effects
280
-
281
- **Pan Effects:**
282
- - Horizontal/vertical pans
283
- - Diagonal movements
284
- - Arc and spiral motions
285
-
286
- **Cinematic Effects:**
287
- - Slow drifts and breathing
288
- - Focus shifts and reveals
289
- - Documentary style movements
290
-
291
- ### πŸ“± Platform Settings
292
- - **Reels/TikTok**: 9:16 (1080x1920)
293
- - **YouTube**: 16:9 (1920x1080)
294
- - **Square**: 1:1 (1080x1080)
295
 
296
- ### βš™οΈ Advanced Settings
297
- - **Workers**: Parallel processing (more = faster)
298
- - **Quality**: FFmpeg preset (fast vs quality)
299
- - **FPS**: Frame rate (higher = smoother)
300
- """)
301
-
302
- # Events
303
- files_input.change(preview_files, [files_input], [preview_img, preview_info])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
304
 
305
  app.launch()
 
124
  tag_choices = ["all"] + sorted(list(all_tags))
125
 
126
  # Interface
127
+ with gr.Blocks(title="Ken Burns Story Creator", css="""
128
  .gradio-container {max-width: 1400px !important}
129
  .compact-group {margin: 5px 0 !important}
130
+ """) as app:
131
+ gr.Markdown("# 🎬 Ken Burns Story Creator\nCreate motion videos for YouTube, TikTok, Reels with 30+ effects")
132
+
133
+ with gr.Tabs():
134
+ with gr.Tab("πŸ“Ή Create Video"):
135
+ with gr.Row():
136
+ with gr.Column(scale=2):
137
+ # Input
138
+ files_input = gr.File(label="Upload Images/Videos", file_count="multiple",
139
+ file_types=["image", "video"])
 
 
 
 
 
 
 
 
 
 
140
 
141
+ # Preview
142
+ with gr.Group():
143
+ gr.Markdown("### Preview")
144
+ preview_img = gr.Image(label="Files Preview", height=200)
145
+ preview_info = gr.Textbox(label="Info", interactive=False)
146
+
147
+ # Effect Selection
148
+ with gr.Group():
149
+ gr.Markdown("### 🎭 Effect Selection")
150
 
 
151
  with gr.Row():
152
+ use_random = gr.Checkbox(label="Random Effects", value=True)
153
+
154
+ with gr.Column(visible=False) as effect_selector:
155
+ with gr.Row():
156
+ tag_filter = gr.Dropdown(
157
+ choices=tag_choices, value="all",
158
+ label="Filter by Tag", scale=1
159
+ )
160
+ search_box = gr.Textbox(
161
+ label="Search Effects", placeholder="zoom, pan, dramatic...", scale=2
162
+ )
163
+
164
+ template_dropdown = gr.Dropdown(
165
+ choices=[f"{t['name']} ({', '.join(t.get('tags', []))})" for t in motion.templates],
166
+ label="Select Effect"
167
  )
168
+
169
+ # Settings
170
+ with gr.Row():
171
+ aspect_ratio = gr.Dropdown(
172
+ choices=['reels', 'tiktok', 'youtube', 'square', 'widescreen'],
173
+ value='reels',
174
+ label="πŸ“± Platform"
175
  )
176
+ output_format = gr.Radio(['mp4', 'gif'], value='mp4', label="Format")
177
 
178
+ with gr.Column(scale=1):
179
+ # Test Effect
180
+ with gr.Group():
181
+ gr.Markdown("### πŸ§ͺ Test Effect")
182
+ test_file = gr.File(label="Test Image", file_types=["image"])
183
+ test_btn = gr.Button("🎬 Test Effect", size="sm")
184
+ test_result = gr.Video(label="Test Result", height=200)
185
+ test_status = gr.Textbox(label="Test Status", interactive=False)
186
+
187
+ # Create Video
188
+ create_btn = gr.Button("πŸš€ Create Story", variant="primary", size="lg")
189
+ status = gr.Textbox(label="Status", interactive=False)
190
+ output_video = gr.Video(label="Result", height=300)
191
+ download_btn = gr.DownloadButton(label="πŸ“₯ Download", visible=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
192
 
193
+ with gr.Tab("βš™οΈ Advanced Settings"):
194
+ gr.Markdown("### Advanced Processing Settings")
195
+
196
+ with gr.Row():
197
+ workers = gr.Slider(1, 8, value=4, step=1, label="πŸ”„ Parallel Workers")
198
+ fps = gr.Slider(15, 60, value=25, step=5, label="🎞️ FPS")
199
+
200
+ with gr.Row():
201
+ quality = gr.Dropdown(
202
+ choices=['ultrafast', 'superfast', 'veryfast', 'faster', 'fast', 'medium', 'slow'],
203
+ value='fast',
204
+ label="πŸ† Quality Preset"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
205
  )
206
+
207
+ with gr.Tab("🎭 Templates"):
208
+ gr.Markdown("### Motion Templates Manager")
209
 
210
+ with gr.Row():
211
+ with gr.Column(scale=2):
212
+ template_dropdown_edit = gr.Dropdown(
213
+ choices=[f"{t['name']} ({', '.join(t.get('tags', []))})" for t in motion.templates],
214
+ value=f"{motion.templates[0]['name']} ({', '.join(motion.templates[0].get('tags', []))})",
215
+ label="Template"
216
+ )
217
+
218
+ with gr.Row():
219
+ name_input = gr.Textbox(label="Name", placeholder="template_name")
220
+ duration_input = gr.Number(label="Duration (s)", value=4, minimum=2, maximum=10)
221
+
222
+ with gr.Row():
223
+ scale_start = gr.Number(label="Scale Start", value=1.0, step=0.1)
224
+ scale_end = gr.Number(label="Scale End", value=1.3, step=0.1)
225
+
226
+ with gr.Row():
227
+ x1 = gr.Number(label="Pan X1", value=0)
228
+ y1 = gr.Number(label="Pan Y1", value=0)
229
+ x2 = gr.Number(label="Pan X2", value=0)
230
+ y2 = gr.Number(label="Pan Y2", value=0)
231
+
232
+ with gr.Row():
233
+ rot_start = gr.Number(label="Rotate Start (Β°)", value=0)
234
+ rot_end = gr.Number(label="Rotate End (Β°)", value=0)
235
+
236
+ tags_input = gr.Textbox(
237
+ label="Tags (comma separated)",
238
+ placeholder="zoom, left, dramatic",
239
+ value=""
240
+ )
241
+
242
+ desc_input = gr.Textbox(
243
+ label="Description",
244
+ placeholder="Describe the motion effect...",
245
+ lines=2
246
+ )
247
+
248
+ save_btn = gr.Button("πŸ’Ύ Save Template", variant="primary")
249
+ template_status = gr.Textbox(label="Status", interactive=False)
250
 
251
+ with gr.Column(scale=1):
252
+ gr.Markdown("### πŸ“‹ Available Tags")
253
+ gr.Markdown(f"**{len(tag_choices)-1} unique tags:**")
254
+ gr.Markdown(", ".join(sorted(tag_choices[1:]))) # Exclude "all"
255
+
256
+ gr.Markdown("### πŸ“– Template Guide")
257
+ gr.Markdown("""
258
+ **Scale**: Zoom level (1.0 = normal)
259
+ **Pan X1,Y1**: Start position
260
+ **Pan X2,Y2**: End position
261
+ **Duration**: Effect length in seconds
262
+ **Tags**: For easy searching
263
+ """)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
264
 
265
+ with gr.Tab("ℹ️ Help"):
266
+ gr.Markdown(f"""
267
+ ### πŸ“– How to Use
268
+ 1. **Upload** your images/videos
269
+ 2. **Choose effects**: Random or specific template
270
+ 3. **Test effects** on single image first
271
+ 4. **Select platform** aspect ratio
272
+ 5. **Create** your story video
273
+
274
+ ### 🎭 Available Effects ({len(motion.templates)} total)
275
+
276
+ **Zoom Effects:**
277
+ - Center zoom in/out
278
+ - Directional zooms (left, right, top, bottom)
279
+ - Dramatic push/pull effects
280
+
281
+ **Pan Effects:**
282
+ - Horizontal/vertical pans
283
+ - Diagonal movements
284
+ - Arc and spiral motions
285
+
286
+ **Cinematic Effects:**
287
+ - Slow drifts and breathing
288
+ - Focus shifts and reveals
289
+ - Documentary style movements
290
+
291
+ ### πŸ“± Platform Settings
292
+ - **Reels/TikTok**: 9:16 (1080x1920)
293
+ - **YouTube**: 16:9 (1920x1080)
294
+ - **Square**: 1:1 (1080x1080)
295
+
296
+ ### βš™οΈ Advanced Settings
297
+ - **Workers**: Parallel processing (more = faster)
298
+ - **Quality**: FFmpeg preset (fast vs quality)
299
+ - **FPS**: Frame rate (higher = smoother)
300
+ """)
301
+
302
+ # Events
303
+ files_input.change(preview_files, [files_input], [preview_img, preview_info])
304
 
305
  app.launch()