akhaliq HF Staff commited on
Commit
3be93ed
Β·
verified Β·
1 Parent(s): 3ae4fdd

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +275 -145
app.py CHANGED
@@ -1,156 +1,213 @@
1
  import gradio as gr
2
  import os
3
  from huggingface_hub import InferenceClient
4
- from pathlib import Path
5
  import tempfile
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
- # Initialize the inference client
8
- client = InferenceClient(
9
- provider="fal-ai",
10
- api_key=os.environ.get("HF_TOKEN"),
11
- bill_to="huggingface",
12
- )
 
 
 
 
13
 
14
- def generate_video_with_auth(image, prompt, profile: gr.OAuthProfile | None, progress=gr.Progress()):
 
 
 
 
 
 
 
 
 
 
15
  """
16
  Generate a video from an image using the Ovi model with authentication check.
17
 
18
  Args:
19
  image: Input image (PIL Image or file path)
20
  prompt: Text prompt describing the desired motion/animation
21
- profile: OAuth profile for authentication
22
  progress: Gradio progress tracker
23
 
24
  Returns:
25
- Path to the generated video file
26
  """
27
- if profile is None:
28
- raise gr.Error("Click Sign in with Hugging Face button to use this app for free")
29
-
30
- if image is None:
31
- raise gr.Error("Please upload an image first!")
32
-
33
- if not prompt or prompt.strip() == "":
34
- raise gr.Error("Please enter a prompt describing the desired motion!")
35
-
36
  try:
 
 
 
 
 
 
 
 
 
 
37
  progress(0.2, desc="Processing image...")
38
 
 
 
39
  # Read the image file
40
  if isinstance(image, str):
 
41
  with open(image, "rb") as image_file:
42
  input_image = image_file.read()
43
  else:
44
- # If image is a PIL Image, save it temporarily
45
- temp_image = tempfile.NamedTemporaryFile(delete=False, suffix=".png")
46
- image.save(temp_image.name)
47
- with open(temp_image.name, "rb") as image_file:
48
- input_image = image_file.read()
 
 
 
 
 
 
 
 
 
49
 
50
  progress(0.4, desc="Generating video with AI...")
51
 
 
 
 
52
  # Generate video using the inference client
53
- video = client.image_to_video(
54
- input_image,
55
- prompt=prompt,
56
- model="chetwinlow1/Ovi",
57
- )
 
 
 
 
 
 
58
 
59
  progress(0.9, desc="Finalizing video...")
60
 
61
  # Save the video to a temporary file
62
- output_path = tempfile.NamedTemporaryFile(delete=False, suffix=".mp4")
63
-
64
- # Check if video is bytes or a file path
65
- if isinstance(video, bytes):
66
- with open(output_path.name, "wb") as f:
67
- f.write(video)
68
- elif isinstance(video, str) and os.path.exists(video):
69
- # If it's a path, copy it
70
- import shutil
71
- shutil.copy(video, output_path.name)
72
- else:
73
- # Try to write it directly
74
- with open(output_path.name, "wb") as f:
75
- f.write(video)
76
 
77
  progress(1.0, desc="Complete!")
78
 
79
- return output_path.name
80
 
 
 
81
  except Exception as e:
82
- raise gr.Error(f"Error generating video: {str(e)}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
 
84
  # Create the Gradio interface
85
- with gr.Blocks(
86
- theme=gr.themes.Soft(
87
- primary_hue="blue",
88
- secondary_hue="indigo",
89
- ),
90
- css="""
91
- .header-link {
92
- font-size: 0.9em;
93
- color: #666;
94
- text-decoration: none;
95
- margin-bottom: 1em;
96
- display: inline-block;
97
- }
98
- .header-link:hover {
99
- color: #333;
100
- text-decoration: underline;
101
- }
102
- .main-header {
103
- text-align: center;
104
- margin-bottom: 2em;
105
- }
106
- .info-box {
107
- background-color: #f0f7ff;
108
- border-left: 4px solid #4285f4;
109
- padding: 1em;
110
- margin: 1em 0;
111
- border-radius: 4px;
112
- }
113
- .auth-warning {
114
- color: #ff6b00;
115
- font-weight: bold;
116
- text-align: center;
117
- margin: 1em 0;
118
- }
119
- """,
120
- title="Image to Video Generator with Ovi",
121
- ) as demo:
122
 
 
123
  gr.HTML(
124
  """
125
- <div class="main-header">
126
- <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="header-link">
127
- Built with anycoder ✨
128
- </a>
 
 
 
 
 
 
 
 
 
129
  </div>
130
  """
131
  )
132
 
133
  gr.Markdown(
134
  """
135
- # 🎬 Image to Video Generator with Ovi
136
 
137
- Transform your static images into dynamic videos with synchronized audio using AI! Upload an image and describe the motion you want to see.
138
-
139
- Powered by Ovi: Twin Backbone Cross-Modal Fusion for Audio-Video Generation via [HuggingFace Inference Providers](https://huggingface.co/docs/huggingface_hub/guides/inference)
140
- .
141
- """
142
- )
143
-
144
- gr.HTML(
145
- """
146
- <div class="auth-warning">
147
- ⚠️ You must Sign in with Hugging Face using the button below to use this app.
148
- </div>
149
  """
150
  )
151
 
152
  # Add login button - required for OAuth
153
- gr.LoginButton()
154
 
155
  gr.HTML(
156
  """
@@ -169,7 +226,7 @@ with gr.Blocks(
169
 
170
  gr.HTML(
171
  """
172
- <div class="info-box">
173
  <strong>✨ Special Tokens for Enhanced Control:</strong>
174
  <ul>
175
  <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>
@@ -186,36 +243,55 @@ with gr.Blocks(
186
  with gr.Column(scale=1):
187
  image_input = gr.Image(
188
  label="πŸ“Έ Upload Image",
189
- type="filepath",
190
  sources=["upload", "clipboard"],
191
  height=400,
192
  )
193
 
194
  prompt_input = gr.Textbox(
195
  label="✍️ Text Prompt",
196
- lines=3,
 
 
197
  )
198
 
199
- generate_btn = gr.Button(
200
- "🎬 Generate Video",
201
- variant="primary",
202
- size="lg",
203
- )
 
 
 
 
 
 
 
204
 
205
- clear_btn = gr.Button(
206
- "πŸ—‘οΈ Clear",
207
- variant="secondary",
 
 
208
  )
209
 
210
  gr.Examples(
211
  examples=[
212
  [
213
- "5.png",
214
  '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>'
 
 
 
 
 
 
 
 
215
  ]
216
  ],
217
  inputs=[image_input, prompt_input],
218
- label="Example",
219
  )
220
 
221
  with gr.Column(scale=1):
@@ -223,6 +299,7 @@ with gr.Blocks(
223
  label="πŸŽ₯ Generated Video",
224
  height=400,
225
  autoplay=True,
 
226
  )
227
 
228
  gr.Markdown(
@@ -240,57 +317,110 @@ with gr.Blocks(
240
  - πŸ“ **Multiple Aspect Ratios**: Supports 720Γ—720 area at various ratios (9:16, 16:9, 1:1, etc)
241
 
242
  Ovi is a veo-3 like model that simultaneously generates both video and audio content from text or text+image inputs.
 
 
 
 
 
 
 
 
 
 
243
  """
244
  )
245
 
246
- # Event handlers with authentication
247
- generate_btn.click(
248
- fn=generate_video_with_auth,
249
- inputs=[image_input, prompt_input],
250
- outputs=[video_output],
251
- queue=False,
252
- api_name=False,
253
- show_api=False,
254
- )
255
-
256
- clear_btn.click(
257
- fn=lambda: (None, "", None),
258
- inputs=None,
259
- outputs=[image_input, prompt_input, video_output],
260
- queue=False,
261
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
262
 
263
  gr.Markdown(
264
  """
265
  ---
266
 
267
- ### πŸš€ How it works
268
-
269
- 1. **Sign in** with your Hugging Face account
270
- 2. **Upload** your image - any photo or illustration
271
- 3. **Describe** the motion you want to see in the prompt
272
- 4. **Generate** and watch your image come to life!
273
-
274
- ### ⚠️ Notes
275
-
276
- - Video generation may take 30-60 seconds
277
- - Generates 5-second videos at 24 FPS with synchronized audio
278
- - Supports multiple aspect ratios (9:16, 16:9, 1:1, etc) at 720Γ—720 area
279
- - Requires a valid HuggingFace token with Inference API access
280
- - Best results with clear, high-quality images
281
- - The model works best with realistic subjects and natural motions
282
-
283
  ### πŸ”— Resources
284
 
285
  - [Ovi Model Card](https://huggingface.co/chetwinlow1/Ovi)
286
  - [Character AI](https://character.ai)
 
 
 
 
 
 
 
 
 
 
287
  """
288
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
289
 
290
  # Launch the app
291
  if __name__ == "__main__":
 
 
 
 
 
 
 
 
292
  demo.launch(
293
  show_api=False,
 
 
294
  enable_monitoring=False,
295
  quiet=True,
296
  )
 
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
8
+ import time
9
+
10
+ # -------------------------
11
+ # Utilities
12
+ # -------------------------
13
+
14
+ def cleanup_temp_files():
15
+ """Clean up old temporary video files"""
16
+ try:
17
+ temp_dir = tempfile.gettempdir()
18
+ for file_path in Path(temp_dir).glob("*.mp4"):
19
+ try:
20
+ if file_path.stat().st_mtime < (time.time() - 300):
21
+ file_path.unlink(missing_ok=True)
22
+ except Exception:
23
+ pass
24
+ except Exception as e:
25
+ print(f"Cleanup error: {e}")
26
 
27
+ def _client_from_token(token: Optional[str]) -> InferenceClient:
28
+ """Create InferenceClient from user's OAuth token"""
29
+ if not token:
30
+ raise gr.Error("Please sign in first. This app requires your Hugging Face login.")
31
+ # IMPORTANT: do not set bill_to when using user OAuth tokens
32
+ # This ensures the user is billed, not Hugging Face
33
+ return InferenceClient(
34
+ provider="fal-ai",
35
+ api_key=token,
36
+ )
37
 
38
+ def _save_bytes_as_temp_mp4(data: bytes) -> str:
39
+ """Save video bytes to temporary MP4 file"""
40
+ temp_file = tempfile.NamedTemporaryFile(suffix=".mp4", delete=False)
41
+ try:
42
+ temp_file.write(data)
43
+ temp_file.flush()
44
+ return temp_file.name
45
+ finally:
46
+ temp_file.close()
47
+
48
+ def generate_video_with_auth(image, prompt, token: gr.OAuthToken | None, progress=gr.Progress()):
49
  """
50
  Generate a video from an image using the Ovi model with authentication check.
51
 
52
  Args:
53
  image: Input image (PIL Image or file path)
54
  prompt: Text prompt describing the desired motion/animation
55
+ token: OAuth token for authentication
56
  progress: Gradio progress tracker
57
 
58
  Returns:
59
+ Tuple of (video_path, status_message)
60
  """
 
 
 
 
 
 
 
 
 
61
  try:
62
+ # Check authentication
63
+ if token is None or not getattr(token, "token", None):
64
+ return None, "❌ Sign in with Hugging Face to continue. This app uses your inference provider credits."
65
+
66
+ if image is None:
67
+ return None, "❌ Please upload an image first!"
68
+
69
+ if not prompt or prompt.strip() == "":
70
+ return None, "❌ Please enter a prompt describing the desired motion!"
71
+
72
  progress(0.2, desc="Processing image...")
73
 
74
+ cleanup_temp_files()
75
+
76
  # Read the image file
77
  if isinstance(image, str):
78
+ # If image is a file path
79
  with open(image, "rb") as image_file:
80
  input_image = image_file.read()
81
  else:
82
+ # If image is PIL Image or array
83
+ import io
84
+ from PIL import Image as PILImage
85
+
86
+ if isinstance(image, PILImage.Image):
87
+ buffer = io.BytesIO()
88
+ image.save(buffer, format='PNG')
89
+ input_image = buffer.getvalue()
90
+ else:
91
+ # Assume it's a numpy array
92
+ pil_image = PILImage.fromarray(image)
93
+ buffer = io.BytesIO()
94
+ pil_image.save(buffer, format='PNG')
95
+ input_image = buffer.getvalue()
96
 
97
  progress(0.4, desc="Generating video with AI...")
98
 
99
+ # Create client with user's token
100
+ client = _client_from_token(token.token)
101
+
102
  # Generate video using the inference client
103
+ try:
104
+ video = client.image_to_video(
105
+ input_image,
106
+ prompt=prompt,
107
+ model="chetwinlow1/Ovi",
108
+ )
109
+ except Exception as e:
110
+ import requests
111
+ if isinstance(e, requests.HTTPError) and getattr(e.response, "status_code", None) == 403:
112
+ return None, "❌ Access denied by provider (403). Make sure your HF account has credits/permission for provider 'fal-ai' and model 'chetwinlow1/Ovi'."
113
+ raise
114
 
115
  progress(0.9, desc="Finalizing video...")
116
 
117
  # Save the video to a temporary file
118
+ video_path = _save_bytes_as_temp_mp4(video)
 
 
 
 
 
 
 
 
 
 
 
 
 
119
 
120
  progress(1.0, desc="Complete!")
121
 
122
+ return video_path, f"βœ… Video generated successfully! Prompt: '{prompt[:60]}...'"
123
 
124
+ except gr.Error as e:
125
+ return None, f"❌ {str(e)}"
126
  except Exception as e:
127
+ return None, f"❌ Generation failed. If this keeps happening, check your provider quota or try again later. Error: {str(e)}"
128
+
129
+ def clear_all():
130
+ """Clear all inputs and outputs"""
131
+ return None, "", None, ""
132
+
133
+ # Custom CSS for better styling
134
+ custom_css = """
135
+ .container {
136
+ max-width: 1200px;
137
+ margin: auto;
138
+ }
139
+ .header-link {
140
+ text-decoration: none;
141
+ color: #2196F3;
142
+ font-weight: bold;
143
+ }
144
+ .header-link:hover {
145
+ text-decoration: underline;
146
+ }
147
+ .status-box {
148
+ padding: 10px;
149
+ border-radius: 5px;
150
+ margin-top: 10px;
151
+ }
152
+ .notice {
153
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
154
+ color: white;
155
+ padding: 14px 16px;
156
+ border-radius: 12px;
157
+ margin: 18px auto 6px;
158
+ max-width: 860px;
159
+ text-align: center;
160
+ font-size: 0.98rem;
161
+ }
162
+ .info-box {
163
+ background-color: #f0f7ff;
164
+ border-left: 4px solid #4285f4;
165
+ padding: 1em;
166
+ margin: 1em 0;
167
+ border-radius: 4px;
168
+ }
169
+ .special-tokens-box {
170
+ background: linear-gradient(135deg, #ffeaa7 0%, #fdcb6e 100%);
171
+ padding: 1em;
172
+ margin: 1em 0;
173
+ border-radius: 8px;
174
+ border-left: 4px solid #e17055;
175
+ }
176
+ """
177
 
178
  # Create the Gradio interface
179
+ with gr.Blocks(css=custom_css, theme=gr.themes.Soft(), title="Ovi Image-to-Video Generator (Paid)") as demo:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
180
 
181
+ # Header with payment notice
182
  gr.HTML(
183
  """
184
+ <div style="text-align:center; padding:2em 1em 1em;">
185
+ <h1 style="font-size:2.2em; margin-bottom:6px;">🎬 Ovi: Image-to-Video with Audio</h1>
186
+ <p style="color:#777; margin:0 0 8px;">Generate synchronized video and audio from images</p>
187
+ <div class="notice">
188
+ <b>Heads up:</b> This is a paid app that uses <b>your</b> inference provider credits when you run generations.
189
+ Free users get <b>$0.10 in included credits</b>. <b>PRO users</b> get <b>$2 in included credits</b>
190
+ and can continue using beyond that (with billing).
191
+ <a href='http://huggingface.co/subscribe/pro?source=ovi' target='_blank' style='color:#fff; text-decoration:underline; font-weight:bold;'>Subscribe to PRO</a>
192
+ for more credits. Please sign in with your Hugging Face account to continue.
193
+ </div>
194
+ <p style="font-size: 0.9em; color: #999; margin-top: 10px;">
195
+ Built with <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" style="color:#667eea; text-decoration:underline;">anycoder</a>
196
+ </p>
197
  </div>
198
  """
199
  )
200
 
201
  gr.Markdown(
202
  """
203
+ ### Transform your static images into dynamic videos with synchronized audio using AI!
204
 
205
+ Powered by **Ovi: Twin Backbone Cross-Modal Fusion for Audio-Video Generation** via [HuggingFace Inference Providers](https://huggingface.co/docs/huggingface_hub/guides/inference)
 
 
 
 
 
 
 
 
 
 
 
206
  """
207
  )
208
 
209
  # Add login button - required for OAuth
210
+ login_btn = gr.LoginButton("Sign in with Hugging Face")
211
 
212
  gr.HTML(
213
  """
 
226
 
227
  gr.HTML(
228
  """
229
+ <div class="special-tokens-box">
230
  <strong>✨ Special Tokens for Enhanced Control:</strong>
231
  <ul>
232
  <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>
 
243
  with gr.Column(scale=1):
244
  image_input = gr.Image(
245
  label="πŸ“Έ Upload Image",
246
+ type="pil",
247
  sources=["upload", "clipboard"],
248
  height=400,
249
  )
250
 
251
  prompt_input = gr.Textbox(
252
  label="✍️ Text Prompt",
253
+ placeholder="Describe the motion and audio you want... (e.g., 'A person walking forward while talking')",
254
+ lines=4,
255
+ max_lines=6
256
  )
257
 
258
+ with gr.Row():
259
+ generate_btn = gr.Button(
260
+ "🎬 Generate Video",
261
+ variant="primary",
262
+ scale=2
263
+ )
264
+
265
+ clear_btn = gr.Button(
266
+ "πŸ—‘οΈ Clear",
267
+ variant="secondary",
268
+ scale=1
269
+ )
270
 
271
+ status_output = gr.Textbox(
272
+ label="Status",
273
+ interactive=False,
274
+ visible=True,
275
+ elem_classes=["status-box"]
276
  )
277
 
278
  gr.Examples(
279
  examples=[
280
  [
281
+ "example1.png",
282
  '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>'
283
+ ],
284
+ [
285
+ None,
286
+ "A cat sitting on a windowsill starts to meow loudly. <S>Meow meow meow!<E> <AUDCAP>Cat meowing, traffic sounds in the background<ENDAUDCAP>"
287
+ ],
288
+ [
289
+ None,
290
+ "A musician playing guitar on stage. The crowd cheers. <AUDCAP>Electric guitar playing, crowd cheering and applause<ENDAUDCAP>"
291
  ]
292
  ],
293
  inputs=[image_input, prompt_input],
294
+ label="Example Prompts",
295
  )
296
 
297
  with gr.Column(scale=1):
 
299
  label="πŸŽ₯ Generated Video",
300
  height=400,
301
  autoplay=True,
302
+ show_download_button=True
303
  )
304
 
305
  gr.Markdown(
 
317
  - πŸ“ **Multiple Aspect Ratios**: Supports 720Γ—720 area at various ratios (9:16, 16:9, 1:1, etc)
318
 
319
  Ovi is a veo-3 like model that simultaneously generates both video and audio content from text or text+image inputs.
320
+
321
+ ---
322
+
323
+ ### πŸ’³ Pricing Information
324
+
325
+ This app uses the Hugging Face Inference API (provider: fal-ai) which charges based on usage:
326
+ - **Free users**: $0.10 in included credits
327
+ - **PRO users**: $2 in included credits + ability to continue with billing
328
+
329
+ [Subscribe to PRO](http://huggingface.co/subscribe/pro?source=ovi) for more credits and features!
330
  """
331
  )
332
 
333
+ # How to Use section
334
+ with gr.Accordion("πŸ“– How to Use", open=False):
335
+ gr.Markdown(
336
+ """
337
+ ### Getting Started:
338
+ 1. **Sign in** with your Hugging Face account using the button above
339
+ 2. **Upload** your image - any photo or illustration
340
+ 3. **Describe** the motion and audio you want in the prompt
341
+ 4. **Use special tokens** for speech and audio descriptions (optional but recommended)
342
+ 5. **Generate** and watch your image come to life with synchronized audio!
343
+
344
+ ### Special Tokens Guide:
345
+
346
+ **Speech Token**: `<S>text<E>`
347
+ - Use this to add spoken dialogue to your video
348
+ - Example: `The person says <S>Hello, how are you?<E>`
349
+
350
+ **Audio Description Token**: `<AUDCAP>description<ENDAUDCAP>`
351
+ - Use this to describe background sounds and audio effects
352
+ - Example: `<AUDCAP>Birds chirping, gentle wind blowing<ENDAUDCAP>`
353
+
354
+ ### Tips for Better Results:
355
+ - Be specific and descriptive in your prompts
356
+ - Combine visual motion descriptions with audio elements
357
+ - Use high-quality input images for better results
358
+ - Experiment with different prompts and special tokens
359
+ - Processing takes 30-60 seconds per generation
360
+
361
+ ### ⚠️ Important Notes:
362
+ - This is a **paid app** that uses your inference provider credits
363
+ - Each generation consumes credits based on processing time
364
+ - Free accounts have limited credits ($0.10)
365
+ - PRO accounts get more credits ($2) and can continue with billing
366
+ - Videos are 5 seconds long at 24 FPS
367
+ - Supports multiple aspect ratios (9:16, 16:9, 1:1, etc)
368
+ """
369
+ )
370
 
371
  gr.Markdown(
372
  """
373
  ---
374
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
375
  ### πŸ”— Resources
376
 
377
  - [Ovi Model Card](https://huggingface.co/chetwinlow1/Ovi)
378
  - [Character AI](https://character.ai)
379
+ - [Hugging Face Inference API Docs](https://huggingface.co/docs/huggingface_hub/guides/inference)
380
+ - [Subscribe to PRO](http://huggingface.co/subscribe/pro?source=ovi)
381
+
382
+ ### πŸ“Š Model Specifications
383
+
384
+ - **Provider**: fal-ai
385
+ - **Model**: chetwinlow1/Ovi
386
+ - **Output**: 5-second videos at 24 FPS with audio
387
+ - **Input**: Image + Text prompt
388
+ - **Resolution**: 720Γ—720 area (various aspect ratios)
389
  """
390
  )
391
+
392
+ # Event handlers with authentication
393
+ generate_btn.click(
394
+ fn=generate_video_with_auth,
395
+ inputs=[image_input, prompt_input, login_btn],
396
+ outputs=[video_output, status_output],
397
+ show_progress="full",
398
+ queue=False,
399
+ api_name=False,
400
+ show_api=False,
401
+ )
402
+
403
+ clear_btn.click(
404
+ fn=clear_all,
405
+ inputs=[],
406
+ outputs=[image_input, prompt_input, video_output, status_output],
407
+ queue=False,
408
+ )
409
 
410
  # Launch the app
411
  if __name__ == "__main__":
412
+ try:
413
+ cleanup_temp_files()
414
+ if os.path.exists("gradio_cached_examples"):
415
+ shutil.rmtree("gradio_cached_examples", ignore_errors=True)
416
+ except Exception as e:
417
+ print(f"Initial cleanup error: {e}")
418
+
419
+ demo.queue(status_update_rate="auto", api_open=False, default_concurrency_limit=None)
420
  demo.launch(
421
  show_api=False,
422
+ share=False,
423
+ show_error=True,
424
  enable_monitoring=False,
425
  quiet=True,
426
  )