65 Commits
testing ... 2.2

Author SHA1 Message Date
Kenneth Estanislao
d0d90ecc03 Creating a fallback and switching of models
Models switch depending on the execution provider
2025-08-02 02:56:20 +08:00
Kenneth Estanislao
2b70131e6a Update requirements.txt 2025-07-09 17:19:26 +08:00
Kenneth Estanislao
fc86365a90 Delete .yml 2025-07-02 18:37:10 +08:00
Kenneth Estanislao
1dd0e8e509 Create .yml 2025-07-02 18:29:32 +08:00
Kenneth Estanislao
4e0ff540f0 Update requirements.txt
faster and better requirements
2025-07-02 04:08:26 +08:00
Kenneth Estanislao
f0fae811d8 Update requirements.txt
should improve the performance by 30%
2025-06-29 15:03:35 +08:00
Kenneth Estanislao
42687f5bd9 Update README.md 2025-06-29 14:58:13 +08:00
Kenneth Estanislao
9086072b8e Update README.md 2025-06-23 17:06:34 +08:00
KRSHH
12fda0a3ed fix formatting 2025-06-17 18:42:36 +05:30
KRSHH
d963430854 Add techlinked link 2025-06-17 18:42:10 +05:30
KRSHH
5855d15c09 Removed outdated links 2025-06-17 18:35:24 +05:30
KRSHH
fcc73d0add Update Download Button 2025-06-16 14:37:41 +05:30
KRSHH
8d4a386a27 Upgrade prebuilt to 2.1 2025-06-15 22:19:49 +05:30
Chittimalla Krish
b98c5234d8 Revert 8bdc14a 2025-06-15 20:08:43 +05:30
Chittimalla Krish
8bdc14a789 Update prebuilt version 2025-06-15 17:50:38 +05:30
Kenneth Estanislao
f121083bc8 Update README.md
RTX 50xx support
2025-06-15 02:22:00 +08:00
Kenneth Estanislao
745d449ca6 Update README.md
support for RTX 50xx
2025-06-09 00:34:26 +08:00
Kenneth Estanislao
ec6d7d2995 Merge pull request #1327 from zjy-dev/fix/add-cudnn-installation-docs
docs: add cuDNN installation guidance for CUDA
2025-06-01 12:05:04 +08:00
zjy-dev
e791f2f18a docs: add cuDNN installation guidance for CUDA 2025-06-01 00:40:29 +08:00
KRSHH
3795e41fd7 Merge pull request #1307 from Neurofix/main
ADD locale ko.json
2025-05-28 08:09:02 +05:30
KRSHH
ab8a1c82c1 Merge pull request #1310 from Jocund96/main
Add Russian locale file: ru.json
2025-05-26 02:34:03 +05:30
Jasurbek Odilov
e1842ae0ba Merge pull request #1 from Jocund96/Jocund96-patch-1
Add locale Russian
2025-05-25 21:28:57 +02:00
Jasurbek Odilov
989106e914 Add files via upload 2025-05-25 21:28:07 +02:00
Neurofix
de27fb8a81 Create ko.json
Add korean
2025-05-25 14:49:54 +09:00
KRSHH
28109e93bb Merge pull request #1297 from j-hewett/main
Add Spanish translation
2025-05-21 21:44:03 +05:30
Jonah Hewett
fc312516e3 Add Spanish translation 2025-05-21 16:35:37 +01:00
Chou Chamnan
72049f3e91 Add khmer translation (#1291)
* Add khmer language

* Fix khmer language

---------

Co-authored-by: Chamnan dev
2025-05-18 23:03:53 +05:30
inwchamp1337
6cb5de01f8 Added a Thai translation (#1284)
* Added a Thai translation

* Update th.json
2025-05-18 23:03:19 +05:30
KRSHH
0bcf340217 Merge pull request #1281 from Giovannapls/add/pt-br-translate
[Added] pt br translate
2025-05-18 23:01:00 +05:30
Giovanna
994a63c546 [Added] pt br translate 2025-05-14 19:24:13 -03:00
Kenneth Estanislao
d5a3fb0c47 Merge pull request #1268 from jiacheng-0/main
Update __init__.py
2025-05-13 00:57:09 +08:00
Teo Jia Cheng
9690070399 Update __init__.py 2025-05-13 00:14:49 +08:00
Kenneth Estanislao
f3e83b985c Merge pull request #1210 from KunjShah01/main
Update __init__.py
2025-05-12 15:14:58 +08:00
Kenneth Estanislao
e3e3638b79 Merge pull request #1232 from gboeer/patch-1
Add german localization and fix minor typos
2025-05-12 15:14:32 +08:00
VilkkuKoo
4a7874a968 Added a Finnish translation (#1255)
* Added finnish translations

* Fixed a typo
2025-05-11 03:58:53 +05:30
Gordon Böer
75122da389 Create german localization 2025-05-07 13:30:22 +02:00
Gordon Böer
7063bba4b3 fix typos in zh.json 2025-05-07 13:24:54 +02:00
Gordon Böer
bdbd7dcfbc fix typos in ui.py 2025-05-07 13:23:31 +02:00
KUNJ SHAH
a64940def7 update 2025-05-05 13:19:46 +00:00
KUNJ SHAH
fe4a87e8f2 update 2025-05-05 13:19:29 +00:00
KUNJ SHAH
9ecd2dab83 changes 2025-05-05 13:10:00 +00:00
KUNJ SHAH
c9f36eb350 Update __init__.py 2025-05-05 18:29:44 +05:30
Kenneth Estanislao
b1f610d432 Update README.md 2025-05-05 08:30:44 +08:00
KRSHH
d86c36dc47 Change Download URL 2025-05-04 23:44:01 +05:30
Kenneth Estanislao
532e7c05ee Merge pull request #1155 from killerlux/patch-1
Added commands for linux
2025-05-03 10:16:02 +08:00
KRSHH
267a273cb2 Download for windows 2025-05-01 22:12:55 +05:30
KRSHH
938aa9eaf1 Delete media/download.png 2025-05-01 22:11:21 +05:30
KRSHH
37bac27302 Add files via upload 2025-05-01 22:10:52 +05:30
killerlux
84836932e6 Added cmomands for linux 2025-04-30 23:09:12 +02:00
Kenneth Estanislao
e879d2ca64 Merge pull request #1094 from NeuroDonu/main
fix core.py for face_enhancer and add TRT support in face_enhancer
2025-04-30 22:28:46 +08:00
Kenneth Estanislao
181144ce33 Update requirements.txt 2025-04-20 03:02:23 +08:00
NeuroDonu
890beb0eae fix & add trt support 2025-04-19 16:03:49 +03:00
NeuroDonu
75b5b096d6 fix 2025-04-19 16:03:24 +03:00
Kenneth Estanislao
40e47a469c Update requirements.txt 2025-04-19 03:41:00 +08:00
KRSHH
874abb4e59 v2 prebuilt 2025-04-17 09:34:10 +05:30
Kenneth Estanislao
18b259da70 Update requirements.txt
improves speed by 10 to 40%
2025-04-17 02:44:24 +08:00
Kenneth Estanislao
01900dcfb5 Revert "Update metadata.py"
This reverts commit 90d5c28542.
2025-04-17 02:39:05 +08:00
Kenneth Estanislao
07e30fe781 Revert "Update face_swapper.py"
This reverts commit 104d8cf4d6.
2025-04-17 02:03:34 +08:00
Kenneth Estanislao
3dda4f2179 Update requirements.txt 2025-04-14 17:45:07 +08:00
Kenneth Estanislao
71735e4f60 Update requirements.txt
update requirements.txt
2025-04-13 03:36:51 +08:00
Kenneth Estanislao
90d5c28542 Update metadata.py
- 40% faster than 1.8
- compatible with 50xx GPU
- onnxruntime 1.21
2025-04-13 03:34:10 +08:00
Kenneth Estanislao
104d8cf4d6 Update face_swapper.py
compatibility with inswapper 1.21
2025-04-13 01:13:40 +08:00
KRSHH
ac3696b69d remove prebuilt 2025-04-04 16:02:28 +05:30
Kenneth Estanislao
76fb209e6c Update README.md 2025-03-29 03:28:22 +08:00
Kenneth Estanislao
2dcd552c4b Update README.md 2025-03-29 03:23:49 +08:00
19 changed files with 526 additions and 161 deletions

View File

@@ -30,14 +30,13 @@ 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. 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.1 Quick Start - Pre-built (Windows/Mac Silicon)
## Quick Start - Pre-built (Windows / Nvidia) <a href="https://deeplivecam.net/index.php/quickstart"> <img src="media/Download.png" width="285" height="77" />
<a href="https://hacksider.gumroad.com/l/vccdmm"> <img src="https://github.com/user-attachments/assets/7d993b32-e3e8-4cd3-bbfb-a549152ebdd5" width="285" height="77" /> ##### This is the fastest build you can get if you have a discrete NVIDIA or AMD GPU or Mac Silicon, And you'll receive special priority support.
##### This is the fastest build you can get if you have a discrete NVIDIA GPU.
###### These Pre-builts are perfect for non-technical users or those who don't have time to, or can't manually install all the requirements. Just a heads-up: this is an open-source project, so you can also install it manually. ###### These Pre-builts are perfect for non-technical users or those who don't have time to, or can't manually install all the requirements. Just a heads-up: this is an open-source project, so you can also install it manually.
## TLDR; Live Deepfake in just 3 Clicks ## TLDR; Live Deepfake in just 3 Clicks
![easysteps](https://github.com/user-attachments/assets/af825228-852c-411b-b787-ffd9aac72fc6) ![easysteps](https://github.com/user-attachments/assets/af825228-852c-411b-b787-ffd9aac72fc6)
@@ -99,7 +98,7 @@ Users are expected to use this software responsibly and legally. If using a real
## Installation (Manual) ## Installation (Manual)
**Please be aware that the installation requires technical skills and is not for beginners. Consider downloading the prebuilt version.** **Please be aware that the installation requires technical skills and is not for beginners. Consider downloading the quickstart version.**
<details> <details>
<summary>Click to see the process</summary> <summary>Click to see the process</summary>
@@ -110,7 +109,7 @@ This is more likely to work on your computer but will be slower as it utilizes t
**1. Set up Your Platform** **1. Set up Your Platform**
- Python (3.10 recommended) - Python (3.11 recommended)
- pip - pip
- git - git
- [ffmpeg](https://www.youtube.com/watch?v=OlNWCpFdVMA) - ```iex (irm ffmpeg.tc.ht)``` - [ffmpeg](https://www.youtube.com/watch?v=OlNWCpFdVMA) - ```iex (irm ffmpeg.tc.ht)```
@@ -134,26 +133,34 @@ Place these files in the "**models**" folder.
We highly recommend using a `venv` to avoid issues. We highly recommend using a `venv` to avoid issues.
For Windows: For Windows:
```bash ```bash
python -m venv venv python -m venv venv
venv\Scripts\activate venv\Scripts\activate
pip install -r requirements.txt pip install -r requirements.txt
``` ```
For Linux:
```bash
# Ensure you use the installed Python 3.10
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
```
**For macOS:** **For macOS:**
Apple Silicon (M1/M2/M3) requires specific setup: Apple Silicon (M1/M2/M3) requires specific setup:
```bash ```bash
# Install Python 3.10 (specific version is important) # Install Python 3.11 (specific version is important)
brew install python@3.10 brew install python@3.11
# Install tkinter package (required for the GUI) # Install tkinter package (required for the GUI)
brew install python-tk@3.10 brew install python-tk@3.10
# Create and activate virtual environment with Python 3.10 # Create and activate virtual environment with Python 3.11
python3.10 -m venv venv python3.11 -m venv venv
source venv/bin/activate source venv/bin/activate
# Install dependencies # Install dependencies
@@ -180,12 +187,16 @@ pip install -r requirements.txt
**CUDA Execution Provider (Nvidia)** **CUDA Execution Provider (Nvidia)**
1. Install [CUDA Toolkit 11.8.0](https://developer.nvidia.com/cuda-11-8-0-download-archive) 1. Install [CUDA Toolkit 12.8.0](https://developer.nvidia.com/cuda-12-8-0-download-archive)
2. Install dependencies: 2. Install [cuDNN v8.9.7 for CUDA 12.x](https://developer.nvidia.com/rdp/cudnn-archive) (required for onnxruntime-gpu):
- Download cuDNN v8.9.7 for CUDA 12.x
- Make sure the cuDNN bin directory is in your system PATH
3. Install dependencies:
```bash ```bash
pip install -U torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu128
pip uninstall onnxruntime onnxruntime-gpu pip uninstall onnxruntime onnxruntime-gpu
pip install onnxruntime-gpu==1.16.3 pip install onnxruntime-gpu==1.21.0
``` ```
3. Usage: 3. Usage:
@@ -225,7 +236,7 @@ python3.10 run.py --execution-provider coreml
# Uninstall conflicting versions if needed # Uninstall conflicting versions if needed
brew uninstall --ignore-dependencies python@3.11 python@3.13 brew uninstall --ignore-dependencies python@3.11 python@3.13
# Keep only Python 3.10 # Keep only Python 3.11
brew cleanup brew cleanup
``` ```
@@ -235,7 +246,7 @@ python3.10 run.py --execution-provider coreml
```bash ```bash
pip uninstall onnxruntime onnxruntime-coreml pip uninstall onnxruntime onnxruntime-coreml
pip install onnxruntime-coreml==1.13.1 pip install onnxruntime-coreml==1.21.0
``` ```
2. Usage: 2. Usage:
@@ -250,7 +261,7 @@ python run.py --execution-provider coreml
```bash ```bash
pip uninstall onnxruntime onnxruntime-directml pip uninstall onnxruntime onnxruntime-directml
pip install onnxruntime-directml==1.15.1 pip install onnxruntime-directml==1.21.0
``` ```
2. Usage: 2. Usage:
@@ -265,7 +276,7 @@ python run.py --execution-provider directml
```bash ```bash
pip uninstall onnxruntime onnxruntime-openvino pip uninstall onnxruntime onnxruntime-openvino
pip install onnxruntime-openvino==1.15.0 pip install onnxruntime-openvino==1.21.0
``` ```
2. Usage: 2. Usage:
@@ -293,19 +304,6 @@ python run.py --execution-provider openvino
- Use a screen capture tool like OBS to stream. - Use a screen capture tool like OBS to stream.
- To change the face, select a new source image. - To change the face, select a new source image.
## Tips and Tricks
Check out these helpful guides to get the most out of Deep-Live-Cam:
- [Unlocking the Secrets to the Perfect Deepfake Image](https://deeplivecam.net/index.php/blog/tips-and-tricks/unlocking-the-secrets-to-the-perfect-deepfake-image) - Learn how to create the best deepfake with full head coverage
- [Video Call with DeepLiveCam](https://deeplivecam.net/index.php/blog/tips-and-tricks/video-call-with-deeplivecam) - Make your meetings livelier by using DeepLiveCam with OBS and meeting software
- [Have a Special Guest!](https://deeplivecam.net/index.php/blog/tips-and-tricks/have-a-special-guest) - Tutorial on how to use face mapping to add special guests to your stream
- [Watch Deepfake Movies in Realtime](https://deeplivecam.net/index.php/blog/tips-and-tricks/watch-deepfake-movies-in-realtime) - See yourself star in any video without processing the video
- [Better Quality without Sacrificing Speed](https://deeplivecam.net/index.php/blog/tips-and-tricks/better-quality-without-sacrificing-speed) - Tips for achieving better results without impacting performance
- [Instant Vtuber!](https://deeplivecam.net/index.php/blog/tips-and-tricks/instant-vtuber) - Create a new persona/vtuber easily using Metahuman Creator
Visit our [official blog](https://deeplivecam.net/index.php/blog/tips-and-tricks) for more tips and tutorials.
## Command Line Arguments (Unmaintained) ## Command Line Arguments (Unmaintained)
``` ```
@@ -349,6 +347,8 @@ Looking for a CLI mode? Using the -s/--source argument will make the run program
- [*"This real-time webcam deepfake tool raises alarms about the future of identity theft"*](https://www.diyphotography.net/this-real-time-webcam-deepfake-tool-raises-alarms-about-the-future-of-identity-theft/) - DIYPhotography - [*"This real-time webcam deepfake tool raises alarms about the future of identity theft"*](https://www.diyphotography.net/this-real-time-webcam-deepfake-tool-raises-alarms-about-the-future-of-identity-theft/) - DIYPhotography
- [*"That's Crazy, Oh God. That's Fucking Freaky Dude... That's So Wild Dude"*](https://www.youtube.com/watch?time_continue=1074&v=py4Tc-Y8BcY) - SomeOrdinaryGamers - [*"That's Crazy, Oh God. That's Fucking Freaky Dude... That's So Wild Dude"*](https://www.youtube.com/watch?time_continue=1074&v=py4Tc-Y8BcY) - SomeOrdinaryGamers
- [*"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 - [*"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)
## Credits ## Credits
@@ -378,4 +378,4 @@ Looking for a CLI mode? Using the -s/--source argument will make the run program
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=hacksider/deep-live-cam&type=Date" /> <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=hacksider/deep-live-cam&type=Date" />
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=hacksider/deep-live-cam&type=Date" /> <img alt="Star History Chart" src="https://api.star-history.com/svg?repos=hacksider/deep-live-cam&type=Date" />
</picture> </picture>
</a> </a>

46
locales/de.json Normal file
View File

@@ -0,0 +1,46 @@
{
"Source x Target Mapper": "Quelle x Ziel Zuordnung",
"select a source image": "Wähle ein Quellbild",
"Preview": "Vorschau",
"select a target image or video": "Wähle ein Zielbild oder Video",
"save image output file": "Bildausgabedatei speichern",
"save video output file": "Videoausgabedatei speichern",
"select a target image": "Wähle ein Zielbild",
"source": "Quelle",
"Select a target": "Wähle ein Ziel",
"Select a face": "Wähle ein Gesicht",
"Keep audio": "Audio beibehalten",
"Face Enhancer": "Gesichtsverbesserung",
"Many faces": "Mehrere Gesichter",
"Show FPS": "FPS anzeigen",
"Keep fps": "FPS beibehalten",
"Keep frames": "Frames beibehalten",
"Fix Blueish Cam": "Bläuliche Kamera korrigieren",
"Mouth Mask": "Mundmaske",
"Show Mouth Mask Box": "Mundmaskenrahmen anzeigen",
"Start": "Starten",
"Live": "Live",
"Destroy": "Beenden",
"Map faces": "Gesichter zuordnen",
"Processing...": "Verarbeitung läuft...",
"Processing succeed!": "Verarbeitung erfolgreich!",
"Processing ignored!": "Verarbeitung ignoriert!",
"Failed to start camera": "Kamera konnte nicht gestartet werden",
"Please complete pop-up or close it.": "Bitte das Pop-up komplettieren oder schließen.",
"Getting unique faces": "Einzigartige Gesichter erfassen",
"Please select a source image first": "Bitte zuerst ein Quellbild auswählen",
"No faces found in target": "Keine Gesichter im Zielbild gefunden",
"Add": "Hinzufügen",
"Clear": "Löschen",
"Submit": "Absenden",
"Select source image": "Quellbild auswählen",
"Select target image": "Zielbild auswählen",
"Please provide mapping!": "Bitte eine Zuordnung angeben!",
"At least 1 source with target is required!": "Mindestens eine Quelle mit einem Ziel ist erforderlich!",
"At least 1 source with target is required!": "Mindestens eine Quelle mit einem Ziel ist erforderlich!",
"Face could not be detected in last upload!": "Im letzten Upload konnte kein Gesicht erkannt werden!",
"Select Camera:": "Kamera auswählen:",
"All mappings cleared!": "Alle Zuordnungen gelöscht!",
"Mappings successfully submitted!": "Zuordnungen erfolgreich übermittelt!",
"Source x Target Mapper is already open.": "Quell-zu-Ziel-Zuordnung ist bereits geöffnet."
}

46
locales/es.json Normal file
View File

@@ -0,0 +1,46 @@
{
"Source x Target Mapper": "Mapeador de fuente x destino",
"select a source image": "Seleccionar imagen fuente",
"Preview": "Vista previa",
"select a target image or video": "elegir un video o una imagen fuente",
"save image output file": "guardar imagen final",
"save video output file": "guardar video final",
"select a target image": "elegir una imagen objetiva",
"source": "fuente",
"Select a target": "Elegir un destino",
"Select a face": "Elegir una cara",
"Keep audio": "Mantener audio original",
"Face Enhancer": "Potenciador de caras",
"Many faces": "Varias caras",
"Show FPS": "Mostrar fps",
"Keep fps": "Mantener fps",
"Keep frames": "Mantener frames",
"Fix Blueish Cam": "Corregir tono azul de video",
"Mouth Mask": "Máscara de boca",
"Show Mouth Mask Box": "Mostrar área de la máscara de boca",
"Start": "Iniciar",
"Live": "En vivo",
"Destroy": "Borrar",
"Map faces": "Mapear caras",
"Processing...": "Procesando...",
"Processing succeed!": "¡Proceso terminado con éxito!",
"Processing ignored!": "¡Procesamiento omitido!",
"Failed to start camera": "No se pudo iniciar la cámara",
"Please complete pop-up or close it.": "Complete o cierre el pop-up",
"Getting unique faces": "Buscando caras únicas",
"Please select a source image first": "Primero, seleccione una imagen fuente",
"No faces found in target": "No se encontró una cara en el destino",
"Add": "Agregar",
"Clear": "Limpiar",
"Submit": "Enviar",
"Select source image": "Seleccionar imagen fuente",
"Select target image": "Seleccionar imagen destino",
"Please provide mapping!": "Por favor, proporcione un mapeo",
"At least 1 source with target is required!": "Se requiere al menos una fuente con un destino.",
"At least 1 source with target is required!": "Se requiere al menos una fuente con un destino.",
"Face could not be detected in last upload!": "¡No se pudo encontrar una cara en el último video o imagen!",
"Select Camera:": "Elegir cámara:",
"All mappings cleared!": "¡Todos los mapeos fueron borrados!",
"Mappings successfully submitted!": "Mapeos enviados con éxito!",
"Source x Target Mapper is already open.": "El mapeador de fuente x destino ya está abierto."
}

46
locales/fi.json Normal file
View File

@@ -0,0 +1,46 @@
{
"Source x Target Mapper": "Source x Target Kartoitin",
"select an source image": "Valitse lähde kuva",
"Preview": "Esikatsele",
"select an target image or video": "Valitse kohde kuva tai video",
"save image output file": "tallenna kuva",
"save video output file": "tallenna video",
"select an target image": "Valitse kohde kuva",
"source": "lähde",
"Select a target": "Valitse kohde",
"Select a face": "Valitse kasvot",
"Keep audio": "Säilytä ääni",
"Face Enhancer": "Kasvojen Parantaja",
"Many faces": "Useampia kasvoja",
"Show FPS": "Näytä FPS",
"Keep fps": "Säilytä FPS",
"Keep frames": "Säilytä ruudut",
"Fix Blueish Cam": "Korjaa Sinertävä Kamera",
"Mouth Mask": "Suu Maski",
"Show Mouth Mask Box": "Näytä Suu Maski Laatiko",
"Start": "Aloita",
"Live": "Live",
"Destroy": "Tuhoa",
"Map faces": "Kartoita kasvot",
"Processing...": "Prosessoi...",
"Processing succeed!": "Prosessointi onnistui!",
"Processing ignored!": "Prosessointi lopetettu!",
"Failed to start camera": "Kameran käynnistäminen epäonnistui",
"Please complete pop-up or close it.": "Viimeistele tai sulje ponnahdusikkuna",
"Getting unique faces": "Hankitaan uniikkeja kasvoja",
"Please select a source image first": "Valitse ensin lähde kuva",
"No faces found in target": "Kasvoja ei löydetty kohteessa",
"Add": "Lisää",
"Clear": "Tyhjennä",
"Submit": "Lähetä",
"Select source image": "Valitse lähde kuva",
"Select target image": "Valitse kohde kuva",
"Please provide mapping!": "Tarjoa kartoitus!",
"Atleast 1 source with target is required!": "Vähintään 1 lähde kohteen kanssa on vaadittu!",
"At least 1 source with target is required!": "Vähintään 1 lähde kohteen kanssa on vaadittu!",
"Face could not be detected in last upload!": "Kasvoja ei voitu tunnistaa edellisessä latauksessa!",
"Select Camera:": "Valitse Kamera:",
"All mappings cleared!": "Kaikki kartoitukset tyhjennetty!",
"Mappings successfully submitted!": "Kartoitukset lähetety onnistuneesti!",
"Source x Target Mapper is already open.": "Lähde x Kohde Kartoittaja on jo auki."
}

45
locales/km.json Normal file
View File

@@ -0,0 +1,45 @@
{
"Source x Target Mapper": "ប្រភប x បន្ថែម Mapper",
"select a source image": "ជ្រើសរើសប្រភពរូបភាព",
"Preview": "បង្ហាញ",
"select a target image or video": "ជ្រើសរើសគោលដៅរូបភាពឬវីដេអូ",
"save image output file": "រក្សាទុកលទ្ធផលឯកសាររូបភាព",
"save video output file": "រក្សាទុកលទ្ធផលឯកសារវីដេអូ",
"select a target image": "ជ្រើសរើសគោលដៅរូបភាព",
"source": "ប្រភព",
"Select a target": "ជ្រើសរើសគោលដៅ",
"Select a face": "ជ្រើសរើសមុខ",
"Keep audio": "រម្លងសម្លេង",
"Face Enhancer": "ឧបករណ៍ពង្រឹងមុខ",
"Many faces": "ទម្រង់មុខច្រើន",
"Show FPS": "បង្ហាញ FPS",
"Keep fps": "រម្លង fps",
"Keep frames": "រម្លងទម្រង់",
"Fix Blueish Cam": "ជួសជុល Cam Blueish",
"Mouth Mask": "របាំងមាត់",
"Show Mouth Mask Box": "បង្ហាញប្រអប់របាំងមាត់",
"Start": "ចាប់ផ្ដើម",
"Live": "ផ្សាយផ្ទាល់",
"Destroy": "លុប",
"Map faces": "ផែនទីមុខ",
"Processing...": "កំពុងដំណើរការ...",
"Processing succeed!": "ការដំណើរការទទួលបានជោគជ័យ!",
"Processing ignored!": "ការដំណើរការមិនទទួលបានជោគជ័យ!",
"Failed to start camera": "បរាជ័យដើម្បីចាប់ផ្ដើមបើកកាមេរ៉ា",
"Please complete pop-up or close it.": "សូមបញ្ចប់ផ្ទាំងផុស ឬបិទវា.",
"Getting unique faces": "ការចាប់ផ្ដើមទម្រង់មុខប្លែក",
"Please select a source image first": "សូមជ្រើសរើសប្រភពរូបភាពដំបូង",
"No faces found in target": "រកអត់ឃើញមុខនៅក្នុងគោលដៅ",
"Add": "បន្ថែម",
"Clear": "សម្អាត",
"Submit": "បញ្ចូន",
"Select source image": "ជ្រើសរើសប្រភពរូបភាព",
"Select target image": "ជ្រើសរើសគោលដៅរូបភាព",
"Please provide mapping!": "សូមផ្ដល់នៅផែនទី",
"At least 1 source with target is required!": "ត្រូវការប្រភពយ៉ាងហោចណាស់ ១ ដែលមានគោលដៅ!",
"Face could not be detected in last upload!": "មុខមិនអាចភ្ជាប់នៅក្នុងការបង្ហេាះចុងក្រោយ!",
"Select Camera:": "ជ្រើសរើសកាមេរ៉ា",
"All mappings cleared!": "ផែនទីទាំងអស់ត្រូវបានសម្អាត!",
"Mappings successfully submitted!": "ផែនទីត្រូវបានបញ្ជូនជោគជ័យ!",
"Source x Target Mapper is already open.": "ប្រភព x Target Mapper បានបើករួចហើយ។"
}

45
locales/ko.json Normal file
View File

@@ -0,0 +1,45 @@
{
"Source x Target Mapper": "소스 x 타겟 매퍼",
"select a source image": "소스 이미지 선택",
"Preview": "미리보기",
"select a target image or video": "타겟 이미지 또는 영상 선택",
"save image output file": "이미지 출력 파일 저장",
"save video output file": "영상 출력 파일 저장",
"select a target image": "타겟 이미지 선택",
"source": "소스",
"Select a target": "타겟 선택",
"Select a face": "얼굴 선택",
"Keep audio": "오디오 유지",
"Face Enhancer": "얼굴 향상",
"Many faces": "여러 얼굴",
"Show FPS": "FPS 표시",
"Keep fps": "FPS 유지",
"Keep frames": "프레임 유지",
"Fix Blueish Cam": "푸른빛 카메라 보정",
"Mouth Mask": "입 마스크",
"Show Mouth Mask Box": "입 마스크 박스 표시",
"Start": "시작",
"Live": "라이브",
"Destroy": "종료",
"Map faces": "얼굴 매핑",
"Processing...": "처리 중...",
"Processing succeed!": "처리 성공!",
"Processing ignored!": "처리 무시됨!",
"Failed to start camera": "카메라 시작 실패",
"Please complete pop-up or close it.": "팝업을 완료하거나 닫아주세요.",
"Getting unique faces": "고유 얼굴 가져오는 중",
"Please select a source image first": "먼저 소스 이미지를 선택해주세요",
"No faces found in target": "타겟에서 얼굴을 찾을 수 없음",
"Add": "추가",
"Clear": "지우기",
"Submit": "제출",
"Select source image": "소스 이미지 선택",
"Select target image": "타겟 이미지 선택",
"Please provide mapping!": "매핑을 입력해주세요!",
"At least 1 source with target is required!": "최소 하나의 소스와 타겟이 필요합니다!",
"Face could not be detected in last upload!": "최근 업로드에서 얼굴을 감지할 수 없습니다!",
"Select Camera:": "카메라 선택:",
"All mappings cleared!": "모든 매핑이 삭제되었습니다!",
"Mappings successfully submitted!": "매핑이 성공적으로 제출되었습니다!",
"Source x Target Mapper is already open.": "소스 x 타겟 매퍼가 이미 열려 있습니다."
}

46
locales/pt-br.json Normal file
View File

@@ -0,0 +1,46 @@
{
"Source x Target Mapper": "Mapeador de Origem x Destino",
"select an source image": "Escolha uma imagem de origem",
"Preview": "Prévia",
"select an target image or video": "Escolha uma imagem ou vídeo de destino",
"save image output file": "Salvar imagem final",
"save video output file": "Salvar vídeo final",
"select an target image": "Escolha uma imagem de destino",
"source": "Origem",
"Select a target": "Escolha o destino",
"Select a face": "Escolha um rosto",
"Keep audio": "Manter o áudio original",
"Face Enhancer": "Melhorar rosto",
"Many faces": "Vários rostos",
"Show FPS": "Mostrar FPS",
"Keep fps": "Manter FPS",
"Keep frames": "Manter frames",
"Fix Blueish Cam": "Corrigir tom azulado da câmera",
"Mouth Mask": "Máscara da boca",
"Show Mouth Mask Box": "Mostrar área da máscara da boca",
"Start": "Começar",
"Live": "Ao vivo",
"Destroy": "Destruir",
"Map faces": "Mapear rostos",
"Processing...": "Processando...",
"Processing succeed!": "Tudo certo!",
"Processing ignored!": "Processamento ignorado!",
"Failed to start camera": "Não foi possível iniciar a câmera",
"Please complete pop-up or close it.": "Finalize ou feche o pop-up",
"Getting unique faces": "Buscando rostos diferentes",
"Please select a source image first": "Selecione primeiro uma imagem de origem",
"No faces found in target": "Nenhum rosto encontrado na imagem de destino",
"Add": "Adicionar",
"Clear": "Limpar",
"Submit": "Enviar",
"Select source image": "Escolha a imagem de origem",
"Select target image": "Escolha a imagem de destino",
"Please provide mapping!": "Você precisa realizar o mapeamento!",
"Atleast 1 source with target is required!": "É necessária pelo menos uma origem com um destino!",
"At least 1 source with target is required!": "É necessária pelo menos uma origem com um destino!",
"Face could not be detected in last upload!": "Não conseguimos detectar o rosto na última imagem!",
"Select Camera:": "Escolher câmera:",
"All mappings cleared!": "Todos os mapeamentos foram removidos!",
"Mappings successfully submitted!": "Mapeamentos enviados com sucesso!",
"Source x Target Mapper is already open.": "O Mapeador de Origem x Destino já está aberto."
}

45
locales/ru.json Normal file
View File

@@ -0,0 +1,45 @@
{
"Source x Target Mapper": "Сопоставитель Источник x Цель",
"select a source image": "выберите исходное изображение",
"Preview": "Предпросмотр",
"select a target image or video": "выберите целевое изображение или видео",
"save image output file": "сохранить выходной файл изображения",
"save video output file": "сохранить выходной файл видео",
"select a target image": "выберите целевое изображение",
"source": "источник",
"Select a target": "Выберите целевое изображение",
"Select a face": "Выберите лицо",
"Keep audio": "Сохранить аудио",
"Face Enhancer": "Улучшение лица",
"Many faces": "Несколько лиц",
"Show FPS": "Показать FPS",
"Keep fps": "Сохранить FPS",
"Keep frames": "Сохранить кадры",
"Fix Blueish Cam": "Исправить синеву камеры",
"Mouth Mask": "Маска рта",
"Show Mouth Mask Box": "Показать рамку маски рта",
"Start": "Старт",
"Live": "В реальном времени",
"Destroy": "Остановить",
"Map faces": "Сопоставить лица",
"Processing...": "Обработка...",
"Processing succeed!": "Обработка успешна!",
"Processing ignored!": "Обработка проигнорирована!",
"Failed to start camera": "Не удалось запустить камеру",
"Please complete pop-up or close it.": "Пожалуйста, заполните всплывающее окно или закройте его.",
"Getting unique faces": "Получение уникальных лиц",
"Please select a source image first": "Сначала выберите исходное изображение, пожалуйста",
"No faces found in target": "В целевом изображении не найдено лиц",
"Add": "Добавить",
"Clear": "Очистить",
"Submit": "Отправить",
"Select source image": "Выбрать исходное изображение",
"Select target image": "Выбрать целевое изображение",
"Please provide mapping!": "Пожалуйста, укажите сопоставление!",
"At least 1 source with target is required!": "Требуется хотя бы 1 источник с целью!",
"Face could not be detected in last upload!": "Лицо не обнаружено в последнем загруженном изображении!",
"Select Camera:": "Выберите камеру:",
"All mappings cleared!": "Все сопоставления очищены!",
"Mappings successfully submitted!": "Сопоставления успешно отправлены!",
"Source x Target Mapper is already open.": "Сопоставитель Источник-Цель уже открыт."
}

45
locales/th.json Normal file
View File

@@ -0,0 +1,45 @@
{
"Source x Target Mapper": "ตัวจับคู่ต้นทาง x ปลายทาง",
"select a source image": "เลือกรูปภาพต้นฉบับ",
"Preview": "ตัวอย่าง",
"select a target image or video": "เลือกรูปภาพหรือวิดีโอเป้าหมาย",
"save image output file": "บันทึกไฟล์รูปภาพ",
"save video output file": "บันทึกไฟล์วิดีโอ",
"select a target image": "เลือกรูปภาพเป้าหมาย",
"source": "ต้นฉบับ",
"Select a target": "เลือกเป้าหมาย",
"Select a face": "เลือกใบหน้า",
"Keep audio": "เก็บเสียง",
"Face Enhancer": "ปรับปรุงใบหน้า",
"Many faces": "หลายใบหน้า",
"Show FPS": "แสดง FPS",
"Keep fps": "คงค่า FPS",
"Keep frames": "คงค่าเฟรม",
"Fix Blueish Cam": "แก้ไขภาพอมฟ้าจากกล้อง",
"Mouth Mask": "มาสก์ปาก",
"Show Mouth Mask Box": "แสดงกรอบมาสก์ปาก",
"Start": "เริ่ม",
"Live": "สด",
"Destroy": "หยุด",
"Map faces": "จับคู่ใบหน้า",
"Processing...": "กำลังประมวลผล...",
"Processing succeed!": "ประมวลผลสำเร็จแล้ว!",
"Processing ignored!": "การประมวลผลถูกละเว้น",
"Failed to start camera": "ไม่สามารถเริ่มกล้องได้",
"Please complete pop-up or close it.": "โปรดดำเนินการในป๊อปอัปให้เสร็จสิ้น หรือปิด",
"Getting unique faces": "กำลังค้นหาใบหน้าที่ไม่ซ้ำกัน",
"Please select a source image first": "โปรดเลือกภาพต้นฉบับก่อน",
"No faces found in target": "ไม่พบใบหน้าในภาพเป้าหมาย",
"Add": "เพิ่ม",
"Clear": "ล้าง",
"Submit": "ส่ง",
"Select source image": "เลือกภาพต้นฉบับ",
"Select target image": "เลือกภาพเป้าหมาย",
"Please provide mapping!": "โปรดระบุการจับคู่!",
"At least 1 source with target is required!": "ต้องมีการจับคู่ต้นฉบับกับเป้าหมายอย่างน้อย 1 คู่!",
"Face could not be detected in last upload!": "ไม่สามารถตรวจพบใบหน้าในไฟล์อัปโหลดล่าสุด!",
"Select Camera:": "เลือกกล้อง:",
"All mappings cleared!": "ล้างการจับคู่ทั้งหมดแล้ว!",
"Mappings successfully submitted!": "ส่งการจับคู่สำเร็จแล้ว!",
"Source x Target Mapper is already open.": "ตัวจับคู่ต้นทาง x ปลายทาง เปิดอยู่แล้ว"
}

View File

@@ -1,11 +1,11 @@
{ {
"Source x Target Mapper": "Source x Target Mapper", "Source x Target Mapper": "Source x Target Mapper",
"select an source image": "选择一个源图像", "select a source image": "选择一个源图像",
"Preview": "预览", "Preview": "预览",
"select an target image or video": "选择一个目标图像或视频", "select a target image or video": "选择一个目标图像或视频",
"save image output file": "保存图像输出文件", "save image output file": "保存图像输出文件",
"save video output file": "保存视频输出文件", "save video output file": "保存视频输出文件",
"select an target image": "选择一个目标图像", "select a target image": "选择一个目标图像",
"source": "源", "source": "源",
"Select a target": "选择一个目标", "Select a target": "选择一个目标",
"Select a face": "选择一张脸", "Select a face": "选择一张脸",
@@ -36,11 +36,11 @@
"Select source image": "请选取源图像", "Select source image": "请选取源图像",
"Select target image": "请选取目标图像", "Select target image": "请选取目标图像",
"Please provide mapping!": "请提供映射", "Please provide mapping!": "请提供映射",
"Atleast 1 source with target is required!": "至少需要一个来源图像与目标图像相关!", "At least 1 source with target is required!": "至少需要一个来源图像与目标图像相关!",
"At least 1 source with target is required!": "至少需要一个来源图像与目标图像相关!", "At least 1 source with target is required!": "至少需要一个来源图像与目标图像相关!",
"Face could not be detected in last upload!": "最近上传的图像中没有检测到人脸!", "Face could not be detected in last upload!": "最近上传的图像中没有检测到人脸!",
"Select Camera:": "选择摄像头", "Select Camera:": "选择摄像头",
"All mappings cleared!": "所有映射均已清除!", "All mappings cleared!": "所有映射均已清除!",
"Mappings successfully submitted!": "成功提交映射!", "Mappings successfully submitted!": "成功提交映射!",
"Source x Target Mapper is already open.": "源 x 目标映射器已打开。" "Source x Target Mapper is already open.": "源 x 目标映射器已打开。"
} }

BIN
media/Download.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.0 KiB

View File

@@ -0,0 +1,18 @@
import os
import cv2
import numpy as np
# Utility function to support unicode characters in file paths for reading
def imread_unicode(path, flags=cv2.IMREAD_COLOR):
return cv2.imdecode(np.fromfile(path, dtype=np.uint8), flags)
# Utility function to support unicode characters in file paths for writing
def imwrite_unicode(path, img, params=None):
root, ext = os.path.splitext(path)
if not ext:
ext = ".png"
result, encoded_img = cv2.imencode(ext, img, params if params else [])
result, encoded_img = cv2.imencode(f".{ext}", img, params if params is not None else [])
encoded_img.tofile(path)
return True
return False

View File

@@ -1,3 +1,3 @@
name = 'Deep-Live-Cam' name = 'Deep-Live-Cam'
version = '1.8' version = '1.8.1'
edition = 'GitHub Edition' edition = 'GitHub Edition'

View File

@@ -42,18 +42,29 @@ def get_frame_processors_modules(frame_processors: List[str]) -> List[ModuleType
def set_frame_processors_modules_from_ui(frame_processors: List[str]) -> None: def set_frame_processors_modules_from_ui(frame_processors: List[str]) -> None:
global FRAME_PROCESSORS_MODULES global FRAME_PROCESSORS_MODULES
current_processor_names = [proc.__name__.split('.')[-1] for proc in FRAME_PROCESSORS_MODULES]
for frame_processor, state in modules.globals.fp_ui.items(): for frame_processor, state in modules.globals.fp_ui.items():
if state == True and frame_processor not in frame_processors: if state == True and frame_processor not in current_processor_names:
frame_processor_module = load_frame_processor_module(frame_processor)
FRAME_PROCESSORS_MODULES.append(frame_processor_module)
modules.globals.frame_processors.append(frame_processor)
if state == False:
try: try:
frame_processor_module = load_frame_processor_module(frame_processor) frame_processor_module = load_frame_processor_module(frame_processor)
FRAME_PROCESSORS_MODULES.remove(frame_processor_module) FRAME_PROCESSORS_MODULES.append(frame_processor_module)
modules.globals.frame_processors.remove(frame_processor) if frame_processor not in modules.globals.frame_processors:
except: modules.globals.frame_processors.append(frame_processor)
pass except SystemExit:
print(f"Warning: Failed to load frame processor {frame_processor} requested by UI state.")
except Exception as e:
print(f"Warning: Error loading frame processor {frame_processor} requested by UI state: {e}")
elif state == False and frame_processor in current_processor_names:
try:
module_to_remove = next((mod for mod in FRAME_PROCESSORS_MODULES if mod.__name__.endswith(f'.{frame_processor}')), None)
if module_to_remove:
FRAME_PROCESSORS_MODULES.remove(module_to_remove)
if frame_processor in modules.globals.frame_processors:
modules.globals.frame_processors.remove(frame_processor)
except Exception as e:
print(f"Warning: Error removing frame processor {frame_processor}: {e}")
def multi_process_frame(source_path: str, temp_frame_paths: List[str], process_frames: Callable[[str, List[str], Any], None], progress: Any = None) -> None: def multi_process_frame(source_path: str, temp_frame_paths: List[str], process_frames: Callable[[str, List[str], Any], None], progress: Any = None) -> None:
with ThreadPoolExecutor(max_workers=modules.globals.execution_threads) as executor: with ThreadPoolExecutor(max_workers=modules.globals.execution_threads) as executor:

View File

@@ -48,6 +48,17 @@ def pre_start() -> bool:
return True return True
TENSORRT_AVAILABLE = False
try:
import torch_tensorrt
TENSORRT_AVAILABLE = True
except ImportError as im:
print(f"TensorRT is not available: {im}")
pass
except Exception as e:
print(f"TensorRT is not available: {e}")
pass
def get_face_enhancer() -> Any: def get_face_enhancer() -> Any:
global FACE_ENHANCER global FACE_ENHANCER
@@ -55,16 +66,26 @@ def get_face_enhancer() -> Any:
if FACE_ENHANCER is None: if FACE_ENHANCER is None:
model_path = os.path.join(models_dir, "GFPGANv1.4.pth") model_path = os.path.join(models_dir, "GFPGANv1.4.pth")
match platform.system(): selected_device = None
case "Darwin": # Mac OS device_priority = []
if torch.backends.mps.is_available():
mps_device = torch.device("mps")
FACE_ENHANCER = gfpgan.GFPGANer(model_path=model_path, upscale=1, device=mps_device) # type: ignore[attr-defined]
else:
FACE_ENHANCER = gfpgan.GFPGANer(model_path=model_path, upscale=1) # type: ignore[attr-defined]
case _: # Other OS
FACE_ENHANCER = gfpgan.GFPGANer(model_path=model_path, upscale=1) # type: ignore[attr-defined]
if TENSORRT_AVAILABLE and torch.cuda.is_available():
selected_device = torch.device("cuda")
device_priority.append("TensorRT+CUDA")
elif torch.cuda.is_available():
selected_device = torch.device("cuda")
device_priority.append("CUDA")
elif torch.backends.mps.is_available() and platform.system() == "Darwin":
selected_device = torch.device("mps")
device_priority.append("MPS")
elif not torch.cuda.is_available():
selected_device = torch.device("cpu")
device_priority.append("CPU")
FACE_ENHANCER = gfpgan.GFPGANer(model_path=model_path, upscale=1, device=selected_device)
# for debug:
print(f"Selected device: {selected_device} and device priority: {device_priority}")
return FACE_ENHANCER return FACE_ENHANCER

View File

@@ -28,12 +28,14 @@ models_dir = os.path.join(
def pre_check() -> bool: def pre_check() -> bool:
download_directory_path = abs_dir download_directory_path = models_dir
model_url = "https://huggingface.co/hacksider/deep-live-cam/resolve/main/inswapper_128.onnx"
if "CUDAExecutionProvider" in modules.globals.execution_providers:
model_url = "https://huggingface.co/hacksider/deep-live-cam/resolve/main/inswapper_128_fp16.onnx"
conditional_download( conditional_download(
download_directory_path, download_directory_path,
[ [model_url],
"https://huggingface.co/hacksider/deep-live-cam/blob/main/inswapper_128_fp16.onnx"
],
) )
return True return True
@@ -60,7 +62,10 @@ def get_face_swapper() -> Any:
with THREAD_LOCK: with THREAD_LOCK:
if FACE_SWAPPER is None: 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)
FACE_SWAPPER = insightface.model_zoo.get_model( FACE_SWAPPER = insightface.model_zoo.get_model(
model_path, providers=modules.globals.execution_providers model_path, providers=modules.globals.execution_providers
) )

View File

@@ -7,7 +7,6 @@ from cv2_enumerate_cameras import enumerate_cameras # Add this import
from PIL import Image, ImageOps from PIL import Image, ImageOps
import time import time
import json import json
import tkinterdnd2 as tkdnd
import modules.globals import modules.globals
import modules.metadata import modules.metadata
from modules.face_analyser import ( from modules.face_analyser import (
@@ -135,65 +134,50 @@ def load_switch_states():
pass pass
def create_root(start: Callable[[], None], destroy: Callable[[], None]) -> tkdnd.TkinterDnD.Tk: def create_root(start: Callable[[], None], destroy: Callable[[], None]) -> ctk.CTk:
global source_label, target_label, status_label, show_fps_switch global source_label, target_label, status_label, show_fps_switch
load_switch_states() load_switch_states()
ctk.deactivate_automatic_dpi_awareness() ctk.deactivate_automatic_dpi_awareness()
ctk.set_appearance_mode("dark") ctk.set_appearance_mode("system")
ctk.set_default_color_theme(resolve_relative_path("ui.json")) ctk.set_default_color_theme(resolve_relative_path("ui.json"))
root = tkdnd.TkinterDnD.Tk() root = ctk.CTk()
root.minsize(ROOT_WIDTH, ROOT_HEIGHT) root.minsize(ROOT_WIDTH, ROOT_HEIGHT)
root.title( root.title(
f"{modules.metadata.name} {modules.metadata.version} {modules.metadata.edition}" f"{modules.metadata.name} {modules.metadata.version} {modules.metadata.edition}"
) )
root.configure(bg="#050505") root.configure()
root.protocol("WM_DELETE_WINDOW", lambda: destroy()) root.protocol("WM_DELETE_WINDOW", lambda: destroy())
main_frame = ctk.CTkFrame(root, fg_color="#181818", corner_radius=0) source_label = ctk.CTkLabel(root, text=None)
main_frame.pack(fill="both", expand=True, padx=0, pady=0)
source_label = ctk.CTkLabel(main_frame, text=None)
source_label.place(relx=0.1, rely=0.1, relwidth=0.3, relheight=0.25) source_label.place(relx=0.1, rely=0.1, relwidth=0.3, relheight=0.25)
source_label.drop_target_register(tkdnd.DND_FILES)
source_label.dnd_bind("<<Drop>>", lambda event: handle_drop_source(event))
target_label = ctk.CTkLabel(main_frame, text=None) target_label = ctk.CTkLabel(root, text=None)
target_label.place(relx=0.6, rely=0.1, relwidth=0.3, relheight=0.25) target_label.place(relx=0.6, rely=0.1, relwidth=0.3, relheight=0.25)
target_label.drop_target_register(tkdnd.DND_FILES)
target_label.dnd_bind("<<Drop>>", lambda event: handle_drop_target(event))
select_face_button = ctk.CTkButton( select_face_button = ctk.CTkButton(
main_frame, text=_("Select a face"), cursor="hand2", command=lambda: select_source_path() root, text=_("Select a face"), cursor="hand2", command=lambda: select_source_path()
) )
select_face_button.place(relx=0.1, rely=0.4, relwidth=0.3, relheight=0.1) select_face_button.place(relx=0.1, rely=0.4, relwidth=0.3, relheight=0.1)
select_face_button.drop_target_register(tkdnd.DND_FILES)
select_face_button.dnd_bind("<<Drop>>", lambda event: handle_drop_source(event))
swap_faces_button = ctk.CTkButton( swap_faces_button = ctk.CTkButton(
main_frame, text="", cursor="hand2", command=lambda: swap_faces_paths() root, text="", cursor="hand2", command=lambda: swap_faces_paths()
) )
swap_faces_button.place(relx=0.45, rely=0.4, relwidth=0.1, relheight=0.1) swap_faces_button.place(relx=0.45, rely=0.4, relwidth=0.1, relheight=0.1)
select_target_button = ctk.CTkButton( select_target_button = ctk.CTkButton(
main_frame, root,
text=_("Select a target"), text=_("Select a target"),
cursor="hand2", cursor="hand2",
command=lambda: select_target_path(), command=lambda: select_target_path(),
) )
select_target_button.place(relx=0.6, rely=0.4, relwidth=0.3, relheight=0.1) select_target_button.place(relx=0.6, rely=0.4, relwidth=0.3, relheight=0.1)
select_target_button.drop_target_register(tkdnd.DND_FILES)
select_target_button.dnd_bind("<<Drop>>", lambda event: handle_drop_target(event))
keep_fps_value = ctk.BooleanVar(value=modules.globals.keep_fps) keep_fps_value = ctk.BooleanVar(value=modules.globals.keep_fps)
keep_fps_checkbox = ctk.CTkSwitch( keep_fps_checkbox = ctk.CTkSwitch(
main_frame, root,
text=_("Keep fps"), text=_("Keep fps"),
variable=keep_fps_value, variable=keep_fps_value,
cursor="hand2", cursor="hand2",
@@ -206,7 +190,7 @@ def create_root(start: Callable[[], None], destroy: Callable[[], None]) -> tkdnd
keep_frames_value = ctk.BooleanVar(value=modules.globals.keep_frames) keep_frames_value = ctk.BooleanVar(value=modules.globals.keep_frames)
keep_frames_switch = ctk.CTkSwitch( keep_frames_switch = ctk.CTkSwitch(
main_frame, root,
text=_("Keep frames"), text=_("Keep frames"),
variable=keep_frames_value, variable=keep_frames_value,
cursor="hand2", cursor="hand2",
@@ -219,7 +203,7 @@ def create_root(start: Callable[[], None], destroy: Callable[[], None]) -> tkdnd
enhancer_value = ctk.BooleanVar(value=modules.globals.fp_ui["face_enhancer"]) enhancer_value = ctk.BooleanVar(value=modules.globals.fp_ui["face_enhancer"])
enhancer_switch = ctk.CTkSwitch( enhancer_switch = ctk.CTkSwitch(
main_frame, root,
text=_("Face Enhancer"), text=_("Face Enhancer"),
variable=enhancer_value, variable=enhancer_value,
cursor="hand2", cursor="hand2",
@@ -232,7 +216,7 @@ def create_root(start: Callable[[], None], destroy: Callable[[], None]) -> tkdnd
keep_audio_value = ctk.BooleanVar(value=modules.globals.keep_audio) keep_audio_value = ctk.BooleanVar(value=modules.globals.keep_audio)
keep_audio_switch = ctk.CTkSwitch( keep_audio_switch = ctk.CTkSwitch(
main_frame, root,
text=_("Keep audio"), text=_("Keep audio"),
variable=keep_audio_value, variable=keep_audio_value,
cursor="hand2", cursor="hand2",
@@ -245,7 +229,7 @@ def create_root(start: Callable[[], None], destroy: Callable[[], None]) -> tkdnd
many_faces_value = ctk.BooleanVar(value=modules.globals.many_faces) many_faces_value = ctk.BooleanVar(value=modules.globals.many_faces)
many_faces_switch = ctk.CTkSwitch( many_faces_switch = ctk.CTkSwitch(
main_frame, root,
text=_("Many faces"), text=_("Many faces"),
variable=many_faces_value, variable=many_faces_value,
cursor="hand2", cursor="hand2",
@@ -258,7 +242,7 @@ def create_root(start: Callable[[], None], destroy: Callable[[], None]) -> tkdnd
color_correction_value = ctk.BooleanVar(value=modules.globals.color_correction) color_correction_value = ctk.BooleanVar(value=modules.globals.color_correction)
color_correction_switch = ctk.CTkSwitch( color_correction_switch = ctk.CTkSwitch(
main_frame, root,
text=_("Fix Blueish Cam"), text=_("Fix Blueish Cam"),
variable=color_correction_value, variable=color_correction_value,
cursor="hand2", cursor="hand2",
@@ -269,9 +253,13 @@ def create_root(start: Callable[[], None], destroy: Callable[[], None]) -> tkdnd
) )
color_correction_switch.place(relx=0.6, rely=0.70) color_correction_switch.place(relx=0.6, rely=0.70)
# nsfw_value = ctk.BooleanVar(value=modules.globals.nsfw_filter)
# nsfw_switch = ctk.CTkSwitch(root, text='NSFW filter', variable=nsfw_value, cursor='hand2', command=lambda: setattr(modules.globals, 'nsfw_filter', nsfw_value.get()))
# nsfw_switch.place(relx=0.6, rely=0.7)
map_faces = ctk.BooleanVar(value=modules.globals.map_faces) map_faces = ctk.BooleanVar(value=modules.globals.map_faces)
map_faces_switch = ctk.CTkSwitch( map_faces_switch = ctk.CTkSwitch(
main_frame, root,
text=_("Map faces"), text=_("Map faces"),
variable=map_faces, variable=map_faces,
cursor="hand2", cursor="hand2",
@@ -285,7 +273,7 @@ def create_root(start: Callable[[], None], destroy: Callable[[], None]) -> tkdnd
show_fps_value = ctk.BooleanVar(value=modules.globals.show_fps) show_fps_value = ctk.BooleanVar(value=modules.globals.show_fps)
show_fps_switch = ctk.CTkSwitch( show_fps_switch = ctk.CTkSwitch(
main_frame, root,
text=_("Show FPS"), text=_("Show FPS"),
variable=show_fps_value, variable=show_fps_value,
cursor="hand2", cursor="hand2",
@@ -298,7 +286,7 @@ def create_root(start: Callable[[], None], destroy: Callable[[], None]) -> tkdnd
mouth_mask_var = ctk.BooleanVar(value=modules.globals.mouth_mask) mouth_mask_var = ctk.BooleanVar(value=modules.globals.mouth_mask)
mouth_mask_switch = ctk.CTkSwitch( mouth_mask_switch = ctk.CTkSwitch(
main_frame, root,
text=_("Mouth Mask"), text=_("Mouth Mask"),
variable=mouth_mask_var, variable=mouth_mask_var,
cursor="hand2", cursor="hand2",
@@ -308,7 +296,7 @@ def create_root(start: Callable[[], None], destroy: Callable[[], None]) -> tkdnd
show_mouth_mask_box_var = ctk.BooleanVar(value=modules.globals.show_mouth_mask_box) show_mouth_mask_box_var = ctk.BooleanVar(value=modules.globals.show_mouth_mask_box)
show_mouth_mask_box_switch = ctk.CTkSwitch( show_mouth_mask_box_switch = ctk.CTkSwitch(
main_frame, root,
text=_("Show Mouth Mask Box"), text=_("Show Mouth Mask Box"),
variable=show_mouth_mask_box_var, variable=show_mouth_mask_box_var,
cursor="hand2", cursor="hand2",
@@ -319,22 +307,22 @@ def create_root(start: Callable[[], None], destroy: Callable[[], None]) -> tkdnd
show_mouth_mask_box_switch.place(relx=0.6, rely=0.55) show_mouth_mask_box_switch.place(relx=0.6, rely=0.55)
start_button = ctk.CTkButton( start_button = ctk.CTkButton(
main_frame, text=_("Start"), cursor="hand2", command=lambda: analyze_target(start, root) root, text=_("Start"), cursor="hand2", command=lambda: analyze_target(start, root)
) )
start_button.place(relx=0.15, rely=0.80, relwidth=0.2, relheight=0.05) start_button.place(relx=0.15, rely=0.80, relwidth=0.2, relheight=0.05)
stop_button = ctk.CTkButton( stop_button = ctk.CTkButton(
main_frame, text=_("Destroy"), cursor="hand2", command=lambda: destroy() root, text=_("Destroy"), cursor="hand2", command=lambda: destroy()
) )
stop_button.place(relx=0.4, rely=0.80, relwidth=0.2, relheight=0.05) stop_button.place(relx=0.4, rely=0.80, relwidth=0.2, relheight=0.05)
preview_button = ctk.CTkButton( preview_button = ctk.CTkButton(
main_frame, text=_("Preview"), cursor="hand2", command=lambda: toggle_preview() root, text=_("Preview"), cursor="hand2", command=lambda: toggle_preview()
) )
preview_button.place(relx=0.65, rely=0.80, relwidth=0.2, relheight=0.05) preview_button.place(relx=0.65, rely=0.80, relwidth=0.2, relheight=0.05)
# --- Camera Selection --- # --- Camera Selection ---
camera_label = ctk.CTkLabel(main_frame, text=_("Select Camera:")) camera_label = ctk.CTkLabel(root, text=_("Select Camera:"))
camera_label.place(relx=0.1, rely=0.86, relwidth=0.2, relheight=0.05) camera_label.place(relx=0.1, rely=0.86, relwidth=0.2, relheight=0.05)
available_cameras = get_available_cameras() available_cameras = get_available_cameras()
@@ -343,7 +331,7 @@ def create_root(start: Callable[[], None], destroy: Callable[[], None]) -> tkdnd
if not camera_names or camera_names[0] == "No cameras found": if not camera_names or camera_names[0] == "No cameras found":
camera_variable = ctk.StringVar(value="No cameras found") camera_variable = ctk.StringVar(value="No cameras found")
camera_optionmenu = ctk.CTkOptionMenu( camera_optionmenu = ctk.CTkOptionMenu(
main_frame, root,
variable=camera_variable, variable=camera_variable,
values=["No cameras found"], values=["No cameras found"],
state="disabled", state="disabled",
@@ -351,13 +339,13 @@ def create_root(start: Callable[[], None], destroy: Callable[[], None]) -> tkdnd
else: else:
camera_variable = ctk.StringVar(value=camera_names[0]) camera_variable = ctk.StringVar(value=camera_names[0])
camera_optionmenu = ctk.CTkOptionMenu( camera_optionmenu = ctk.CTkOptionMenu(
main_frame, variable=camera_variable, values=camera_names root, variable=camera_variable, values=camera_names
) )
camera_optionmenu.place(relx=0.35, rely=0.86, relwidth=0.25, relheight=0.05) camera_optionmenu.place(relx=0.35, rely=0.86, relwidth=0.25, relheight=0.05)
live_button = ctk.CTkButton( live_button = ctk.CTkButton(
main_frame, root,
text=_("Live"), text=_("Live"),
cursor="hand2", cursor="hand2",
command=lambda: webcam_preview( command=lambda: webcam_preview(
@@ -377,11 +365,11 @@ def create_root(start: Callable[[], None], destroy: Callable[[], None]) -> tkdnd
live_button.place(relx=0.65, rely=0.86, relwidth=0.2, relheight=0.05) live_button.place(relx=0.65, rely=0.86, relwidth=0.2, relheight=0.05)
# --- End Camera Selection --- # --- End Camera Selection ---
status_label = ctk.CTkLabel(main_frame, text=None, justify="center") status_label = ctk.CTkLabel(root, text=None, justify="center")
status_label.place(relx=0.1, rely=0.9, relwidth=0.8) status_label.place(relx=0.1, rely=0.9, relwidth=0.8)
donate_label = ctk.CTkLabel( donate_label = ctk.CTkLabel(
main_frame, text="Deep Live Cam", justify="center", cursor="hand2" root, text="Deep Live Cam", justify="center", cursor="hand2"
) )
donate_label.place(relx=0.1, rely=0.95, relwidth=0.8) donate_label.place(relx=0.1, rely=0.95, relwidth=0.8)
donate_label.configure( donate_label.configure(
@@ -441,7 +429,7 @@ def create_source_target_popup(
POPUP.destroy() POPUP.destroy()
select_output_path(start) select_output_path(start)
else: else:
update_pop_status("Atleast 1 source with target is required!") update_pop_status("At least 1 source with target is required!")
scrollable_frame = ctk.CTkScrollableFrame( scrollable_frame = ctk.CTkScrollableFrame(
POPUP, width=POPUP_SCROLL_WIDTH, height=POPUP_SCROLL_HEIGHT POPUP, width=POPUP_SCROLL_WIDTH, height=POPUP_SCROLL_HEIGHT
@@ -501,7 +489,7 @@ def update_popup_source(
global source_label_dict global source_label_dict
source_path = ctk.filedialog.askopenfilename( source_path = ctk.filedialog.askopenfilename(
title=_("select an source image"), title=_("select a source image"),
initialdir=RECENT_DIRECTORY_SOURCE, initialdir=RECENT_DIRECTORY_SOURCE,
filetypes=[img_ft], filetypes=[img_ft],
) )
@@ -596,7 +584,7 @@ def select_source_path() -> None:
PREVIEW.withdraw() PREVIEW.withdraw()
source_path = ctk.filedialog.askopenfilename( source_path = ctk.filedialog.askopenfilename(
title=_("select an source image"), title=_("select a source image"),
initialdir=RECENT_DIRECTORY_SOURCE, initialdir=RECENT_DIRECTORY_SOURCE,
filetypes=[img_ft], filetypes=[img_ft],
) )
@@ -639,7 +627,7 @@ def select_target_path() -> None:
PREVIEW.withdraw() PREVIEW.withdraw()
target_path = ctk.filedialog.askopenfilename( target_path = ctk.filedialog.askopenfilename(
title=_("select an target image or video"), title=_("select a target image or video"),
initialdir=RECENT_DIRECTORY_TARGET, initialdir=RECENT_DIRECTORY_TARGET,
filetypes=[img_ft, vid_ft], filetypes=[img_ft, vid_ft],
) )
@@ -809,6 +797,7 @@ def webcam_preview(root: ctk.CTk, camera_index: int):
) )
def get_available_cameras(): def get_available_cameras():
"""Returns a list of available camera names and indices.""" """Returns a list of available camera names and indices."""
if platform.system() == "Windows": if platform.system() == "Windows":
@@ -1014,6 +1003,7 @@ def create_source_target_popup_for_webcam(
close_button.place(relx=0.7, rely=0.92, relwidth=0.2, relheight=0.05) close_button.place(relx=0.7, rely=0.92, relwidth=0.2, relheight=0.05)
def clear_source_target_images(map: list): def clear_source_target_images(map: list):
global source_label_dict_live, target_label_dict_live global source_label_dict_live, target_label_dict_live
@@ -1118,7 +1108,7 @@ def update_webcam_source(
global source_label_dict_live global source_label_dict_live
source_path = ctk.filedialog.askopenfilename( source_path = ctk.filedialog.askopenfilename(
title=_("select an source image"), title=_("select a source image"),
initialdir=RECENT_DIRECTORY_SOURCE, initialdir=RECENT_DIRECTORY_SOURCE,
filetypes=[img_ft], filetypes=[img_ft],
) )
@@ -1170,7 +1160,7 @@ def update_webcam_target(
global target_label_dict_live global target_label_dict_live
target_path = ctk.filedialog.askopenfilename( target_path = ctk.filedialog.askopenfilename(
title=_("select an target image"), title=_("select a target image"),
initialdir=RECENT_DIRECTORY_SOURCE, initialdir=RECENT_DIRECTORY_SOURCE,
filetypes=[img_ft], filetypes=[img_ft],
) )
@@ -1214,43 +1204,3 @@ def update_webcam_target(
else: else:
update_pop_live_status("Face could not be detected in last upload!") update_pop_live_status("Face could not be detected in last upload!")
return map return map
# New drop handler functions
def handle_drop_source(event):
"""Handle files dropped on source button or label"""
file_path = event.data
# On Windows, file paths may be enclosed in {}
if file_path.startswith("{") and file_path.endswith("}"):
file_path = file_path[1:-1]
if is_image(file_path):
modules.globals.source_path = file_path
global RECENT_DIRECTORY_SOURCE
RECENT_DIRECTORY_SOURCE = os.path.dirname(modules.globals.source_path)
image = render_image_preview(modules.globals.source_path, (200, 200))
source_label.configure(image=image)
else:
update_status("Please drop an image file for the source.")
def handle_drop_target(event):
"""Handle files dropped on target button or label"""
file_path = event.data
# On Windows, file paths may be enclosed in {}
if file_path.startswith("{") and file_path.endswith("}"):
file_path = file_path[1:-1]
if is_image(file_path) or is_video(file_path):
modules.globals.target_path = file_path
global RECENT_DIRECTORY_TARGET
RECENT_DIRECTORY_TARGET = os.path.dirname(modules.globals.target_path)
if is_image(file_path):
image = render_image_preview(modules.globals.target_path, (200, 200))
target_label.configure(image=image)
elif is_video(file_path):
video_frame = render_video_preview(file_path, (200, 200))
target_label.configure(image=video_frame)
else:
update_status("Please drop an image or video file for the target.")

View File

@@ -1,25 +1,21 @@
--extra-index-url https://download.pytorch.org/whl/cu118 --extra-index-url https://download.pytorch.org/whl/cu128
numpy>=1.23.5,<2 numpy>=1.23.5,<2
typing-extensions>=4.8.0 typing-extensions>=4.8.0
opencv-python==4.10.0.84 opencv-python==4.10.0.84
cv2_enumerate_cameras==1.1.15 cv2_enumerate_cameras==1.1.15
onnx==1.16.0 onnx==1.18.0
insightface==0.7.3 insightface==0.7.3
psutil==5.9.8 psutil==5.9.8
tk==0.1.0 tk==0.1.0
customtkinter==5.2.2 customtkinter==5.2.2
pillow==11.1.0 pillow==11.1.0
torch==2.5.1+cu118; sys_platform != 'darwin' torch; sys_platform != 'darwin'
torch==2.5.1; sys_platform == 'darwin' torch==2.5.1; sys_platform == 'darwin'
torchvision==0.20.1; sys_platform != 'darwin' torchvision; sys_platform != 'darwin'
torchvision==0.20.1; sys_platform == 'darwin' torchvision==0.20.1; sys_platform == 'darwin'
onnxruntime-silicon==1.16.3; sys_platform == 'darwin' and platform_machine == 'arm64' onnxruntime-silicon==1.16.3; sys_platform == 'darwin' and platform_machine == 'arm64'
onnxruntime-gpu==1.16.3; sys_platform != 'darwin' onnxruntime-gpu==1.22.0; sys_platform != 'darwin'
tensorflow; sys_platform != 'darwin' tensorflow; sys_platform != 'darwin'
opennsfw2==0.10.2 opennsfw2==0.10.2
protobuf==4.23.2 protobuf==4.25.1
tqdm==4.66.4
gfpgan==1.3.8
tkinterdnd2==0.4.2
pygrabber==0.2