banao-tech commited on
Commit
ebe6c13
Β·
verified Β·
1 Parent(s): ff0ed1c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +78 -24
app.py CHANGED
@@ -1,6 +1,5 @@
1
- import os
2
- import shutil
3
  import subprocess
 
4
  from pathlib import Path
5
  import gradio as gr
6
 
@@ -9,40 +8,98 @@ SETUP_FLAG = Path("setup_done.txt")
9
  OUTPUT_DIR = Path("outputs")
10
  OUTPUT_DIR.mkdir(exist_ok=True)
11
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  def run(cmd, cwd=None):
13
- """
14
- Run a shell command safely and raise a helpful error if it fails.
15
- """
16
  p = subprocess.run(
17
  cmd,
18
  cwd=str(cwd) if cwd else None,
19
  stdout=subprocess.PIPE,
20
  stderr=subprocess.STDOUT,
21
  text=True,
22
- check=False
23
  )
24
  if p.returncode != 0:
25
- raise RuntimeError(f"Command failed ({p.returncode}): {' '.join(cmd)}\n\n{p.stdout}")
 
 
26
  return p.stdout
27
 
28
- def setup():
 
29
  """
30
- One-time setup: clone repo + download models.
31
- Uses a flag file so it doesn't redo work every request.
32
  """
33
- if SETUP_FLAG.exists() and REPO_DIR.exists():
 
 
34
  return
 
 
35
 
36
- print("Setting up Video-Retalking...")
 
 
37
 
38
- if not REPO_DIR.exists():
39
- run(["git", "clone", "https://github.com/OpenTalker/video-retalking.git", str(REPO_DIR)])
 
 
40
 
41
- # Download models (idempotent in most cases)
42
- run(["bash", "scripts/download_models.sh"], cwd=REPO_DIR)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
 
44
- SETUP_FLAG.touch()
45
- print("βœ… Setup complete!")
46
 
47
  def generate(image_path, audio_path):
48
  if not image_path or not audio_path:
@@ -59,14 +116,10 @@ def generate(image_path, audio_path):
59
  if not audio_path.exists():
60
  return None, f"❌ Audio not found: {audio_path}"
61
 
62
- # Unique output name per run
63
  out_path = (OUTPUT_DIR / "result.mp4").resolve()
64
-
65
- # Clean old output if any
66
  if out_path.exists():
67
  out_path.unlink()
68
 
69
- # Run inference
70
  cmd = [
71
  "python",
72
  "inference.py",
@@ -78,11 +131,12 @@ def generate(image_path, audio_path):
78
 
79
  if out_path.exists():
80
  return str(out_path), "βœ… Video generated successfully!"
81
- return None, "❌ Failed to generate video (no output file created)."
82
 
83
  except Exception as e:
84
  return None, f"❌ Error: {e}"
85
 
 
86
  demo = gr.Interface(
87
  fn=generate,
88
  inputs=[
@@ -91,7 +145,7 @@ demo = gr.Interface(
91
  ],
92
  outputs=[
93
  gr.Video(label="πŸ“Ή Generated Video"),
94
- gr.Textbox(label="Status", lines=3),
95
  ],
96
  title="🎬 Video-Retalking Lip Sync",
97
  description="Upload a face image and audio to generate a lip-synced video.",
 
 
 
1
  import subprocess
2
+ import threading
3
  from pathlib import Path
4
  import gradio as gr
5
 
 
8
  OUTPUT_DIR = Path("outputs")
9
  OUTPUT_DIR.mkdir(exist_ok=True)
10
 
11
+ # Hugging Face mirror containing the checkpoint files (fast + reliable)
12
+ HF_BASE = "https://huggingface.co/camenduru/video-retalking/resolve/main"
13
+
14
+ # Files needed by Video-Retalking pipeline (common minimal set)
15
+ CHECKPOINT_FILES = [
16
+ "30_net_gen.pth",
17
+ "BFM.zip",
18
+ "DNet.pt",
19
+ "ENet.pth",
20
+ "LNet.pth",
21
+ "ParseNet-latest.pth",
22
+ "RetinaFace-R50.pth",
23
+ "expression.mat",
24
+ "face3d_pretrain_epoch_20.pth",
25
+ "GFPGANv1.3.pth",
26
+ "GPEN-BFR-512.pth",
27
+ "shape_predictor_68_face_landmarks.dat",
28
+ ]
29
+
30
+ _setup_lock = threading.Lock()
31
+
32
+
33
  def run(cmd, cwd=None):
 
 
 
34
  p = subprocess.run(
35
  cmd,
36
  cwd=str(cwd) if cwd else None,
37
  stdout=subprocess.PIPE,
38
  stderr=subprocess.STDOUT,
39
  text=True,
40
+ check=False,
41
  )
42
  if p.returncode != 0:
43
+ raise RuntimeError(
44
+ f"Command failed ({p.returncode}): {' '.join(cmd)}\n\n{p.stdout}"
45
+ )
46
  return p.stdout
47
 
48
+
49
+ def download_file(url: str, dest: Path):
50
  """
51
+ Download using curl with resume support (-C -) and follow redirects (-L).
 
52
  """
53
+ dest.parent.mkdir(parents=True, exist_ok=True)
54
+ # Skip if already present
55
+ if dest.exists() and dest.stat().st_size > 0:
56
  return
57
+ run(["bash", "-lc", f'curl -L -C - --retry 5 --retry-delay 2 -o "{dest}" "{url}"'])
58
+
59
 
60
+ def ensure_checkpoints():
61
+ ckpt_dir = REPO_DIR / "checkpoints"
62
+ ckpt_dir.mkdir(parents=True, exist_ok=True)
63
 
64
+ # Download required checkpoint files
65
+ for fname in CHECKPOINT_FILES:
66
+ url = f"{HF_BASE}/{fname}"
67
+ download_file(url, ckpt_dir / fname)
68
 
69
+ # Unzip BFM.zip -> checkpoints/BFM/
70
+ bfm_zip = ckpt_dir / "BFM.zip"
71
+ bfm_dir = ckpt_dir / "BFM"
72
+ if not bfm_dir.exists():
73
+ bfm_dir.mkdir(parents=True, exist_ok=True)
74
+ run(["unzip", "-q", str(bfm_zip), "-d", str(bfm_dir)])
75
+
76
+
77
+ def setup():
78
+ """
79
+ One-time setup: clone repo, pull LFS (best effort), download checkpoints.
80
+ Guarded by a lock to prevent multiple concurrent setup runs.
81
+ """
82
+ with _setup_lock:
83
+ if SETUP_FLAG.exists() and REPO_DIR.exists():
84
+ return
85
+
86
+ print("Setting up Video-Retalking...")
87
+
88
+ if not REPO_DIR.exists():
89
+ run(["git", "clone", "https://github.com/OpenTalker/video-retalking.git", str(REPO_DIR)])
90
+
91
+ # Best-effort: fetch any git-lfs files if repo uses them
92
+ try:
93
+ run(["git", "lfs", "pull"], cwd=REPO_DIR)
94
+ except Exception:
95
+ # Not fatal; we'll fetch checkpoints from HF mirror anyway
96
+ pass
97
+
98
+ ensure_checkpoints()
99
+
100
+ SETUP_FLAG.touch()
101
+ print("βœ… Setup complete!")
102
 
 
 
103
 
104
  def generate(image_path, audio_path):
105
  if not image_path or not audio_path:
 
116
  if not audio_path.exists():
117
  return None, f"❌ Audio not found: {audio_path}"
118
 
 
119
  out_path = (OUTPUT_DIR / "result.mp4").resolve()
 
 
120
  if out_path.exists():
121
  out_path.unlink()
122
 
 
123
  cmd = [
124
  "python",
125
  "inference.py",
 
131
 
132
  if out_path.exists():
133
  return str(out_path), "βœ… Video generated successfully!"
134
+ return None, "❌ Failed (no output file created)."
135
 
136
  except Exception as e:
137
  return None, f"❌ Error: {e}"
138
 
139
+
140
  demo = gr.Interface(
141
  fn=generate,
142
  inputs=[
 
145
  ],
146
  outputs=[
147
  gr.Video(label="πŸ“Ή Generated Video"),
148
+ gr.Textbox(label="Status", lines=4),
149
  ],
150
  title="🎬 Video-Retalking Lip Sync",
151
  description="Upload a face image and audio to generate a lip-synced video.",