README and models/instructions.txt named GFPGANv1.4, but the enhancer loads gfpgan-1024.onnx via onnxruntime. instructions.txt also pointed at a PyTorch .pth that the ONNX path cannot load at all, so the manual-fallback instructions were unusable.
setrlimit(RLIMIT_DATA) is rejected by the macOS kernel for the values used here,
crashing the app during startup. Since --max-memory defaults to suggest_max_memory()
(4 on Darwin), max_memory is always set on macOS and every launch reached this call.
Fixes#1848.
Verified this fix. Confirmed the bug by reverting just the `modules/core.py` hunk and
re-running the new regression test — with the old code, `process_video`/`create_video`
run against a temp directory that was never populated when `map_faces=True`, since
`create_temp`/`extract_frames` were skipped for that case. That means map-faces video
runs were silently broken (empty or failed output).
The fix removes the `map_faces` guard so extraction always runs before the disk-based
fallback, which is correct for both cases that reach this branch (map_faces=True, and
non-map-faces pipe failures). `create_temp` is idempotent (mkdir exist_ok=True), so the
double-call for the non-map-faces path is harmless.
Prevent get_video_frame() from seeking to invalid frame positions.
The default frame_number=0 now resolves to the first frame instead of -1, and oversized frame requests clamp to the final valid frame instead of seeking past the end. Empty or invalid videos now return None safely after releasing the capture.
Affected files: capturer.py
Signed-off-by: Nguyen Van Nam <nam.nv205106@gmail.com>
`find_cluster_centroids()` iterates `k` from 1..`max_k` unconditionally. If `len(embeddings) < max_k`, `KMeans(n_clusters=k)` will raise `ValueError` when `k` exceeds the number of samples. This is an unhandled crash path on small datasets.
Affected files: cluster_analysis.py
Signed-off-by: Nguyen Van Nam <nam.nv205106@gmail.com>
Address Sourcery review feedback on PR #1879:
- Move OPENVINO_PROVIDER_CONFIG from _onnx_enhancer.py to
platform_info.py (a leaf module with no modules.* imports), so
the enhancer and face_swapper no longer import each other just to
share a constant. _onnx_enhancer re-exports it; face_swapper now
imports it at module top level instead of inside get_face_swapper().
- Narrow run.py's SystemExit handling: catch SystemExit separately
and print a [startup] message so the failure is visible instead
of being swallowed alongside ImportError/FileNotFoundError.
- Catch SystemExit from add_openvino_libs_to_path() so a missing
OpenVINO installation never causes a hard exit on Windows
- Replace hard-coded GPU+FP16 with AUTO:GPU,NPU,CPU device priority,
letting OpenVINO pick the best available accelerator
- Extract shared OPENVINO_PROVIDER_CONFIG constant to avoid
duplication between _onnx_enhancer and face_swapper
- Defer thread-suggestion evaluation until after execution_providers
is assigned, fixing a latent timing bug that affected OpenVINO,
CUDA, and DML thread hints
- Add add_openvino_libs_to_path() call in run.py before any ONNX
InferenceSession creation to register openvino.dll directory
- Detect and advertise OpenVINOExecutionProvider in platform_info
banner and accelerator label
- Prioritize openvino over dml in suggest_default_execution_provider
- Configure OpenVINO EP with GPU + FP16 device options for optimal
performance (~13 FPS on Intel GPU vs ~1 FPS CPU fallback)
- Set thread hint to 1 when OpenVINO EP is active
- build the video save-dialog filter from VIDEO_EXTENSIONS (_VIDEO_FILE_FILTER)
instead of a hardcoded "Videos (*.mp4 *.mkv)" — the last filter that still
drifted from the canonical set
- remove the now-dead file_types list (unused in both the fork and upstream;
the PySide6 dialogs use the QFileDialog filter strings) and drop it from the
centralization comment
Review feedback on #1831:
- Remove *.gif from the save/output dialog filter (PR had added it there).
Verified empirically that cv2.imread/imwrite cannot decode OR encode GIF on
OpenCV 4.10 *or* 4.11 (write raises, read returns None), so GIF silently
failed on both ends — dropped from every dialog and from has_image_extension.
- has_image_extension now uses os.path.splitext so only the true extension
counts ('photo.png.bak' / 'clip.webp.mp4' are no longer treated as images).
- Centralize the supported-extension set in modules.globals (IMAGE_EXTENSIONS /
VIDEO_EXTENSIONS); file_types, all QFileDialog filters and has_image_extension
now derive from it instead of hand-copied lists that had already drifted.
WEBP itself is unchanged and works (libwebp ships with opencv-python).
Swap the manual pip install + ruff check steps for astral-sh/ruff-action@v4.0.0.
Same pinned ruff 0.15.7, but with --output-format=github so violations appear
as inline annotations on the PR diff instead of a flat log.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Introduces pyproject.toml + .github/workflows/ruff.yml that gate
E701, E711, E712, F401, F541 on every PR and push to main.
Fixes the existing findings for those rules:
- Remove unused imports (sklearn.silhouette_score, numpy in several
files, typing.Optional, get_one_face, gpu_cvt_color, sys,
insightface.face_align)
- Annotate the intentional tkinter_fix side-effect import with
`# noqa: F401`
- Split multi-statement `if x: y` one-liners onto separate lines
- Replace `state == True` / `state == False` with truthiness checks
- Drop `f` prefix from f-strings with no placeholders
F841 (unused-variable), E402 (module-level-import-not-at-top), and
F821 (undefined-name) are left out of the gate for now — they surface
real findings (including a latent NameError in face_swapper.py) that
require human review to fix safely.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Skip prepending a directory that is already on LD_LIBRARY_PATH, so a
repeated import of run.py does not bloat the variable.
Addresses review feedback on #1826.
Mirrors the Windows preload block from #1775. When onnxruntime-gpu is
installed via pip with nvidia-cudnn-cu12, the .so files sit under
venv/lib/pythonX.Y/site-packages/nvidia/<pkg>/lib/ and the dynamic
linker never sees them. LD_LIBRARY_PATH cannot be set after Python
starts.
Pre-loads every lib*.so* via ctypes.CDLL with RTLD_GLOBAL before
onnxruntime opens its CUDA provider. Also extends LD_LIBRARY_PATH so
child processes (ffmpeg) inherit the path.
Fixes "libcudnn.so.9: cannot open shared object file" on pip-only
Linux installs.