ghostai1 commited on
Commit
8576125
·
verified ·
1 Parent(s): f134c08

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +27 -24
app.py CHANGED
@@ -2,8 +2,15 @@
2
  # FILE: app.py
3
  # Description: Image-to-Video generation server with Gradio UI and FastAPI for Hugging Face Spaces
4
  # Version: 1.2.8
5
- # Timestamp: 2025-07-02 03:00 CDT
6
-
 
 
 
 
 
 
 
7
  # Requires custom diffusers_helper package in /diffusers_helper
8
 
9
  import os
@@ -107,7 +114,7 @@ args = parser.parse_args()
107
  render_on_off = True
108
 
109
  BASE = os.path.abspath(os.path.dirname(__file__))
110
- os.environ["HF_HOME"] = "/tmp/hf_cache" # Cache models in /tmp
111
 
112
  # Check if ports are available
113
  def is_port_in_use(port):
@@ -134,7 +141,7 @@ INSTALL_LOG_FILE = "/data/install_logs.txt"
134
  LAST_CLEANUP_FILE = "/data/last_cleanup.txt"
135
 
136
  # Initialize directories
137
- for d in (DATA_DIR, TMP_DIR, VIDEO_OUTPUT_DIR, VIDEO_IMG_DIR, VIDEO_TMP_DIR):
138
  if not os.path.exists(d):
139
  try:
140
  os.makedirs(d, exist_ok=True)
@@ -413,36 +420,36 @@ logger.info(f"VRAM available: {free_mem:.2f} GB, High VRAM mode: {hv}")
413
  print(f"{yellow(f'VRAM available: {free_mem:.2f} GB, High VRAM mode: {hv}')}")
414
 
415
  try:
416
- print(f"{yellow('Loading models...')}")
417
  text_encoder = LlamaModel.from_pretrained(
418
- "hunyuanvideo-community/HunyuanVideo", subfolder="text_encoder", torch_dtype=torch.float16, token=HF_TOKEN, cache_dir="/tmp/hf_cache"
419
  ).cpu().eval()
420
  text_encoder_2 = CLIPTextModel.from_pretrained(
421
- "hunyuanvideo-community/HunyuanVideo", subfolder="text_encoder_2", torch_dtype=torch.float16, token=HF_TOKEN, cache_dir="/tmp/hf_cache"
422
  ).cpu().eval()
423
  tokenizer = LlamaTokenizerFast.from_pretrained(
424
- "hunyuanvideo-community/HunyuanVideo", subfolder="tokenizer", token=HF_TOKEN, cache_dir="/tmp/hf_cache"
425
  )
426
  tokenizer_2 = CLIPTokenizer.from_pretrained(
427
- "hunyuanvideo-community/HunyuanVideo", subfolder="tokenizer_2", token=HF_TOKEN, cache_dir="/tmp/hf_cache"
428
  )
429
  vae = AutoencoderKLHunyuanVideo.from_pretrained(
430
- "hunyuanvideo-community/HunyuanVideo", subfolder="vae", torch_dtype=torch.float16, token=HF_TOKEN, cache_dir="/tmp/hf_cache"
431
  ).cpu().eval()
432
  feature_extractor = SiglipImageProcessor.from_pretrained(
433
- "lllyasviel/flux_redux_bfl", subfolder="feature_extractor", token=HF_TOKEN, cache_dir="/tmp/hf_cache"
434
  )
435
  image_encoder = SiglipVisionModel.from_pretrained(
436
- "lllyasviel/flux_redux_bfl", subfolder="image_encoder", torch_dtype=torch.float16, token=HF_TOKEN, cache_dir="/tmp/hf_cache"
437
  ).cpu().eval()
438
  transformer = HunyuanVideoTransformer3DModelPacked.from_pretrained(
439
- "lllyasviel/FramePack_F1_I2V_HY_20250503", torch_dtype=torch.bfloat16, token=HF_TOKEN, cache_dir="/tmp/hf_cache"
440
  ).cpu().eval()
441
- logger.info("Models loaded successfully")
442
- print(f"{green('Models loaded successfully')}")
443
  except Exception as e:
444
  logger.error(f"Failed to load models: {e}", exc_info=True)
445
- print(f"{red(f'Error: Failed to load models: {e}')}")
446
  raise
447
 
448
  if not hv:
@@ -539,6 +546,7 @@ async def test_server():
539
  },
540
  "paths": {
541
  "base": BASE,
 
542
  "images": VIDEO_IMG_DIR,
543
  "videos": VIDEO_OUTPUT_DIR,
544
  "temp": VIDEO_TMP_DIR,
@@ -553,6 +561,7 @@ async def test_server():
553
  "videos_writable": os.access(VIDEO_OUTPUT_DIR, os.W_OK),
554
  "temp_writable": os.access(VIDEO_TMP_DIR, os.W_OK),
555
  "data_writable": os.access(DATA_DIR, os.W_OK),
 
556
  },
557
  "dependencies": {
558
  "xformers": status_xformers(),
@@ -613,7 +622,7 @@ async def stop_render(job_id: str, api_key: str = Depends(verify_api_key)):
613
  logger.info(f"No active job {job_id} to stop")
614
  print(f"{yellow(f'No active job {job_id} to stop')}")
615
  return JSONResponse(content={"message": f"No active job {job_id}"})
616
- stream = active_jobs[job_id]
617
  stream.stop()
618
  active_jobs.pop(job_id, None)
619
  job_status[job_id]["status"] = "stopped"
@@ -1365,10 +1374,4 @@ if __name__ == "__main__":
1365
  logger.info(f"Public Gradio URL: {server.share_url}")
1366
  print(f"{yellow(f'Public Gradio URL: {server.share_url}')}")
1367
  logger.info(f"Gradio UI running on http://{args.server}:7860")
1368
- print(f"{green(f'Gradio UI running on http://{args.server}:7860')}")
1369
- while True:
1370
- time.sleep(1)
1371
- except KeyboardInterrupt:
1372
- logger.info("Shutting down gracefully")
1373
- print(f"{green('Shutting down gracefully')}")
1374
- sys.exit(0)
 
2
  # FILE: app.py
3
  # Description: Image-to-Video generation server with Gradio UI and FastAPI for Hugging Face Spaces
4
  # Version: 1.2.8
5
+ # Timestamp: 2025-07-02 03:20 CDT
6
+ # Author: Grok 3, built by xAI (based on GhostAI's ghostpack_gradio_f1.py)
7
+ # NOTE: Optimized for Hugging Face Spaces with H200 GPU, 25 min/day render time
8
+ # Loads models from /data/models (pre-downloaded)
9
+ # Uses /data for persistent storage, /tmp for temporary files
10
+ # API key authentication for /generate endpoint (off-site use)
11
+ # Base64-encoded video responses
12
+ # Gradio UI matches original ghostpack_gradio_f1.py
13
+ # Idle until triggered by API or Gradio
14
  # Requires custom diffusers_helper package in /diffusers_helper
15
 
16
  import os
 
114
  render_on_off = True
115
 
116
  BASE = os.path.abspath(os.path.dirname(__file__))
117
+ MODEL_DIR = "/data/models"
118
 
119
  # Check if ports are available
120
  def is_port_in_use(port):
 
141
  LAST_CLEANUP_FILE = "/data/last_cleanup.txt"
142
 
143
  # Initialize directories
144
+ for d in (DATA_DIR, TMP_DIR, VIDEO_OUTPUT_DIR, VIDEO_IMG_DIR, VIDEO_TMP_DIR, MODEL_DIR):
145
  if not os.path.exists(d):
146
  try:
147
  os.makedirs(d, exist_ok=True)
 
420
  print(f"{yellow(f'VRAM available: {free_mem:.2f} GB, High VRAM mode: {hv}')}")
421
 
422
  try:
423
+ print(f"{yellow('Loading models from /data/models...')}")
424
  text_encoder = LlamaModel.from_pretrained(
425
+ os.path.join(MODEL_DIR, "hunyuanvideo-community/HunyuanVideo/text_encoder"), torch_dtype=torch.float16
426
  ).cpu().eval()
427
  text_encoder_2 = CLIPTextModel.from_pretrained(
428
+ os.path.join(MODEL_DIR, "hunyuanvideo-community/HunyuanVideo/text_encoder_2"), torch_dtype=torch.float16
429
  ).cpu().eval()
430
  tokenizer = LlamaTokenizerFast.from_pretrained(
431
+ os.path.join(MODEL_DIR, "hunyuanvideo-community/HunyuanVideo/tokenizer")
432
  )
433
  tokenizer_2 = CLIPTokenizer.from_pretrained(
434
+ os.path.join(MODEL_DIR, "hunyuanvideo-community/HunyuanVideo/tokenizer_2")
435
  )
436
  vae = AutoencoderKLHunyuanVideo.from_pretrained(
437
+ os.path.join(MODEL_DIR, "hunyuanvideo-community/HunyuanVideo/vae"), torch_dtype=torch.float16
438
  ).cpu().eval()
439
  feature_extractor = SiglipImageProcessor.from_pretrained(
440
+ os.path.join(MODEL_DIR, "lllyasviel/flux_redux_bfl/feature_extractor")
441
  )
442
  image_encoder = SiglipVisionModel.from_pretrained(
443
+ os.path.join(MODEL_DIR, "lllyasviel/flux_redux_bfl/image_encoder"), torch_dtype=torch.float16
444
  ).cpu().eval()
445
  transformer = HunyuanVideoTransformer3DModelPacked.from_pretrained(
446
+ os.path.join(MODEL_DIR, "lllyasviel/FramePack_F1_I2V_HY_20250503"), torch_dtype=torch.bfloat16
447
  ).cpu().eval()
448
+ logger.info("Models loaded successfully from /data/models")
449
+ print(f"{green('Models loaded successfully from /data/models')}")
450
  except Exception as e:
451
  logger.error(f"Failed to load models: {e}", exc_info=True)
452
+ print(f"{red(f'Error: Failed to load models from /data/models: {e}')}")
453
  raise
454
 
455
  if not hv:
 
546
  },
547
  "paths": {
548
  "base": BASE,
549
+ "models": MODEL_DIR,
550
  "images": VIDEO_IMG_DIR,
551
  "videos": VIDEO_OUTPUT_DIR,
552
  "temp": VIDEO_TMP_DIR,
 
561
  "videos_writable": os.access(VIDEO_OUTPUT_DIR, os.W_OK),
562
  "temp_writable": os.access(VIDEO_TMP_DIR, os.W_OK),
563
  "data_writable": os.access(DATA_DIR, os.W_OK),
564
+ "models_writable": os.access(MODEL_DIR, os.W_OK),
565
  },
566
  "dependencies": {
567
  "xformers": status_xformers(),
 
622
  logger.info(f"No active job {job_id} to stop")
623
  print(f"{yellow(f'No active job {job_id} to stop')}")
624
  return JSONResponse(content={"message": f"No active job {job_id}"})
625
+ stream = active_jobs[jid]
626
  stream.stop()
627
  active_jobs.pop(job_id, None)
628
  job_status[job_id]["status"] = "stopped"
 
1374
  logger.info(f"Public Gradio URL: {server.share_url}")
1375
  print(f"{yellow(f'Public Gradio URL: {server.share_url}')}")
1376
  logger.info(f"Gradio UI running on http://{args.server}:7860")
1377
+ print