akhaliq HF Staff commited on
Commit
1f6e6f1
·
verified ·
1 Parent(s): 509ccc4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +255 -183
app.py CHANGED
@@ -1,11 +1,11 @@
1
  import gradio as gr
2
  import os
3
  from huggingface_hub import InferenceClient
4
- from pathlib import Path
5
  import tempfile
6
- import time
7
- from typing import Optional
8
  import shutil
 
 
 
9
 
10
  # -------------------------
11
  # Utilities
@@ -23,6 +23,15 @@ def cleanup_temp_files():
23
  except Exception as e:
24
  print(f"Cleanup error: {e}")
25
 
 
 
 
 
 
 
 
 
 
26
  def _save_bytes_as_temp_mp4(data: bytes) -> str:
27
  temp_file = tempfile.NamedTemporaryFile(suffix=".mp4", delete=False)
28
  try:
@@ -32,39 +41,63 @@ def _save_bytes_as_temp_mp4(data: bytes) -> str:
32
  finally:
33
  temp_file.close()
34
 
35
- def generate_video_with_auth(image, prompt, profile: gr.OAuthProfile | None, progress=gr.Progress()):
36
- """
37
- Generate a video from an image using the Ovi model with authentication check.
38
-
39
- Args:
40
- image: Input image (PIL Image or file path)
41
- prompt: Text prompt describing the desired motion/animation
42
- profile: OAuth profile for authentication
43
- progress: Gradio progress tracker
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
 
45
- Returns:
46
- Path to the generated video file
47
- """
 
 
 
 
48
  try:
49
- if profile is None:
50
- raise gr.Error("Please sign in with Hugging Face to continue. This app uses your inference provider credits.")
51
 
52
  if image is None:
53
- raise gr.Error("Please upload an image first!")
54
 
55
  if not prompt or prompt.strip() == "":
56
- raise gr.Error("Please enter a prompt describing the desired motion!")
57
 
58
  cleanup_temp_files()
59
 
60
- progress(0.2, desc="Processing image...")
61
-
62
  # Read the image file
63
  if isinstance(image, str):
 
64
  with open(image, "rb") as image_file:
65
  input_image = image_file.read()
66
  else:
67
- # If image is a PIL Image, save it temporarily
68
  import io
69
  from PIL import Image as PILImage
70
 
@@ -80,50 +113,39 @@ def generate_video_with_auth(image, prompt, profile: gr.OAuthProfile | None, pro
80
  pil_image.save(buffer, format='PNG')
81
  input_image = buffer.getvalue()
82
 
83
- progress(0.4, desc="Generating video with AI...")
 
84
 
85
- # Create client - use environment token if available, otherwise user's OAuth
86
- api_key = os.environ.get("HF_TOKEN")
87
- if api_key:
88
- client = InferenceClient(
89
- provider="fal-ai",
90
- api_key=api_key,
91
- bill_to="huggingface",
92
- )
93
- else:
94
- # This would require user's token from OAuth
95
- raise gr.Error("Server configuration error: HF_TOKEN not available")
96
-
97
- # Generate video using the inference client
98
  try:
99
  video = client.image_to_video(
100
  input_image,
101
  prompt=prompt,
102
- model="chetwinlow1/Ovi",
103
  )
104
  except Exception as e:
105
  import requests
106
  if isinstance(e, requests.HTTPError) and getattr(e.response, "status_code", None) == 403:
107
- raise gr.Error("Access denied by provider (403). Make sure your HF account has credits/permission for provider 'fal-ai' and model 'chetwinlow1/Ovi'.")
108
  raise
109
 
110
- progress(0.9, desc="Finalizing video...")
111
-
112
  # Save the video to a temporary file
113
  video_path = _save_bytes_as_temp_mp4(video)
114
 
115
- progress(1.0, desc="Complete!")
116
-
117
- return video_path
118
 
119
- except gr.Error:
120
- raise
121
  except Exception as e:
122
- raise gr.Error(f"Generation failed: {str(e)}")
123
 
124
- def clear_inputs():
125
- """Clear all inputs and outputs"""
126
- return None, "", None
 
 
 
 
127
 
128
  # Custom CSS for better styling
129
  custom_css = """
@@ -154,197 +176,247 @@ custom_css = """
154
  text-align: center;
155
  font-size: 0.98rem;
156
  }
157
- .info-box {
158
- background-color: #f0f7ff;
159
- border-left: 4px solid #4285f4;
160
- padding: 1em;
 
161
  margin: 1em 0;
162
- border-radius: 4px;
163
  }
164
- .auth-warning {
165
- color: #ff6b00;
 
166
  font-weight: bold;
167
- text-align: center;
168
- margin: 1em 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
169
  }
170
  """
171
 
172
  # Create the Gradio interface
173
- with gr.Blocks(css=custom_css, theme=gr.themes.Soft(), title="Image to Video Generator with Ovi (Paid)") as demo:
 
 
 
 
 
 
 
174
 
175
  gr.HTML(
176
  """
177
  <div style="text-align:center; max-width:900px; margin:0 auto;">
178
- <h1 style="font-size:2.2em; margin-bottom:6px;">🎬 Image to Video Generator with Ovi</h1>
179
- <p style="color:#777; margin:0 0 8px;">Transform your static images into dynamic videos with synchronized audio using AI!</p>
180
  <div class="notice">
181
  <b>Heads up:</b> This is a paid app that uses <b>your</b> inference provider credits when you run generations.
182
  Free users get <b>$0.10 in included credits</b>. <b>PRO users</b> get <b>$2 in included credits</b>
183
  and can continue using beyond that (with billing).
184
- <a href='http://huggingface.co/subscribe/pro?source=ovi' target='_blank' style='color:#fff; text-decoration:underline; font-weight:bold;'>Subscribe to PRO</a>
185
  for more credits. Please sign in with your Hugging Face account to continue.
186
  </div>
187
  <p style="font-size: 0.9em; color: #999; margin-top: 10px;">
188
- Built with <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" style="color:#667eea; text-decoration:underline;">anycoder</a>
189
  </p>
190
  </div>
191
  """
192
  )
193
 
194
- gr.Markdown(
195
- """
196
- Powered by Ovi: Twin Backbone Cross-Modal Fusion for Audio-Video Generation via [HuggingFace Inference Providers](https://huggingface.co/docs/huggingface_hub/guides/inference).
197
- """
198
- )
199
-
200
  gr.HTML(
201
  """
202
- <div class="auth-warning">
203
- ⚠️ You must Sign in with Hugging Face using the button below to use this app.
 
 
 
204
  </div>
205
  """
206
  )
207
 
208
- # Add login button - required for OAuth
209
- gr.LoginButton()
210
-
211
  gr.HTML(
212
  """
213
- <div class="info-box">
214
- <strong>💡 Tips for best results:</strong>
215
- <ul>
216
- <li>Use clear, well-lit images with a single main subject</li>
217
- <li>Write specific prompts describing the desired motion or action</li>
218
- <li>Keep prompts concise and focused on movement and audio elements</li>
219
- <li>Processing generates 5-second videos at 24 FPS with synchronized audio</li>
220
- <li>Processing may take 30-60 seconds depending on server load</li>
221
- </ul>
222
- </div>
223
  """
224
  )
225
 
226
- gr.HTML(
227
- """
228
- <div class="info-box">
229
- <strong>✨ Special Tokens for Enhanced Control:</strong>
230
- <ul>
231
- <li><strong>Speech:</strong> <code>&lt;S&gt;Your speech content here&lt;E&gt;</code> - Text enclosed in these tags will be converted to speech</li>
232
- <li><strong>Audio Description:</strong> <code>&lt;AUDCAP&gt;Audio description here&lt;ENDAUDCAP&gt;</code> - Describes the audio or sound effects present in the video</li>
233
- </ul>
234
- <br>
235
- <strong>📝 Example Prompt:</strong><br>
236
- <code>Dogs bark loudly at a man wearing a red shirt. The man says &lt;S&gt;Please stop barking at me!&lt;E&gt;. &lt;AUDCAP&gt;Dogs barking, angry man yelling in stern voice&lt;ENDAUDCAP&gt;.</code>
237
- </div>
238
- """
239
- )
240
 
241
- with gr.Row():
242
- with gr.Column(scale=1):
243
- image_input = gr.Image(
244
- label="📸 Upload Image",
245
- type="pil",
246
- height=400,
247
- )
248
-
249
- prompt_input = gr.Textbox(
250
- label="✍️ Text Prompt",
251
- lines=3,
252
- placeholder="Describe the motion you want to see in the video..."
253
- )
254
 
255
  with gr.Row():
256
- generate_btn = gr.Button(
257
- "🎬 Generate Video",
258
- variant="primary",
259
- scale=2,
260
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
261
 
262
- clear_btn = gr.Button(
263
- "🗑️ Clear",
264
- variant="secondary",
265
- scale=1,
266
- )
 
 
267
 
 
268
  gr.Examples(
269
  examples=[
270
- [
271
- "5.png",
272
- 'A bearded man wearing large dark sunglasses and a blue patterned cardigan sits in a studio, actively speaking into a large, suspended microphone. He has headphones on and gestures with his hands, displaying rings on his fingers. Behind him, a wall is covered with red, textured sound-dampening foam on the left, and a white banner on the right features the "CHOICE FM" logo and various social media handles like "@ilovechoicefm" with "RALEIGH" below it. The man intently addresses the microphone, articulating, <S>is talent. It\'s all about authenticity. You gotta be who you really are, especially if you\'re working<E>. He leans forward slightly as he speaks, maintaining a serious expression behind his sunglasses.. <AUDCAP>Clear male voice speaking into a microphone, a low background hum.<ENDAUDCAP>'
273
- ]
 
274
  ],
275
- inputs=[image_input, prompt_input],
276
- label="Example",
277
  )
278
 
279
- with gr.Column(scale=1):
280
- video_output = gr.Video(
281
- label="🎥 Generated Video",
282
- height=400,
283
- autoplay=True,
284
- show_download_button=True,
285
- )
286
 
287
- gr.Markdown(
288
- """
289
- ### About Ovi Model
290
-
291
- **Ovi: Twin Backbone Cross-Modal Fusion for Audio-Video Generation**
292
-
293
- Developed by Chetwin Low, Weimin Wang (Character AI) & Calder Katyal (Yale University)
294
-
295
- 🌟 **Key Features:**
296
- - 🎬 **Video+Audio Generation**: Generates synchronized video and audio content simultaneously
297
- - 📝 **Flexible Input**: Supports text-only or text+image conditioning
298
- - ⏱️ **5-second Videos**: Generates 5-second videos at 24 FPS
299
- - 📐 **Multiple Aspect Ratios**: Supports 720×720 area at various ratios (9:16, 16:9, 1:1, etc)
 
 
 
 
 
 
 
 
 
 
 
 
300
 
301
- Ovi is a veo-3 like model that simultaneously generates both video and audio content from text or text+image inputs.
302
- """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
303
  )
304
 
305
- # Event handlers with authentication - uses OAuthProfile automatically
306
- generate_btn.click(
307
- fn=generate_video_with_auth,
308
- inputs=[image_input, prompt_input],
309
- outputs=[video_output],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
310
  show_progress="full",
311
  queue=False,
312
  api_name=False,
313
- show_api=False,
314
  )
315
 
316
- clear_btn.click(
317
- fn=clear_inputs,
318
  inputs=[],
319
- outputs=[image_input, prompt_input, video_output],
 
 
 
 
 
 
 
 
320
  queue=False,
 
 
321
  )
322
 
323
- gr.Markdown(
324
- """
325
- ---
326
-
327
- ### 🚀 How it works
328
-
329
- 1. **Sign in** with your Hugging Face account
330
- 2. **Upload** your image - any photo or illustration
331
- 3. **Describe** the motion you want to see in the prompt
332
- 4. **Generate** and watch your image come to life!
333
-
334
- ### ⚠️ Notes
335
-
336
- - Video generation may take 30-60 seconds
337
- - Generates 5-second videos at 24 FPS with synchronized audio
338
- - Supports multiple aspect ratios (9:16, 16:9, 1:1, etc) at 720×720 area
339
- - Requires a valid HuggingFace token with Inference API access
340
- - Best results with clear, high-quality images
341
- - The model works best with realistic subjects and natural motions
342
-
343
- ### 🔗 Resources
344
-
345
- - [Ovi Model Card](https://huggingface.co/chetwinlow1/Ovi)
346
- - [Character AI](https://character.ai)
347
- """
348
  )
349
 
350
  # Launch the app
 
1
  import gradio as gr
2
  import os
3
  from huggingface_hub import InferenceClient
 
4
  import tempfile
 
 
5
  import shutil
6
+ from pathlib import Path
7
+ from typing import Optional, Union
8
+ import time
9
 
10
  # -------------------------
11
  # Utilities
 
23
  except Exception as e:
24
  print(f"Cleanup error: {e}")
25
 
26
+ def _client_from_token(token: Optional[str]) -> InferenceClient:
27
+ if not token:
28
+ raise gr.Error("Please sign in first. This app requires your Hugging Face login.")
29
+ # IMPORTANT: do not set bill_to when using user OAuth tokens
30
+ return InferenceClient(
31
+ provider="fal-ai",
32
+ api_key=token,
33
+ )
34
+
35
  def _save_bytes_as_temp_mp4(data: bytes) -> str:
36
  temp_file = tempfile.NamedTemporaryFile(suffix=".mp4", delete=False)
37
  try:
 
41
  finally:
42
  temp_file.close()
43
 
44
+ def text_to_video(prompt, token: gr.OAuthToken | None, duration=5, aspect_ratio="16:9", resolution="720p", *_):
45
+ """Generate video from text prompt"""
46
+ try:
47
+ if token is None or not getattr(token, "token", None):
48
+ return None, "❌ Sign in with Hugging Face to continue. This app uses your inference provider credits."
49
+
50
+ if not prompt or prompt.strip() == "":
51
+ return None, "Please enter a text prompt"
52
+
53
+ cleanup_temp_files()
54
+
55
+ # Create client with user's token
56
+ client = _client_from_token(token.token)
57
+
58
+ # Generate video from text
59
+ try:
60
+ video = client.text_to_video(
61
+ prompt,
62
+ model="akhaliq/veo3.1-fast",
63
+ )
64
+ except Exception as e:
65
+ import requests
66
+ if isinstance(e, requests.HTTPError) and getattr(e.response, "status_code", None) == 403:
67
+ return None, "❌ Access denied by provider (403). Make sure your HF account has credits/permission for provider 'fal-ai' and model 'akhaliq/veo3.1-fast'."
68
+ raise
69
+
70
+ # Save the video to a temporary file
71
+ video_path = _save_bytes_as_temp_mp4(video)
72
+
73
+ return video_path, f"✅ Video generated successfully from prompt: '{prompt[:50]}...'"
74
 
75
+ except gr.Error as e:
76
+ return None, f"❌ {str(e)}"
77
+ except Exception as e:
78
+ return None, f"❌ Generation failed. If this keeps happening, check your provider quota or try again later."
79
+
80
+ def image_to_video(image, prompt, token: gr.OAuthToken | None, duration=5, aspect_ratio="16:9", resolution="720p", *_):
81
+ """Generate video from image and prompt"""
82
  try:
83
+ if token is None or not getattr(token, "token", None):
84
+ return None, " Sign in with Hugging Face to continue. This app uses your inference provider credits."
85
 
86
  if image is None:
87
+ return None, "Please upload an image"
88
 
89
  if not prompt or prompt.strip() == "":
90
+ return None, "Please enter a prompt describing the motion"
91
 
92
  cleanup_temp_files()
93
 
 
 
94
  # Read the image file
95
  if isinstance(image, str):
96
+ # If image is a file path
97
  with open(image, "rb") as image_file:
98
  input_image = image_file.read()
99
  else:
100
+ # If image is already bytes or similar
101
  import io
102
  from PIL import Image as PILImage
103
 
 
113
  pil_image.save(buffer, format='PNG')
114
  input_image = buffer.getvalue()
115
 
116
+ # Create client with user's token
117
+ client = _client_from_token(token.token)
118
 
119
+ # Generate video from image
 
 
 
 
 
 
 
 
 
 
 
 
120
  try:
121
  video = client.image_to_video(
122
  input_image,
123
  prompt=prompt,
124
+ model="akhaliq/veo3.1-fast-image-to-video",
125
  )
126
  except Exception as e:
127
  import requests
128
  if isinstance(e, requests.HTTPError) and getattr(e.response, "status_code", None) == 403:
129
+ return None, "Access denied by provider (403). Make sure your HF account has credits/permission for provider 'fal-ai' and model 'akhaliq/veo3.1-fast-image-to-video'."
130
  raise
131
 
 
 
132
  # Save the video to a temporary file
133
  video_path = _save_bytes_as_temp_mp4(video)
134
 
135
+ return video_path, f"✅ Video generated successfully with motion: '{prompt[:50]}...'"
 
 
136
 
137
+ except gr.Error as e:
138
+ return None, f"❌ {str(e)}"
139
  except Exception as e:
140
+ return None, f"Generation failed. If this keeps happening, check your provider quota or try again later."
141
 
142
+ def clear_text_tab():
143
+ """Clear text-to-video tab"""
144
+ return "", None, ""
145
+
146
+ def clear_image_tab():
147
+ """Clear image-to-video tab"""
148
+ return None, "", None, ""
149
 
150
  # Custom CSS for better styling
151
  custom_css = """
 
176
  text-align: center;
177
  font-size: 0.98rem;
178
  }
179
+ .mobile-link-container {
180
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
181
+ padding: 1.5em;
182
+ border-radius: 10px;
183
+ text-align: center;
184
  margin: 1em 0;
185
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
186
  }
187
+ .mobile-link {
188
+ color: white !important;
189
+ font-size: 1.2em;
190
  font-weight: bold;
191
+ text-decoration: none;
192
+ display: inline-block;
193
+ padding: 0.5em 1.5em;
194
+ background: rgba(255, 255, 255, 0.2);
195
+ border-radius: 25px;
196
+ transition: all 0.3s ease;
197
+ }
198
+ .mobile-link:hover {
199
+ background: rgba(255, 255, 255, 0.3);
200
+ transform: translateY(-2px);
201
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
202
+ }
203
+ .mobile-text {
204
+ color: white;
205
+ margin-bottom: 0.5em;
206
+ font-size: 1.1em;
207
  }
208
  """
209
 
210
  # Create the Gradio interface
211
+ with gr.Blocks(css=custom_css, theme=gr.themes.Soft(), title="AI Video Generator (Paid)") as demo:
212
+ gr.Markdown(
213
+ """
214
+ # 🎬 AI Video Generator
215
+ ### Generate stunning videos from text or animate your images with AI
216
+ #### Powered by VEO 3.1 Fast Model via Hugging Face Inference API (provider: fal-ai)
217
+ """
218
+ )
219
 
220
  gr.HTML(
221
  """
222
  <div style="text-align:center; max-width:900px; margin:0 auto;">
223
+ <h1 style="font-size:2.2em; margin-bottom:6px;">🎬 Sora-2</h1>
224
+ <p style="color:#777; margin:0 0 8px;">Generate videos via the Hugging Face Inference API (provider: fal-ai)</p>
225
  <div class="notice">
226
  <b>Heads up:</b> This is a paid app that uses <b>your</b> inference provider credits when you run generations.
227
  Free users get <b>$0.10 in included credits</b>. <b>PRO users</b> get <b>$2 in included credits</b>
228
  and can continue using beyond that (with billing).
229
+ <a href='http://huggingface.co/subscribe/pro?source=veo3' target='_blank' style='color:#fff; text-decoration:underline; font-weight:bold;'>Subscribe to PRO</a>
230
  for more credits. Please sign in with your Hugging Face account to continue.
231
  </div>
232
  <p style="font-size: 0.9em; color: #999; margin-top: 10px;">
233
+ Built with <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" style="color:#fff; text-decoration:underline;">anycoder</a>
234
  </p>
235
  </div>
236
  """
237
  )
238
 
239
+ # Add mobile link section
 
 
 
 
 
240
  gr.HTML(
241
  """
242
+ <div class="mobile-link-container">
243
+ <div class="mobile-text">📱 On mobile? Use the optimized version:</div>
244
+ <a href="https://akhaliq-veo3-1-fast.hf.space" target="_blank" class="mobile-link">
245
+ 🚀 Open Mobile Version
246
+ </a>
247
  </div>
248
  """
249
  )
250
 
 
 
 
251
  gr.HTML(
252
  """
253
+ <p style="text-align: center; font-size: 0.9em; color: #999; margin-top: 10px;">
254
+ Built with <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" style="color:#667eea; text-decoration:underline;">anycoder</a>
255
+ </p>
 
 
 
 
 
 
 
256
  """
257
  )
258
 
259
+ # Add login button - required for OAuth
260
+ login_btn = gr.LoginButton("Sign in with Hugging Face")
 
 
 
 
 
 
 
 
 
 
 
 
261
 
262
+ with gr.Tabs() as tabs:
263
+ # Text-to-Video Tab
264
+ with gr.Tab("📝 Text to Video", id=0):
265
+ gr.Markdown("### Transform your text descriptions into dynamic videos")
 
 
 
 
 
 
 
 
 
266
 
267
  with gr.Row():
268
+ with gr.Column(scale=1):
269
+ text_prompt = gr.Textbox(
270
+ label="Text Prompt",
271
+ placeholder="Describe the video you want to create... (e.g., 'A young man walking on the street during sunset')",
272
+ lines=4,
273
+ max_lines=6
274
+ )
275
+
276
+ with gr.Row():
277
+ text_generate_btn = gr.Button("🎬 Generate Video", variant="primary", scale=2)
278
+ text_clear_btn = gr.ClearButton(value="🗑️ Clear", scale=1)
279
+
280
+ text_status = gr.Textbox(
281
+ label="Status",
282
+ interactive=False,
283
+ visible=True,
284
+ elem_classes=["status-box"]
285
+ )
286
 
287
+ with gr.Column(scale=1):
288
+ text_video_output = gr.Video(
289
+ label="Generated Video",
290
+ autoplay=True,
291
+ show_download_button=True,
292
+ height=400
293
+ )
294
 
295
+ # Examples for text-to-video
296
  gr.Examples(
297
  examples=[
298
+ ["A serene beach at sunset with gentle waves"],
299
+ ["A bustling city street with neon lights at night"],
300
+ ["A majestic eagle soaring through mountain peaks"],
301
+ ["An astronaut floating in space near the International Space Station"],
302
+ ["Cherry blossoms falling in slow motion in a Japanese garden"],
303
  ],
304
+ inputs=text_prompt,
305
+ label="Example Prompts"
306
  )
307
 
308
+ # Image-to-Video Tab
309
+ with gr.Tab("🖼️ Image to Video", id=1):
310
+ gr.Markdown("### Bring your static images to life with motion")
 
 
 
 
311
 
312
+ with gr.Row():
313
+ with gr.Column(scale=1):
314
+ image_input = gr.Image(
315
+ label="Upload Image",
316
+ type="pil",
317
+ height=300
318
+ )
319
+
320
+ image_prompt = gr.Textbox(
321
+ label="Motion Prompt",
322
+ placeholder="Describe how the image should move... (e.g., 'The cat starts to dance')",
323
+ lines=3,
324
+ max_lines=5
325
+ )
326
+
327
+ with gr.Row():
328
+ image_generate_btn = gr.Button("🎬 Animate Image", variant="primary", scale=2)
329
+ image_clear_btn = gr.ClearButton(value="🗑️ Clear", scale=1)
330
+
331
+ image_status = gr.Textbox(
332
+ label="Status",
333
+ interactive=False,
334
+ visible=True,
335
+ elem_classes=["status-box"]
336
+ )
337
 
338
+ with gr.Column(scale=1):
339
+ image_video_output = gr.Video(
340
+ label="Generated Video",
341
+ autoplay=True,
342
+ show_download_button=True,
343
+ height=400
344
+ )
345
+
346
+ # Examples for image-to-video
347
+ gr.Examples(
348
+ examples=[
349
+ [None, "The person starts walking forward"],
350
+ [None, "The animal begins to run"],
351
+ [None, "Camera slowly zooms in while the subject smiles"],
352
+ [None, "The flowers sway gently in the breeze"],
353
+ [None, "The clouds move across the sky in time-lapse"],
354
+ ],
355
+ inputs=[image_input, image_prompt],
356
+ label="Example Motion Prompts"
357
  )
358
 
359
+ # How to Use section
360
+ with gr.Accordion("📖 How to Use", open=False):
361
+ gr.Markdown(
362
+ """
363
+ ### Text to Video:
364
+ 1. Enter a detailed description of the video you want to create
365
+ 2. Optionally adjust advanced settings (duration, aspect ratio, resolution)
366
+ 3. Click "Generate Video" and wait for the AI to create your video
367
+ 4. Download or preview your generated video
368
+
369
+ ### Image to Video:
370
+ 1. Upload an image you want to animate
371
+ 2. Describe the motion or action you want to add to the image
372
+ 3. Optionally adjust advanced settings
373
+ 4. Click "Animate Image" to bring your image to life
374
+ 5. Download or preview your animated video
375
+
376
+ ### Tips for Better Results:
377
+ - Be specific and descriptive in your prompts
378
+ - For image-to-video, describe natural motions that fit the image
379
+ - Use high-quality input images for better results
380
+ - Experiment with different prompts to get the desired effect
381
+
382
+ ### Mobile Users:
383
+ - For the best mobile experience, use the optimized version at: https://akhaliq-veo3-1-fast.hf.space
384
+ """
385
+ )
386
+
387
+ # Event handlers - FIXED: removed login_btn from inputs
388
+ text_generate_btn.click(
389
+ fn=text_to_video,
390
+ inputs=[text_prompt],
391
+ outputs=[text_video_output, text_status],
392
  show_progress="full",
393
  queue=False,
394
  api_name=False,
395
+ show_api=False
396
  )
397
 
398
+ text_clear_btn.click(
399
+ fn=clear_text_tab,
400
  inputs=[],
401
+ outputs=[text_prompt, text_video_output, text_status],
402
+ queue=False
403
+ )
404
+
405
+ image_generate_btn.click(
406
+ fn=image_to_video,
407
+ inputs=[image_input, image_prompt],
408
+ outputs=[image_video_output, image_status],
409
+ show_progress="full",
410
  queue=False,
411
+ api_name=False,
412
+ show_api=False
413
  )
414
 
415
+ image_clear_btn.click(
416
+ fn=clear_image_tab,
417
+ inputs=[],
418
+ outputs=[image_input, image_prompt, image_video_output, image_status],
419
+ queue=False
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
420
  )
421
 
422
  # Launch the app