dosesnrolls1 commited on
Commit
97f568b
·
verified ·
1 Parent(s): 9bd2cd2

Upload 4 files

Browse files
Files changed (3) hide show
  1. Dockerfile +1 -1
  2. app.py +30 -30
  3. readme.md +31 -0
Dockerfile CHANGED
@@ -1,6 +1,6 @@
1
  FROM nvidia/cuda:12.1.1-cudnn8-runtime-ubuntu22.04
2
 
3
- ENV DEBIAN_FRONTEND=noninteractive PYTHONUNBUFFERED=1 PIP_NO_CACHE_DIR=1 HOME=/home/user PATH=/home/user/.local/bin:$PATH
4
 
5
  RUN apt-get update && apt-get install -y python3 python3-pip ffmpeg libgl1 libglib2.0-0 && rm -rf /var/lib/apt/lists/*
6
 
 
1
  FROM nvidia/cuda:12.1.1-cudnn8-runtime-ubuntu22.04
2
 
3
+ ENV DEBIAN_FRONTEND=noninteractive PYTHONUNBUFFERED=1 PIP_NO_CACHE_DIR=1 HOME=/home/user PATH=/home/user/.local/bin:$PATH FORCE_CPU=0
4
 
5
  RUN apt-get update && apt-get install -y python3 python3-pip ffmpeg libgl1 libglib2.0-0 && rm -rf /var/lib/apt/lists/*
6
 
app.py CHANGED
@@ -24,7 +24,6 @@ HF_TOKEN = os.environ.get("HF_TOKEN") or os.environ.get("HUGGINGFACEHUB_API_TOKE
24
  FACE_MODEL_NAME = os.environ.get("FACE_MODEL_NAME", "buffalo_l")
25
  DETECTION_SIZE = int(os.environ.get("DETECTION_SIZE", "640"))
26
  MAX_FRAMES = int(os.environ.get("MAX_FRAMES", "0"))
27
- FORCE_CPU = os.environ.get("FORCE_CPU") == "1"
28
 
29
  face_analyzer = None
30
  face_swapper = None
@@ -36,17 +35,21 @@ def ensure_ffmpeg():
36
  raise RuntimeError("ffmpeg is required but not available in PATH.")
37
 
38
 
39
- def get_execution_providers():
40
- providers = []
41
- if not FORCE_CPU:
42
- providers.append("CUDAExecutionProvider")
43
- providers.append("CPUExecutionProvider")
44
- return providers
45
 
46
 
47
- def provider_status():
48
- available = ort.get_available_providers()
49
- return available, ("CUDAExecutionProvider" in available)
 
 
 
 
 
 
 
 
50
 
51
 
52
  def ensure_swap_model() -> str:
@@ -57,25 +60,26 @@ def ensure_swap_model() -> str:
57
  if local_target.exists():
58
  model_path = str(local_target)
59
  return model_path
60
- downloaded = hf_hub_download(
61
  repo_id=MODEL_REPO_ID,
62
  filename=MODEL_FILENAME,
63
  revision=MODEL_REVISION,
64
  token=HF_TOKEN,
65
  local_dir=str(MODELS_DIR),
66
  )
67
- model_path = downloaded
68
  return model_path
69
 
70
 
71
  def load_models():
72
  global face_analyzer, face_swapper
 
73
  if face_analyzer is not None and face_swapper is not None:
74
  return face_analyzer, face_swapper
75
  swap_model_path = ensure_swap_model()
76
- face_analyzer = FaceAnalysis(name=FACE_MODEL_NAME, providers=get_execution_providers())
 
77
  face_analyzer.prepare(ctx_id=0, det_size=(DETECTION_SIZE, DETECTION_SIZE))
78
- face_swapper = get_model(swap_model_path, providers=get_execution_providers())
79
  return face_analyzer, face_swapper
80
 
81
 
@@ -107,15 +111,16 @@ def swap_frame(frame_bgr, source_face, analyzer, swapper):
107
  return result
108
 
109
 
110
- def process_video(face_image_path, video_path, progress=gr.Progress(track_tqdm=False)):
111
- available_providers, cuda_available = provider_status()
112
- if FORCE_CPU:
113
- raise RuntimeError(f"FORCE_CPU=1 is set. Available providers: {available_providers}")
114
- if not cuda_available:
115
- raise RuntimeError(f"CUDAExecutionProvider is not available. Available providers: {available_providers}")
116
 
 
 
117
  ensure_ffmpeg()
118
  analyzer, swapper = load_models()
 
119
  src = cv2.imread(face_image_path)
120
  if src is None:
121
  raise ValueError("Could not read the source face image.")
@@ -153,18 +158,13 @@ def process_video(face_image_path, video_path, progress=gr.Progress(track_tqdm=F
153
  cap.release()
154
  writer.release()
155
  mux_audio(silent_video, audio_file, final_video)
156
- return final_video, f"Done. Processed {idx} frame(s). Providers: {available_providers}"
157
-
158
-
159
- def startup_message():
160
- available, cuda_ok = provider_status()
161
- return f"ONNX Runtime providers: {available} | CUDA available: {cuda_ok}"
162
 
163
 
164
- with gr.Blocks(title="Video FaceSwap GPU") as demo:
165
- gr.Markdown("""# Video FaceSwap GPU
166
- Upload a source face image and a target video. The app downloads the swap model from the Hugging Face Hub at runtime, then swaps the main source face onto detected faces in the video.""")
167
- status_banner = gr.Textbox(label="Startup status", value=startup_message(), interactive=False)
168
  with gr.Row():
169
  face_image = gr.Image(type="filepath", label="Source face image")
170
  target_video = gr.Video(label="Target video")
 
24
  FACE_MODEL_NAME = os.environ.get("FACE_MODEL_NAME", "buffalo_l")
25
  DETECTION_SIZE = int(os.environ.get("DETECTION_SIZE", "640"))
26
  MAX_FRAMES = int(os.environ.get("MAX_FRAMES", "0"))
 
27
 
28
  face_analyzer = None
29
  face_swapper = None
 
35
  raise RuntimeError("ffmpeg is required but not available in PATH.")
36
 
37
 
38
+ def available_providers():
39
+ return ort.get_available_providers()
 
 
 
 
40
 
41
 
42
+ def gpu_ready():
43
+ return "CUDAExecutionProvider" in available_providers()
44
+
45
+
46
+ def gpu_guard():
47
+ providers = available_providers()
48
+ if "CUDAExecutionProvider" not in providers:
49
+ raise RuntimeError(
50
+ "GPU-only mode: CUDAExecutionProvider is missing. "
51
+ f"Available providers: {providers}"
52
+ )
53
 
54
 
55
  def ensure_swap_model() -> str:
 
60
  if local_target.exists():
61
  model_path = str(local_target)
62
  return model_path
63
+ model_path = hf_hub_download(
64
  repo_id=MODEL_REPO_ID,
65
  filename=MODEL_FILENAME,
66
  revision=MODEL_REVISION,
67
  token=HF_TOKEN,
68
  local_dir=str(MODELS_DIR),
69
  )
 
70
  return model_path
71
 
72
 
73
  def load_models():
74
  global face_analyzer, face_swapper
75
+ gpu_guard()
76
  if face_analyzer is not None and face_swapper is not None:
77
  return face_analyzer, face_swapper
78
  swap_model_path = ensure_swap_model()
79
+ providers = ["CUDAExecutionProvider"]
80
+ face_analyzer = FaceAnalysis(name=FACE_MODEL_NAME, providers=providers)
81
  face_analyzer.prepare(ctx_id=0, det_size=(DETECTION_SIZE, DETECTION_SIZE))
82
+ face_swapper = get_model(swap_model_path, providers=providers)
83
  return face_analyzer, face_swapper
84
 
85
 
 
111
  return result
112
 
113
 
114
+ def startup_status():
115
+ providers = available_providers()
116
+ return f"Available providers: {providers} | GPU ready: {gpu_ready()}"
117
+
 
 
118
 
119
+ def process_video(face_image_path, video_path, progress=gr.Progress(track_tqdm=False)):
120
+ gpu_guard()
121
  ensure_ffmpeg()
122
  analyzer, swapper = load_models()
123
+
124
  src = cv2.imread(face_image_path)
125
  if src is None:
126
  raise ValueError("Could not read the source face image.")
 
158
  cap.release()
159
  writer.release()
160
  mux_audio(silent_video, audio_file, final_video)
161
+ return final_video, f"Done. Processed {idx} frame(s)."
 
 
 
 
 
162
 
163
 
164
+ with gr.Blocks(title="Video FaceSwap GPU Only") as demo:
165
+ gr.Markdown("""# Video FaceSwap GPU Only
166
+ This Space will only run when ONNX Runtime exposes CUDAExecutionProvider. If not, it refuses to process video.""")
167
+ gr.Textbox(label="GPU status", value=startup_status(), interactive=False)
168
  with gr.Row():
169
  face_image = gr.Image(type="filepath", label="Source face image")
170
  target_video = gr.Video(label="Target video")
readme.md ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Video FaceSwap GPU Only
3
+ emoji: 🎭
4
+ colorFrom: blue
5
+ colorTo: purple
6
+ sdk: docker
7
+ app_port: 7860
8
+ suggested_hardware: a10g-small
9
+ startup_duration_timeout: 1h
10
+ ---
11
+
12
+ # Video FaceSwap GPU Only
13
+
14
+ This Space is strict GPU-only. It refuses to process video unless ONNX Runtime exposes CUDAExecutionProvider.
15
+
16
+ ## Environment variables
17
+
18
+ - `MODEL_REPO_ID`: default `ezioruan/inswapper_128.onnx`
19
+ - `MODEL_FILENAME`: default `inswapper_128.onnx`
20
+ - `MODEL_REVISION`: optional branch, tag, or commit hash
21
+ - `HF_TOKEN`: recommended for gated/private repos and better Hub rate limits
22
+ - `FACE_MODEL_NAME`: default `buffalo_l`
23
+ - `DETECTION_SIZE`: default `640`
24
+ - `MAX_FRAMES`: optional frame cap for testing, default `0`
25
+
26
+ ## Deploy
27
+
28
+ 1. Create a Docker Space.
29
+ 2. Select a paid GPU hardware tier such as A10G small.
30
+ 3. Add these files.
31
+ 4. Add `HF_TOKEN` if needed.