Skip to content

fix: critical bugs in face_swapper and globals, update gitignore#1740

Open
huynhhh wants to merge 2 commits intohacksider:mainfrom
huynhhh:main
Open

fix: critical bugs in face_swapper and globals, update gitignore#1740
huynhhh wants to merge 2 commits intohacksider:mainfrom
huynhhh:main

Conversation

@huynhhh
Copy link
Copy Markdown

@huynhhh huynhhh commented Apr 6, 2026

  • Add missing import logging that caused NameError
  • Fix model path mismatch: pre_start() now checks inswapper_128.onnx matching pre_check() download
  • Add missing eyes_mask_size and eyebrows_mask_size globals to prevent AttributeError
  • Add INTERPOLATION_LOCK to protect PREVIOUS_FRAME_RESULT from race conditions across threads
  • Update .gitignore for env, claude, docs, plans

Summary by Sourcery

Fix critical issues in face interpolation state handling, model loading, and global configuration, and update ignore rules.

Bug Fixes:

  • Correct the inswapper model path used during startup to match the downloaded model filename.
  • Prevent race conditions in frame interpolation by guarding shared state with a lock across frame-processing paths.
  • Ensure interpolation state is safely reset when opacity disables face swapping in both simple and advanced processing flows.
  • Add missing global configuration values for eye and eyebrow mask sizing to avoid runtime attribute errors.

Enhancements:

  • Adjust frame interpolation logic to consistently manage previous-frame caching based on interpolation settings.

Build:

  • Extend .gitignore to exclude additional local environment, documentation, and planning artifacts from version control.

- Add missing `import logging` that caused NameError
- Fix model path mismatch: pre_start() now checks inswapper_128.onnx matching pre_check() download
- Add missing eyes_mask_size and eyebrows_mask_size globals to prevent AttributeError
- Add INTERPOLATION_LOCK to protect PREVIOUS_FRAME_RESULT from race conditions across threads
- Update .gitignore for env, claude, docs, plans
@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai bot commented Apr 6, 2026

Reviewer's Guide

Fixes several critical runtime issues in the face swapper pipeline: aligns the ONNX model path with the pre-check downloader, adds missing global config values, introduces a lock around frame interpolation state for thread safety, and updates .gitignore entries.

Sequence diagram for thread safe frame interpolation in face_swapper

sequenceDiagram
    actor WorkerThread1
    actor WorkerThread2
    participant FaceSwapper as FaceSwapperFrameProcessor
    participant Globals
    participant State as PREVIOUS_FRAME_RESULT

    WorkerThread1->>FaceSwapper: apply_post_processing(frame1, bboxes1)
    activate FaceSwapper
    FaceSwapper->>FaceSwapper: acquire INTERPOLATION_LOCK
    FaceSwapper->>Globals: read enable_interpolation, interpolation_weight
    FaceSwapper->>State: read PREVIOUS_FRAME_RESULT
    FaceSwapper->>FaceSwapper: interpolate frame1 with PREVIOUS_FRAME_RESULT
    FaceSwapper->>State: write new PREVIOUS_FRAME_RESULT
    FaceSwapper->>FaceSwapper: release INTERPOLATION_LOCK
    deactivate FaceSwapper

    par concurrent_frame_processing
        WorkerThread2->>FaceSwapper: apply_post_processing(frame2, bboxes2)
        activate FaceSwapper
        FaceSwapper->>FaceSwapper: acquire INTERPOLATION_LOCK
        FaceSwapper->>Globals: read enable_interpolation, interpolation_weight
        FaceSwapper->>State: read PREVIOUS_FRAME_RESULT
        FaceSwapper->>FaceSwapper: interpolate frame2 with PREVIOUS_FRAME_RESULT
        FaceSwapper->>State: write new PREVIOUS_FRAME_RESULT
        FaceSwapper->>FaceSwapper: release INTERPOLATION_LOCK
        deactivate FaceSwapper
    end

    WorkerThread1->>FaceSwapper: process_frame(source_face, frameX) with opacity 0
    activate FaceSwapper
    FaceSwapper->>Globals: read opacity
    FaceSwapper->>FaceSwapper: acquire INTERPOLATION_LOCK
    FaceSwapper->>State: set PREVIOUS_FRAME_RESULT to None
    FaceSwapper->>FaceSwapper: release INTERPOLATION_LOCK
    FaceSwapper-->>WorkerThread1: return original frameX
    deactivate FaceSwapper
Loading

Class diagram for updated face_swapper interpolation and globals

classDiagram
    class FaceSwapperFrameProcessor {
        <<module>>
        PREVIOUS_FRAME_RESULT np_ndarray_or_None
        INTERPOLATION_LOCK threading_Lock
        pre_check() bool
        pre_start() bool
        apply_post_processing(current_frame Frame, swapped_face_bboxes List_np_ndarray) Frame
        process_frame(source_face Face, temp_frame Frame) Frame
        process_frame_v2(temp_frame Frame, temp_frame_path str) Frame
        process_image(source_path str, target_path str, output_path str) void
        process_video(source_path str, temp_frame_paths List_str) void
    }

    class Globals {
        <<module>>
        opacity float
        map_faces bool
        enable_interpolation bool
        interpolation_weight float
        mask_down_size float
        mask_size float
        mouth_mask_size float
        eyes_mask_size float
        eyebrows_mask_size float
    }

    class ModelFiles {
        <<filesystem>>
        models_dir str
        inswapper_128_onnx str
    }

    FaceSwapperFrameProcessor ..> Globals : uses
    FaceSwapperFrameProcessor ..> ModelFiles : reads_path

    class ThreadingRuntime {
        <<runtime>>
        acquire(lock threading_Lock) void
        release(lock threading_Lock) void
    }

    FaceSwapperFrameProcessor ..> ThreadingRuntime : synchronized_by
Loading

Flow diagram for updated frame interpolation logic in apply_post_processing

flowchart TD
    A_start[Start apply_post_processing] --> B_set_final[Set final_frame to processed_frame]
    B_set_final --> C_lock[Acquire INTERPOLATION_LOCK]
    C_lock --> D_check_interp{enable_interpolation
    and 0<weight<1?}

    D_check_interp -- No --> D1_clear_prev[Set PREVIOUS_FRAME_RESULT to None]
    D1_clear_prev --> E_unlock[Release INTERPOLATION_LOCK]
    E_unlock --> F_return[Return final_frame]

    D_check_interp -- Yes --> G_check_prev{PREVIOUS_FRAME_RESULT
    is not None and
    shape and dtype match?}

    G_check_prev -- No --> H_set_prev_curr[Set PREVIOUS_FRAME_RESULT to processed_frame copy]
    H_set_prev_curr --> E_unlock

    G_check_prev -- Yes --> I_try_interp[Try gpu_add_weighted
    using PREVIOUS_FRAME_RESULT
    and processed_frame]
    I_try_interp --> J_success{Interpolation
    success?}

    J_success -- Yes --> K_clip[Clip to 0_255 and cast to uint8]
    K_clip --> L_set_final[Set final_frame to interpolated result]
    L_set_final --> M_update_prev[Set PREVIOUS_FRAME_RESULT to final_frame copy]
    M_update_prev --> E_unlock

    J_success -- No --> N_fallback[Set final_frame to processed_frame
    and PREVIOUS_FRAME_RESULT to None]
    N_fallback --> E_unlock

    F_return --> Z_end[End]
Loading

File-Level Changes

Change Details Files
Harden frame interpolation logic with thread-safe access to previous-frame state and consistent reset behavior.
  • Introduce a global INTERPOLATION_LOCK to guard access to PREVIOUS_FRAME_RESULT across threads.
  • Wrap interpolation logic in apply_post_processing in a with INTERPOLATION_LOCK block, including both the interpolation path and the state updates/fallbacks.
  • On OpenCV interpolation errors, fall back to the current frame and clear PREVIOUS_FRAME_RESULT instead of leaking stale state.
  • Ensure that when interpolation is disabled or the weight is invalid, PREVIOUS_FRAME_RESULT is explicitly set to None inside the same lock scope.
  • In process_frame, process_frame_v2, process_image, and process_video, reset PREVIOUS_FRAME_RESULT inside a with INTERPOLATION_LOCK block whenever opacity is zero or a new processing run starts.
modules/processors/frame/face_swapper.py
Align the face swapper ONNX model path with the model downloaded during pre-check to avoid missing-model failures at runtime.
  • Change pre_start to look for inswapper_128.onnx instead of inswapper_128_fp16.onnx so it matches the asset used by pre_check and the downloader logic.
  • Preserve the existing status update and early-return behavior if the model file is missing.
modules/processors/frame/face_swapper.py
Add missing global mask configuration values to prevent AttributeError when referenced in processing code.
  • Introduce eyes_mask_size with a default of 0.0 to control eyes mask size adjustments.
  • Introduce eyebrows_mask_size with a default of 1.0 to control eyebrows mask padding.
modules/globals.py
Update repository ignore rules for local/dev artifacts and tooling.
  • Extend .gitignore to ignore environment directories, Claude-related files, documentation artifacts, and planning files as described in the PR.
.gitignore

Possibly linked issues

  • #Unknown: The PR fixes the inswapper_128 model path in face_swapper, directly addressing the black/failed image swapping issue.
  • #unknown: Yes. PR changes pre_start() to use inswapper_128.onnx, making filename usage consistent and fixing the model load bug.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey - I've left some high level feedback:

  • The new INTERPOLATION_LOCK wraps the entire interpolation computation; consider narrowing the locked section to just the reads/writes of PREVIOUS_FRAME_RESULT so that other threads don’t block on gpu_add_weighted and numpy work unnecessarily.
  • Using a single global PREVIOUS_FRAME_RESULT and INTERPOLATION_LOCK will couple all concurrent video/image processing sessions; if multi-stream processing is expected, consider moving this state to a per-stream/context object instead of globals.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The new INTERPOLATION_LOCK wraps the entire interpolation computation; consider narrowing the locked section to just the reads/writes of PREVIOUS_FRAME_RESULT so that other threads don’t block on gpu_add_weighted and numpy work unnecessarily.
- Using a single global PREVIOUS_FRAME_RESULT and INTERPOLATION_LOCK will couple all concurrent video/image processing sessions; if multi-stream processing is expected, consider moving this state to a per-stream/context object instead of globals.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Lock only protects reads/writes of PREVIOUS_FRAME_RESULT.
Expensive gpu_add_weighted and numpy computation now runs outside the lock.
@huynhhh huynhhh closed this Apr 6, 2026
@huynhhh huynhhh reopened this Apr 6, 2026
@huynhhh huynhhh closed this Apr 6, 2026
@huynhhh huynhhh reopened this Apr 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant