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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +55 -38
app.py CHANGED
@@ -23,15 +23,6 @@ def cleanup_temp_files():
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,30 +32,33 @@ def _save_bytes_as_temp_mp4(data: bytes) -> str:
41
  finally:
42
  temp_file.close()
43
 
44
- def generate_video_with_auth(image, prompt, token: gr.OAuthToken | None):
45
  """
46
  Generate a video from an image using the Ovi model with authentication check.
47
 
48
  Args:
49
  image: Input image (PIL Image or file path)
50
  prompt: Text prompt describing the desired motion/animation
51
- token: OAuth token for authentication
 
52
 
53
  Returns:
54
- Tuple of (video_path, status_message)
55
  """
56
  try:
57
- if token is None or not getattr(token, "token", None):
58
- return None, " Sign in with Hugging Face to continue. This app uses your inference provider credits."
59
 
60
  if image is None:
61
- return None, "Please upload an image first!"
62
 
63
  if not prompt or prompt.strip() == "":
64
- return None, "Please enter a prompt describing the desired motion!"
65
 
66
  cleanup_temp_files()
67
 
 
 
68
  # Read the image file
69
  if isinstance(image, str):
70
  with open(image, "rb") as image_file:
@@ -86,8 +80,19 @@ def generate_video_with_auth(image, prompt, token: gr.OAuthToken | None):
86
  pil_image.save(buffer, format='PNG')
87
  input_image = buffer.getvalue()
88
 
89
- # Create client with user's token
90
- client = _client_from_token(token.token)
 
 
 
 
 
 
 
 
 
 
 
91
 
92
  # Generate video using the inference client
93
  try:
@@ -99,22 +104,26 @@ def generate_video_with_auth(image, prompt, token: gr.OAuthToken | None):
99
  except Exception as e:
100
  import requests
101
  if isinstance(e, requests.HTTPError) and getattr(e.response, "status_code", None) == 403:
102
- return None, "Access denied by provider (403). Make sure your HF account has credits/permission for provider 'fal-ai' and model 'chetwinlow1/Ovi'."
103
  raise
104
 
 
 
105
  # Save the video to a temporary file
106
  video_path = _save_bytes_as_temp_mp4(video)
107
 
108
- return video_path, f"✅ Video generated successfully with motion: '{prompt[:50]}...'"
 
 
109
 
110
- except gr.Error as e:
111
- return None, f"❌ {str(e)}"
112
  except Exception as e:
113
- return None, f"Generation failed. If this keeps happening, check your provider quota or try again later."
114
 
115
  def clear_inputs():
116
  """Clear all inputs and outputs"""
117
- return None, "", None, ""
118
 
119
  # Custom CSS for better styling
120
  custom_css = """
@@ -152,6 +161,12 @@ custom_css = """
152
  margin: 1em 0;
153
  border-radius: 4px;
154
  }
 
 
 
 
 
 
155
  """
156
 
157
  # Create the Gradio interface
@@ -182,8 +197,16 @@ with gr.Blocks(css=custom_css, theme=gr.themes.Soft(), title="Image to Video Gen
182
  """
183
  )
184
 
 
 
 
 
 
 
 
 
185
  # Add login button - required for OAuth
186
- login_btn = gr.LoginButton("Sign in with Hugging Face")
187
 
188
  gr.HTML(
189
  """
@@ -236,18 +259,12 @@ with gr.Blocks(css=custom_css, theme=gr.themes.Soft(), title="Image to Video Gen
236
  scale=2,
237
  )
238
 
239
- clear_btn = gr.ClearButton(
240
- value="🗑️ Clear",
 
241
  scale=1,
242
  )
243
 
244
- status = gr.Textbox(
245
- label="Status",
246
- interactive=False,
247
- visible=True,
248
- elem_classes=["status-box"]
249
- )
250
-
251
  gr.Examples(
252
  examples=[
253
  [
@@ -285,11 +302,11 @@ with gr.Blocks(css=custom_css, theme=gr.themes.Soft(), title="Image to Video Gen
285
  """
286
  )
287
 
288
- # Event handlers with authentication
289
  generate_btn.click(
290
  fn=generate_video_with_auth,
291
- inputs=[image_input, prompt_input, login_btn],
292
- outputs=[video_output, status],
293
  show_progress="full",
294
  queue=False,
295
  api_name=False,
@@ -299,7 +316,7 @@ with gr.Blocks(css=custom_css, theme=gr.themes.Soft(), title="Image to Video Gen
299
  clear_btn.click(
300
  fn=clear_inputs,
301
  inputs=[],
302
- outputs=[image_input, prompt_input, video_output, status],
303
  queue=False,
304
  )
305
 
 
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
  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:
 
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:
 
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 = """
 
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
 
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
  """
 
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
  [
 
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,
 
316
  clear_btn.click(
317
  fn=clear_inputs,
318
  inputs=[],
319
+ outputs=[image_input, prompt_input, video_output],
320
  queue=False,
321
  )
322