Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 56 additions & 35 deletions modules/processors/frame/face_swapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,43 +83,64 @@ def pre_start() -> bool:
def get_face_swapper() -> Any:
global FACE_SWAPPER

with THREAD_LOCK:
if FACE_SWAPPER is None:
model_name = "inswapper_128.onnx"
if "CUDAExecutionProvider" in modules.globals.execution_providers:
if FACE_SWAPPER is None:
with THREAD_LOCK:
if FACE_SWAPPER is None:
model_name = "inswapper_128_fp16.onnx"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Model selection now always uses the fp16 variant and no longer respects non-CUDA providers.

With this change, model_name is now always set to "inswapper_128_fp16.onnx" whenever FACE_SWAPPER is initialized, regardless of the available execution providers. This can break or degrade behavior on providers without good fp16 support (e.g., CPU, some CoreML configs). Please restore conditional selection based on modules.globals.execution_providers, or gate fp16 behind an explicit capability check.

model_path = os.path.join(models_dir, model_name)
update_status(f"Loading face swapper model from: {model_path}", NAME)
try:
# Optimized provider configuration for Apple Silicon
providers_config = []
for p in modules.globals.execution_providers:
if p == "CoreMLExecutionProvider" and IS_APPLE_SILICON:
# Enhanced CoreML configuration for M1-M5
providers_config.append((
"CoreMLExecutionProvider",
{
"ModelFormat": "MLProgram",
"MLComputeUnits": "ALL", # Use Neural Engine + GPU + CPU
"SpecializationStrategy": "FastPrediction",
"AllowLowPrecisionAccumulationOnGPU": 1,
"EnableOnSubgraphs": 1,
"RequireStaticShapes": 0,
"MaximumCacheSize": 1024 * 1024 * 512, # 512MB cache
model_path = os.path.join(models_dir, model_name)
update_status(f"Loading face swapper model from: {model_path}", NAME)
try:
# Optimized provider configuration for Apple Silicon
providers_config = []
for p in modules.globals.execution_providers:
if p == "CoreMLExecutionProvider" and IS_APPLE_SILICON:
# Enhanced CoreML configuration for M1-M5
providers_config.append((
"CoreMLExecutionProvider",
{
"ModelFormat": "MLProgram",
"MLComputeUnits": "ALL", # Use Neural Engine + GPU + CPU
"SpecializationStrategy": "FastPrediction",
"AllowLowPrecisionAccumulationOnGPU": 1,
"EnableOnSubgraphs": 1,
"RequireStaticShapes": 1,
"MaximumCacheSize": 1024 * 1024 * 512, # 512MB cache
}
))
else:
providers_config.append(p)

FACE_SWAPPER = insightface.model_zoo.get_model(
model_path,
providers=providers_config,
)
update_status("Face swapper model loaded successfully.", NAME)
# Warmup inference: trigger CoreML JIT compilation and compute plan
# caching so the first real inference call has no latency spike.
if any(
(p[0] if isinstance(p, tuple) else p) == "CoreMLExecutionProvider"
for p in providers_config
):
try:
session = FACE_SWAPPER.session
input_feed = {
inp.name: np.zeros(
[d if isinstance(d, int) and d > 0 else 1
for d in inp.shape],
dtype=np.float32,
)
for inp in session.get_inputs()
}
))
else:
providers_config.append(p)

FACE_SWAPPER = insightface.model_zoo.get_model(
model_path,
providers=providers_config,
)
update_status("Face swapper model loaded successfully.", NAME)
except Exception as e:
update_status(f"Error loading face swapper model: {e}", NAME)
FACE_SWAPPER = None
return None
session.run(None, input_feed)
update_status("CoreML warmup inference complete.", NAME)
except Exception as warmup_err:
update_status(
f"CoreML warmup skipped (non-fatal): {warmup_err}", NAME
)
except Exception as e:
update_status(f"Error loading face swapper model: {e}", NAME)
FACE_SWAPPER = None
return None
return FACE_SWAPPER


Expand Down