diff --git a/README.md b/README.md index 2e97d172..2bf3a05b 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ By using this software, you agree to these terms and commit to using it in a man Users are expected to use this software responsibly and legally. If using a real person's face, obtain their consent and clearly label any output as a deepfake when sharing online. We are not responsible for end-user actions. -## Exclusive v2.3 Quick Start - Pre-built (Windows/Mac Silicon) +## Exclusive v2.3c Quick Start - Pre-built (Windows/Mac Silicon) @@ -354,11 +354,13 @@ Looking for a CLI mode? Using the -s/--source argument will make the run program - [*"Alright look look look, now look chat, we can do any face we want to look like chat"*](https://www.youtube.com/live/mFsCe7AIxq8?feature=shared&t=2686) - IShowSpeed - [*"They do a pretty good job matching poses, expression and even the lighting"*](https://www.youtube.com/watch?v=wnCghLjqv3s&t=551s) - TechLinked (LTT) - [*"Als Sean Connery an der Redaktionskonferenz teilnahm"*](https://www.golem.de/news/deepfakes-als-sean-connery-an-der-redaktionskonferenz-teilnahm-2408-188172.html) - Golem.de (German) + - [*"What the F***! Why do I look like Vinny Jr? I look exactly like Vinny Jr!? No, this shit is crazy! Bro This is F*** Crazy! "*](https://youtu.be/JbUPRmXRUtE?t=3964) - IShowSpeed ## Credits - [ffmpeg](https://ffmpeg.org/): for making video-related operations easy +- [Henry](https://github.com/henryruhs): One of the major contributor in this repo - [deepinsight](https://github.com/deepinsight): for their [insightface](https://github.com/deepinsight/insightface) project which provided a well-made library and models. Please be reminded that the [use of the model is for non-commercial research purposes only](https://github.com/deepinsight/insightface?tab=readme-ov-file#license). - [havok2-htwo](https://github.com/havok2-htwo): for sharing the code for webcam - [GosuDRM](https://github.com/GosuDRM): for the open version of roop diff --git a/locales/id.json b/locales/id.json new file mode 100644 index 00000000..f3f4a6ac --- /dev/null +++ b/locales/id.json @@ -0,0 +1,45 @@ +{ + "Source x Target Mapper": "Pemetaan Sumber x Target", + "select a source image": "Pilih gambar sumber", + "Preview": "Pratinjau", + "select a target image or video": "Pilih gambar atau video target", + "save image output file": "Simpan file keluaran gambar", + "save video output file": "Simpan file keluaran video", + "select a target image": "Pilih gambar target", + "source": "Sumber", + "Select a target": "Pilih target", + "Select a face": "Pilih wajah", + "Keep audio": "Pertahankan audio", + "Face Enhancer": "Peningkat wajah", + "Many faces": "Banyak wajah", + "Show FPS": "Tampilkan FPS", + "Keep fps": "Pertahankan FPS", + "Keep frames": "Pertahankan frame", + "Fix Blueish Cam": "Perbaiki kamera kebiruan", + "Mouth Mask": "Masker mulut", + "Show Mouth Mask Box": "Tampilkan kotak masker mulut", + "Start": "Mulai", + "Live": "Langsung", + "Destroy": "Hentikan", + "Map faces": "Petakan wajah", + "Processing...": "Sedang memproses...", + "Processing succeed!": "Pemrosesan berhasil!", + "Processing ignored!": "Pemrosesan diabaikan!", + "Failed to start camera": "Gagal memulai kamera", + "Please complete pop-up or close it.": "Harap selesaikan atau tutup pop-up.", + "Getting unique faces": "Mengambil wajah unik", + "Please select a source image first": "Silakan pilih gambar sumber terlebih dahulu", + "No faces found in target": "Tidak ada wajah ditemukan pada target", + "Add": "Tambah", + "Clear": "Bersihkan", + "Submit": "Kirim", + "Select source image": "Pilih gambar sumber", + "Select target image": "Pilih gambar target", + "Please provide mapping!": "Harap tentukan pemetaan!", + "At least 1 source with target is required!": "Minimal 1 sumber dengan target diperlukan!", + "Face could not be detected in last upload!": "Wajah tidak dapat terdeteksi pada unggahan terakhir!", + "Select Camera:": "Pilih Kamera:", + "All mappings cleared!": "Semua pemetaan telah dibersihkan!", + "Mappings successfully submitted!": "Pemetaan berhasil dikirim!", + "Source x Target Mapper is already open.": "Pemetaan Sumber x Target sudah terbuka." +} \ No newline at end of file diff --git a/modules/globals.py b/modules/globals.py index aad50f0b..b1da393a 100644 --- a/modules/globals.py +++ b/modules/globals.py @@ -12,7 +12,7 @@ ] # Face Mapping Data -souce_target_map: List[Dict[str, Any]] = [] # Stores detailed map for image/video processing +source_target_map: List[Dict[str, Any]] = [] # Stores detailed map for image/video processing simple_map: Dict[str, Any] = {} # Stores simplified map (embeddings/faces) for live/simple mode # Paths @@ -26,7 +26,7 @@ keep_audio: bool = True keep_frames: bool = False many_faces: bool = False # Process all detected faces with default source -map_faces: bool = False # Use souce_target_map or simple_map for specific swaps +map_faces: bool = False # Use source_target_map or simple_map for specific swaps color_correction: bool = False # Enable color correction (implementation specific) nsfw_filter: bool = False @@ -68,4 +68,4 @@ interpolation_weight: float = 0 # Blend weight for current frame (0.0-1.0). Lower=smoother. # --- END: Added for Frame Interpolation --- -# --- END OF FILE globals.py --- \ No newline at end of file +# --- END OF FILE globals.py --- diff --git a/modules/processors/frame/face_swapper.py b/modules/processors/frame/face_swapper.py index 7c4a98f3..61b4ca35 100644 --- a/modules/processors/frame/face_swapper.py +++ b/modules/processors/frame/face_swapper.py @@ -63,14 +63,32 @@ def get_face_swapper() -> Any: with THREAD_LOCK: if FACE_SWAPPER is None: - model_path = os.path.join(models_dir, "inswapper_128_fp16.onnx") + model_name = "inswapper_128.onnx" + if "CUDAExecutionProvider" in modules.globals.execution_providers: + model_name = "inswapper_128_fp16.onnx" + model_path = os.path.join(models_dir, model_name) update_status(f"Loading face swapper model from: {model_path}", NAME) try: # Ensure the providers list is correctly passed - providers = modules.globals.execution_providers - # print(f"Attempting to load model with providers: {providers}") # Debug print + # Apply CoreML optimization for Mac systems FACE_SWAPPER = insightface.model_zoo.get_model( - model_path, providers=providers + model_path, + providers=[ + ( + ( + "CoreMLExecutionProvider", + { + "ModelFormat": "MLProgram", + "MLComputeUnits": "CPUAndGPU", + "SpecializationStrategy": "FastPrediction", + "AllowLowPrecisionAccumulationOnGPU": 1, + }, + ) + if p == "CoreMLExecutionProvider" + else p + ) + for p in modules.globals.execution_providers + ], ) update_status("Face swapper model loaded successfully.", NAME) except Exception as e: @@ -323,7 +341,7 @@ def process_frame_v2(temp_frame: Frame, temp_frame_path: str = "") -> Frame: source_target_pairs = [] # Ensure maps exist before accessing them - souce_target_map = getattr(modules.globals, "souce_target_map", None) + source_target_map = getattr(modules.globals, "source_target_map", None) simple_map = getattr(modules.globals, "simple_map", None) # Check if target is a file path (image or video) or live stream @@ -331,11 +349,11 @@ def process_frame_v2(temp_frame: Frame, temp_frame_path: str = "") -> Frame: if is_file_target: # Processing specific image or video file with pre-analyzed maps - if souce_target_map: + if source_target_map: if modules.globals.many_faces: source_face = default_source_face() # Use default source for all targets if source_face: - for map_data in souce_target_map: + for map_data in source_target_map: if is_image(modules.globals.target_path): target_info = map_data.get("target", {}) if target_info: # Check if target info exists @@ -353,7 +371,7 @@ def process_frame_v2(temp_frame: Frame, temp_frame_path: str = "") -> Frame: for target_face in faces_in_frame: source_target_pairs.append((source_face, target_face)) else: # Single face or specific mapping - for map_data in souce_target_map: + for map_data in source_target_map: source_info = map_data.get("source", {}) if not source_info: continue # Skip if no source info source_face = source_info.get("face") diff --git a/modules/ui.py b/modules/ui.py index c310cca0..f4f61256 100644 --- a/modules/ui.py +++ b/modules/ui.py @@ -465,7 +465,7 @@ def analyze_target(start: Callable[[], None], root: ctk.CTk): return if modules.globals.map_faces: - modules.globals.souce_target_map = [] + modules.globals.source_target_map = [] if is_image(modules.globals.target_path): update_status("Getting unique faces") @@ -474,8 +474,8 @@ def analyze_target(start: Callable[[], None], root: ctk.CTk): update_status("Getting unique faces") get_unique_faces_from_target_video() - if len(modules.globals.souce_target_map) > 0: - create_source_target_popup(start, root, modules.globals.souce_target_map) + if len(modules.globals.source_target_map) > 0: + create_source_target_popup(start, root, modules.globals.source_target_map) else: update_status("No faces found in target") else: @@ -855,9 +855,9 @@ def webcam_preview(root: ctk.CTk, camera_index: int): return create_webcam_preview(camera_index) else: - modules.globals.souce_target_map = [] + modules.globals.source_target_map = [] create_source_target_popup_for_webcam( - root, modules.globals.souce_target_map, camera_index + root, modules.globals.source_target_map, camera_index )