akhaliq HF Staff commited on
Commit
b87c1b6
Β·
verified Β·
1 Parent(s): e34f60e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +146 -254
app.py CHANGED
@@ -1,192 +1,179 @@
 
1
  import os
2
- import time
3
  import tempfile
4
  import shutil
5
- from pathlib import Path
6
  from typing import Optional, Tuple, Union
7
-
8
- import gradio as gr
9
  from huggingface_hub import InferenceClient, whoami
 
10
 
11
- # =========================
12
- # Inference client (fal-ai)
13
- # =========================
14
  client = InferenceClient(
15
  provider="fal-ai",
16
  api_key=os.environ.get("HF_TOKEN"),
17
  bill_to="huggingface",
18
  )
19
 
20
- # =========================
21
- # Auth / PRO helpers
22
- # =========================
23
  def verify_pro_status(token: Optional[Union[gr.OAuthToken, str]]) -> bool:
24
  """Verifies if the user is a Hugging Face PRO user or part of an enterprise org."""
25
  if not token:
26
  return False
27
-
28
  if isinstance(token, gr.OAuthToken):
29
  token_str = token.token
30
  elif isinstance(token, str):
31
  token_str = token
32
  else:
33
  return False
34
-
35
  try:
36
  user_info = whoami(token=token_str)
37
  return (
38
- user_info.get("isPro", False)
39
- or any(org.get("isEnterprise", False) for org in user_info.get("orgs", []))
40
  )
41
  except Exception as e:
42
  print(f"Could not verify user's PRO/Enterprise status: {e}")
43
  return False
44
 
45
- # =========================
46
- # Storage hygiene
47
- # =========================
48
  def cleanup_temp_files():
49
- """Clean up old temporary .mp4 files to prevent storage overflow."""
50
  try:
51
  temp_dir = tempfile.gettempdir()
 
52
  for file_path in Path(temp_dir).glob("*.mp4"):
53
  try:
54
  # Remove files older than 5 minutes
 
55
  if file_path.stat().st_mtime < (time.time() - 300):
56
  file_path.unlink(missing_ok=True)
57
  except Exception:
58
- pass # Ignore errors for individual files
59
  except Exception as e:
60
  print(f"Cleanup error: {e}")
61
 
62
- def _write_video_bytes_to_tempfile(video_bytes: bytes) -> str:
63
- temp_file = tempfile.NamedTemporaryFile(suffix=".mp4", delete=False)
64
- try:
65
- temp_file.write(video_bytes)
66
- temp_file.flush()
67
- return temp_file.name
68
- finally:
69
- temp_file.close()
70
-
71
- # =========================
72
- # Generation (Text β†’ Video)
73
- # =========================
74
  def generate_video(
75
  prompt: str,
76
  duration: int = 8,
77
  size: str = "1280x720",
78
- api_key: Optional[str] = None,
79
  ) -> Tuple[Optional[str], str]:
80
- """
81
- Generate video using Sora-2 via Hugging Face Inference API (fal-ai provider).
82
- Returns (video_path, status_message).
83
- """
84
  cleanup_temp_files()
85
-
86
  try:
87
- # Use provided API key or environment variable
88
- temp_client = (
89
- InferenceClient(provider="fal-ai", api_key=api_key, bill_to="huggingface")
90
- if api_key
91
- else client
92
- )
93
- if not (api_key or os.environ.get("HF_TOKEN")):
94
- return None, "❌ Please set HF_TOKEN environment variable."
95
-
96
- # Call text-to-video
 
97
  video_bytes = temp_client.text_to_video(
98
  prompt,
99
  model="akhaliq/sora-2",
100
- # If your backend supports these, you can forward them as kwargs:
101
- # duration=duration,
102
- # size=size,
103
  )
104
-
105
- video_path = _write_video_bytes_to_tempfile(video_bytes)
 
 
 
 
 
 
 
106
  return video_path, "βœ… Video generated successfully!"
107
  except Exception as e:
108
  return None, f"❌ Error generating video: {str(e)}"
109
 
110
- # =========================
111
- # Generation (Image β†’ Video)
112
- # =========================
113
  def generate_video_from_image(
 
114
  prompt: str,
115
- image_path: str,
116
- api_key: Optional[str] = None,
117
  ) -> Tuple[Optional[str], str]:
118
- """
119
- Generate video from a single input image using Sora-2 image-to-video.
120
- Returns (video_path, status_message).
121
- """
122
  cleanup_temp_files()
123
-
124
- if not image_path or not Path(image_path).exists():
125
- return None, "❌ Please upload an image."
126
-
127
  try:
128
- temp_client = (
129
- InferenceClient(provider="fal-ai", api_key=api_key, bill_to="huggingface")
130
- if api_key
131
- else client
132
- )
133
- if not (api_key or os.environ.get("HF_TOKEN")):
134
- return None, "❌ Please set HF_TOKEN environment variable."
135
-
136
- with open(image_path, "rb") as f:
137
- input_image = f.read()
 
 
 
 
 
 
 
 
138
 
139
  video_bytes = temp_client.image_to_video(
140
  input_image,
141
- prompt=prompt or "",
142
  model="akhaliq/sora-2-image-to-video",
143
  )
144
 
145
- video_path = _write_video_bytes_to_tempfile(video_bytes)
146
- return video_path, "βœ… Video generated successfully from image!"
 
 
 
 
 
 
 
147
  except Exception as e:
148
  return None, f"❌ Error generating video from image: {str(e)}"
149
 
150
- # =========================
151
- # PRO wrapper (uses request)
152
- # =========================
153
  def generate_with_pro_auth(
154
- mode: str,
155
- prompt: str,
156
- image_path: Optional[str],
157
- request: gr.Request,
158
  ) -> Tuple[Optional[str], str]:
159
- """
160
- Check PRO status from the request's OAuth token, then route to the
161
- appropriate generation function based on mode.
162
- """
163
- oauth_token = getattr(request, "oauth_token", None)
164
  if not verify_pro_status(oauth_token):
165
- raise gr.Error(
166
- "Access Denied. This app is exclusively for Hugging Face PRO users. Please subscribe to PRO to use this app."
167
- )
168
-
169
- if mode == "Text β†’ Video":
170
- if not prompt or not prompt.strip():
171
- return None, "❌ Please enter a prompt."
172
- return generate_video(prompt, duration=8, size="1280x720", api_key=None)
 
 
 
173
 
174
- # Image β†’ Video
 
 
 
 
 
 
 
 
175
  if not image_path:
176
- return None, "❌ Please upload an image."
177
- # Prompt is optional for image→video; pass empty string if not provided
178
- return generate_video_from_image(prompt or "", image_path, api_key=None)
179
 
180
  def simple_generate(prompt: str) -> Optional[str]:
181
- """Examples: only return the video path (text→video)."""
182
- if not prompt or not prompt.strip():
183
  return None
184
  video_path, _ = generate_video(prompt, duration=8, size="1280x720", api_key=None)
185
  return video_path
186
 
187
- # =========================
188
- # UI
189
- # =========================
190
  def create_ui():
191
  css = '''
192
  .logo-dark{display: none}
@@ -204,7 +191,7 @@ def create_ui():
204
  margin-left: 8px;
205
  }
206
  '''
207
-
208
  with gr.Blocks(title="Sora-2 Text-to-Video Generator", theme=gr.themes.Soft(), css=css) as demo:
209
  gr.HTML("""
210
  <div style="text-align: center; max-width: 800px; margin: 0 auto;">
@@ -222,182 +209,87 @@ def create_ui():
222
  </p>
223
  </div>
224
  """)
225
-
226
- # HF OAuth (Spaces must have hf_oauth: true)
227
  gr.LoginButton()
228
-
229
- # Hidden by default; we’ll toggle based on PRO status
230
  pro_message = gr.Markdown(visible=False)
231
  main_interface = gr.Column(visible=False)
232
-
233
  with main_interface:
234
- gr.HTML("""
235
- <div style="text-align: center; margin: 20px 0;">
236
- <p style="color: #28a745; font-weight: bold;">✨ Welcome PRO User! You have full access to Sora-2.</p>
237
- </div>
238
- """)
239
-
240
  with gr.Row():
241
  with gr.Column(scale=1):
242
- mode_radio = gr.Radio(
243
- choices=["Text β†’ Video", "Image β†’ Video"],
244
- value="Text β†’ Video",
245
- label="Mode",
246
- )
247
  prompt_input = gr.Textbox(
248
- label="Prompt",
249
- placeholder="Describe the video you want to create (optional for image→video)...",
250
- lines=4,
251
  )
252
-
253
- image_group = gr.Group(visible=False)
254
- with image_group:
255
- image_input = gr.Image(
256
- label="Input Image (for Image β†’ Video)",
257
- type="filepath",
258
- sources=["upload", "clipboard"],
259
- image_mode="RGB",
260
- )
261
-
262
- with gr.Accordion("Advanced Settings", open=False):
263
- gr.Markdown("*Coming soon: Duration and resolution controls*")
264
-
265
  generate_btn = gr.Button("πŸŽ₯ Generate Video", variant="primary", size="lg")
266
-
267
  with gr.Column(scale=1):
268
- video_output = gr.Video(
269
- label="Generated Video",
270
- height=400,
271
- interactive=False,
272
- show_download_button=True,
273
- )
274
- status_output = gr.Textbox(
275
- label="Status",
276
- interactive=False,
277
- visible=True,
278
- )
279
-
280
- # Examples (text→video only)
281
- gr.Examples(
282
- examples=[
283
- "A serene beach at sunset with waves gently rolling onto the shore",
284
- "A butterfly emerging from its chrysalis in slow motion",
285
- "Northern lights dancing across a starry night sky",
286
- "A bustling city street transitioning from day to night in timelapse",
287
- "A close-up of coffee being poured into a cup with steam rising",
288
- "Cherry blossoms falling in slow motion in a Japanese garden",
289
- ],
290
- inputs=prompt_input,
291
- outputs=video_output,
292
- fn=simple_generate,
293
- cache_examples=False,
294
- api_name=False,
295
- show_api=False,
296
- )
297
-
298
- # Toggle image upload visibility with mode
299
- def _toggle_image_group(mode: str):
300
- return gr.update(visible=(mode == "Image β†’ Video"))
301
-
302
- mode_radio.change(
303
- _toggle_image_group,
304
- inputs=[mode_radio],
305
- outputs=[image_group],
306
- show_progress=False,
307
- )
308
-
309
- # Generation handler (uses request to read OAuth token)
310
  generate_btn.click(
311
  fn=generate_with_pro_auth,
312
- inputs=[mode_radio, prompt_input, image_input],
313
  outputs=[video_output, status_output],
314
- queue=False,
315
- api_name=False,
316
- show_api=False,
317
  )
318
 
319
- # Footer
320
  gr.HTML("""
321
- <div style="text-align: center; margin-top: 40px; padding: 20px; border-top: 1px solid #e0e0e0;">
322
- <h3 style="color: #667eea;">Thank you for being a PRO user! πŸ€—</h3>
 
323
  </div>
324
  """)
325
-
326
- # Use request to check access on load
327
- def control_access(request: gr.Request):
328
- oauth_profile = getattr(request, "oauth_profile", None)
329
- oauth_token = getattr(request, "oauth_token", None)
330
-
331
- if not oauth_profile:
332
- # Not logged in
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
333
  return gr.update(visible=False), gr.update(visible=False)
334
-
335
  if verify_pro_status(oauth_token):
336
  return gr.update(visible=True), gr.update(visible=False)
337
  else:
338
- message = """
339
- ## ✨ Exclusive Access for PRO Users
340
-
341
- Thank you for your interest in the Sora-2 Text-to-Video Generator!
342
-
343
- This advanced AI video generation tool is available exclusively for Hugging Face **PRO** members.
344
-
345
- ### What you get with PRO:
346
- - βœ… Unlimited access to Sora-2 video generation
347
- - βœ… High-quality video outputs up to 1280x720
348
- - βœ… Fast generation times with priority queue
349
- - βœ… Access to other exclusive PRO Spaces
350
- - βœ… Support the development of cutting-edge AI tools
351
-
352
- ### Ready to create amazing videos?
353
-
354
- <div style="text-align: center; margin: 30px 0;">
355
- <a href="http://huggingface.co/subscribe/pro?source=sora2_video" target="_blank" style="
356
- display: inline-block;
357
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
358
- color: white;
359
- padding: 12px 30px;
360
- border-radius: 25px;
361
- text-decoration: none;
362
- font-weight: bold;
363
- font-size: 1.1em;
364
- box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3);
365
- transition: transform 0.2s;
366
- ">
367
- πŸš€ Become a PRO Today!
368
- </a>
369
- </div>
370
-
371
- <p style="text-align: center; color: #666; margin-top: 20px;">
372
- Join thousands of creators who are already using PRO tools to bring their ideas to life.
373
- </p>
374
- """
375
  return gr.update(visible=False), gr.update(visible=True, value=message)
376
-
377
- demo.load(
378
- control_access,
379
- inputs=None,
380
- outputs=[main_interface, pro_message],
381
- )
382
-
383
  return demo
384
 
385
- # =========================
386
- # Entrypoint
387
- # =========================
388
  if __name__ == "__main__":
389
- # Clean up any leftover files on startup
390
  try:
391
  cleanup_temp_files()
392
  if os.path.exists("gradio_cached_examples"):
393
  shutil.rmtree("gradio_cached_examples", ignore_errors=True)
394
  except Exception as e:
395
  print(f"Initial cleanup error: {e}")
396
-
397
  app = create_ui()
398
- app.launch(
399
- show_api=False,
400
- enable_monitoring=False,
401
- quiet=True,
402
- max_threads=10,
403
- )
 
1
+ import gradio as gr
2
  import os
 
3
  import tempfile
4
  import shutil
 
5
  from typing import Optional, Tuple, Union
 
 
6
  from huggingface_hub import InferenceClient, whoami
7
+ from pathlib import Path
8
 
9
+ # Initialize Hugging Face Inference Client with fal-ai provider
 
 
10
  client = InferenceClient(
11
  provider="fal-ai",
12
  api_key=os.environ.get("HF_TOKEN"),
13
  bill_to="huggingface",
14
  )
15
 
 
 
 
16
  def verify_pro_status(token: Optional[Union[gr.OAuthToken, str]]) -> bool:
17
  """Verifies if the user is a Hugging Face PRO user or part of an enterprise org."""
18
  if not token:
19
  return False
20
+
21
  if isinstance(token, gr.OAuthToken):
22
  token_str = token.token
23
  elif isinstance(token, str):
24
  token_str = token
25
  else:
26
  return False
27
+
28
  try:
29
  user_info = whoami(token=token_str)
30
  return (
31
+ user_info.get("isPro", False) or
32
+ any(org.get("isEnterprise", False) for org in user_info.get("orgs", []))
33
  )
34
  except Exception as e:
35
  print(f"Could not verify user's PRO/Enterprise status: {e}")
36
  return False
37
 
 
 
 
38
  def cleanup_temp_files():
39
+ """Clean up old temporary video files to prevent storage overflow."""
40
  try:
41
  temp_dir = tempfile.gettempdir()
42
+ # Clean up old .mp4 files in temp directory
43
  for file_path in Path(temp_dir).glob("*.mp4"):
44
  try:
45
  # Remove files older than 5 minutes
46
+ import time
47
  if file_path.stat().st_mtime < (time.time() - 300):
48
  file_path.unlink(missing_ok=True)
49
  except Exception:
50
+ pass
51
  except Exception as e:
52
  print(f"Cleanup error: {e}")
53
 
 
 
 
 
 
 
 
 
 
 
 
 
54
  def generate_video(
55
  prompt: str,
56
  duration: int = 8,
57
  size: str = "1280x720",
58
+ api_key: Optional[str] = None
59
  ) -> Tuple[Optional[str], str]:
60
+ """Generate video using Sora-2 through Hugging Face Inference API with fal-ai provider."""
 
 
 
61
  cleanup_temp_files()
 
62
  try:
63
+ if api_key:
64
+ temp_client = InferenceClient(
65
+ provider="fal-ai",
66
+ api_key=api_key,
67
+ bill_to="huggingface",
68
+ )
69
+ else:
70
+ temp_client = client
71
+ if not os.environ.get("HF_TOKEN") and not api_key:
72
+ return None, "❌ Please set HF_TOKEN environment variable."
73
+
74
  video_bytes = temp_client.text_to_video(
75
  prompt,
76
  model="akhaliq/sora-2",
 
 
 
77
  )
78
+
79
+ temp_file = tempfile.NamedTemporaryFile(suffix=".mp4", delete=False)
80
+ try:
81
+ temp_file.write(video_bytes)
82
+ temp_file.flush()
83
+ video_path = temp_file.name
84
+ finally:
85
+ temp_file.close()
86
+
87
  return video_path, "βœ… Video generated successfully!"
88
  except Exception as e:
89
  return None, f"❌ Error generating video: {str(e)}"
90
 
91
+ # --- NEW: image -> video support ---
 
 
92
  def generate_video_from_image(
93
+ image: Union[str, bytes],
94
  prompt: str,
95
+ api_key: Optional[str] = None
 
96
  ) -> Tuple[Optional[str], str]:
97
+ """Generate a video from a single input image + prompt using Sora-2 image-to-video."""
 
 
 
98
  cleanup_temp_files()
99
+ if not prompt or prompt.strip() == "":
100
+ return None, "❌ Please enter a prompt"
 
 
101
  try:
102
+ if api_key:
103
+ temp_client = InferenceClient(
104
+ provider="fal-ai",
105
+ api_key=api_key,
106
+ bill_to="huggingface",
107
+ )
108
+ else:
109
+ temp_client = client
110
+ if not os.environ.get("HF_TOKEN") and not api_key:
111
+ return None, "❌ Please set HF_TOKEN environment variable."
112
+
113
+ if isinstance(image, str):
114
+ with open(image, "rb") as f:
115
+ input_image = f.read()
116
+ elif isinstance(image, (bytes, bytearray)):
117
+ input_image = image
118
+ else:
119
+ return None, "❌ Invalid image input. Please upload an image."
120
 
121
  video_bytes = temp_client.image_to_video(
122
  input_image,
123
+ prompt=prompt,
124
  model="akhaliq/sora-2-image-to-video",
125
  )
126
 
127
+ temp_file = tempfile.NamedTemporaryFile(suffix=".mp4", delete=False)
128
+ try:
129
+ temp_file.write(video_bytes)
130
+ temp_file.flush()
131
+ video_path = temp_file.name
132
+ finally:
133
+ temp_file.close()
134
+
135
+ return video_path, "βœ… Video generated from image successfully!"
136
  except Exception as e:
137
  return None, f"❌ Error generating video from image: {str(e)}"
138
 
 
 
 
139
  def generate_with_pro_auth(
140
+ prompt: str,
141
+ oauth_token: Optional[gr.OAuthToken] = None
 
 
142
  ) -> Tuple[Optional[str], str]:
143
+ """Wrapper function that checks if user is PRO before generating video."""
 
 
 
 
144
  if not verify_pro_status(oauth_token):
145
+ raise gr.Error("Access Denied. This app is exclusively for Hugging Face PRO users.")
146
+
147
+ if not prompt or prompt.strip() == "":
148
+ return None, "❌ Please enter a prompt"
149
+
150
+ return generate_video(
151
+ prompt,
152
+ duration=8,
153
+ size="1280x720",
154
+ api_key=None
155
+ )
156
 
157
+ # --- NEW: PRO-gated wrapper for image -> video ---
158
+ def generate_with_pro_auth_image(
159
+ prompt: str,
160
+ image_path: Optional[str] = None,
161
+ oauth_token: Optional[gr.OAuthToken] = None
162
+ ) -> Tuple[Optional[str], str]:
163
+ """Checks PRO status then calls image->video generator."""
164
+ if not verify_pro_status(oauth_token):
165
+ raise gr.Error("Access Denied. This app is exclusively for Hugging Face PRO users.")
166
  if not image_path:
167
+ return None, "❌ Please upload an image"
168
+ return generate_video_from_image(image=image_path, prompt=prompt, api_key=None)
 
169
 
170
  def simple_generate(prompt: str) -> Optional[str]:
171
+ """Simplified wrapper for examples that only returns video."""
172
+ if not prompt or prompt.strip() == "":
173
  return None
174
  video_path, _ = generate_video(prompt, duration=8, size="1280x720", api_key=None)
175
  return video_path
176
 
 
 
 
177
  def create_ui():
178
  css = '''
179
  .logo-dark{display: none}
 
191
  margin-left: 8px;
192
  }
193
  '''
194
+
195
  with gr.Blocks(title="Sora-2 Text-to-Video Generator", theme=gr.themes.Soft(), css=css) as demo:
196
  gr.HTML("""
197
  <div style="text-align: center; max-width: 800px; margin: 0 auto;">
 
209
  </p>
210
  </div>
211
  """)
212
+
 
213
  gr.LoginButton()
 
 
214
  pro_message = gr.Markdown(visible=False)
215
  main_interface = gr.Column(visible=False)
216
+
217
  with main_interface:
218
+ gr.HTML("""<div style="text-align: center; margin: 20px 0;">
219
+ <p style="color: #28a745; font-weight: bold;">✨ Welcome PRO User! You have full access to Sora-2.</p>
220
+ </div>""")
221
+
222
+ # Text -> Video
 
223
  with gr.Row():
224
  with gr.Column(scale=1):
 
 
 
 
 
225
  prompt_input = gr.Textbox(
226
+ label="Enter your prompt",
227
+ placeholder="Describe the video you want to create...",
228
+ lines=4
229
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
230
  generate_btn = gr.Button("πŸŽ₯ Generate Video", variant="primary", size="lg")
 
231
  with gr.Column(scale=1):
232
+ video_output = gr.Video(label="Generated Video", height=400, interactive=False, show_download_button=True)
233
+ status_output = gr.Textbox(label="Status", interactive=False, visible=True)
234
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
235
  generate_btn.click(
236
  fn=generate_with_pro_auth,
237
+ inputs=[prompt_input],
238
  outputs=[video_output, status_output],
239
+ queue=False
 
 
240
  )
241
 
242
+ # --- NEW: Image -> Video UI ---
243
  gr.HTML("""
244
+ <div style="text-align: center; margin: 40px 0 10px;">
245
+ <h3 style="margin-bottom: 8px;">πŸ–ΌοΈ ➜ 🎬 Image β†’ Video (beta)</h3>
246
+ <p style="color:#666; margin:0;">Turn a single image into a short video with a guiding prompt.</p>
247
  </div>
248
  """)
249
+ with gr.Row():
250
+ with gr.Column(scale=1):
251
+ img_prompt_input = gr.Textbox(
252
+ label="Describe how the scene should evolve",
253
+ placeholder="e.g., The cat starts to dance and spins playfully",
254
+ lines=3,
255
+ )
256
+ image_input = gr.Image(label="Upload an image", type="filepath")
257
+ generate_img_btn = gr.Button("πŸŽ₯ Generate from Image", variant="primary")
258
+ with gr.Column(scale=1):
259
+ video_output_img = gr.Video(label="Generated Video (from Image)", height=400, interactive=False, show_download_button=True)
260
+ status_output_img = gr.Textbox(label="Status", interactive=False, visible=True)
261
+
262
+ generate_img_btn.click(
263
+ fn=generate_with_pro_auth_image,
264
+ inputs=[img_prompt_input, image_input],
265
+ outputs=[video_output_img, status_output_img],
266
+ queue=False
267
+ )
268
+
269
+ gr.HTML("""<div style="text-align: center; margin-top: 40px; padding: 20px; border-top: 1px solid #e0e0e0;">
270
+ <h3 style="color: #667eea;">Thank you for being a PRO user! πŸ€—</h3>
271
+ </div>""")
272
+
273
+ def control_access(profile: Optional[gr.OAuthProfile] = None, oauth_token: Optional[gr.OAuthToken] = None):
274
+ if not profile:
275
  return gr.update(visible=False), gr.update(visible=False)
 
276
  if verify_pro_status(oauth_token):
277
  return gr.update(visible=True), gr.update(visible=False)
278
  else:
279
+ message = "## ✨ Exclusive Access for PRO Users\n\nThis tool is available exclusively for Hugging Face **PRO** members."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
280
  return gr.update(visible=False), gr.update(visible=True, value=message)
281
+
282
+ demo.load(control_access, inputs=None, outputs=[main_interface, pro_message])
283
+
 
 
 
 
284
  return demo
285
 
 
 
 
286
  if __name__ == "__main__":
 
287
  try:
288
  cleanup_temp_files()
289
  if os.path.exists("gradio_cached_examples"):
290
  shutil.rmtree("gradio_cached_examples", ignore_errors=True)
291
  except Exception as e:
292
  print(f"Initial cleanup error: {e}")
293
+
294
  app = create_ui()
295
+ app.launch(show_api=False, enable_monitoring=False, quiet=True, max_threads=10)