Files changed (1) hide show
  1. app.py +78 -0
app.py ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import shutil
3
+ import subprocess
4
+ import spaces
5
+ import gradio as gr
6
+ from pathlib import Path
7
+ from huggingface_hub import snapshot_download
8
+
9
+ # --- 1. CONFIGURATION & WEIGHT HYDRATION ---
10
+ REPO_ID = "Macfeigh/visor-weights"
11
+ CHECKPOINT_DIR = "/app/SadTalker/checkpoints"
12
+
13
+ def hydrate_workspace():
14
+ # Clone SadTalker and Wav2Lip if they don't exist
15
+ if not os.path.exists("/app/SadTalker"):
16
+ print("📥 Cloning SadTalker...")
17
+ subprocess.run(["git", "clone", "https://github.com/OpenTalker/SadTalker.git", "/app/SadTalker"])
18
+
19
+ if not os.path.exists("/app/Wav2Lip"):
20
+ print("📥 Cloning Wav2Lip...")
21
+ subprocess.run(["git", "clone", "https://github.com/Rudrabha/Wav2Lip.git", "/app/Wav2Lip"])
22
+
23
+ # Download weights from your model repo
24
+ print(f"🌡️ Pulling weights from {REPO_ID}...")
25
+ snapshot_download(
26
+ repo_id=REPO_ID,
27
+ local_dir=CHECKPOINT_DIR,
28
+ local_dir_use_symlinks=False
29
+ )
30
+ print("✅ Weights ready.")
31
+
32
+ # Initialize workspace before Gradio starts
33
+ hydrate_workspace()
34
+
35
+ # --- 2. GPU INFERENCE ENGINE ---
36
+ @spaces.GPU(duration=120)
37
+ def visor_execute(image_path, audio_path):
38
+ output_dir = "/tmp/visor_output"
39
+ if os.path.exists(output_dir):
40
+ shutil.rmtree(output_dir)
41
+ os.makedirs(output_dir, exist_ok=True)
42
+
43
+ print("🚀 Executing Phase 3: Animation...")
44
+
45
+ # Run SadTalker
46
+ st_proc = subprocess.run([
47
+ "python", "/app/SadTalker/inference.py",
48
+ "--driven_audio", audio_path,
49
+ "--source_image", image_path,
50
+ "--result_dir", output_dir,
51
+ "--still",
52
+ "--preprocess", "full",
53
+ "--checkpoint_dir", CHECKPOINT_DIR
54
+ ], env={**os.environ, "PYTHONPATH": "/app/SadTalker"})
55
+
56
+ # Find result
57
+ generated_videos = list(Path(output_dir).glob("**/*.mp4"))
58
+ if not generated_videos:
59
+ return None
60
+
61
+ return str(generated_videos[0])
62
+
63
+ # --- 3. INTERFACE ---
64
+ with gr.Blocks(theme=gr.themes.Soft()) as demo:
65
+ gr.Markdown("# 🛡️ VisorFlow Core: Sovereign Intelligence Node")
66
+ gr.Markdown("Zero-cost execution environment running on NVIDIA H200.")
67
+
68
+ with gr.Row():
69
+ with gr.Column():
70
+ img = gr.Image(type="filepath", label="Source Portrait")
71
+ aud = gr.Audio(type="filepath", label="Voice Command")
72
+ btn = gr.Button("RUN PHASE 3", variant="primary")
73
+ with gr.Column():
74
+ out = gr.Video(label="Generated Output")
75
+
76
+ btn.click(fn=visor_execute, inputs=[img, aud], outputs=[out])
77
+
78
+ demo.launch()