* Update official url for cuda 12-2 wheels

* Fix preview for audio to image

* Prevent download loop when remote is unreachable

* Prevent download loop when remote is unreachable

* changes (#444)

* Tidy up monkey patch

* Use cpu core count for concurrency count

* Dynamic concurrency_count for ideal Gradio performance

* Conditional download face analyser models

* Fix testing via pre_check()

* Introduce checking to process manager for blocking the UI

* Introduce checking to process manager for blocking the UI

* Introduce checking to process manager for blocking the UI

* Introduce checking to process manager for blocking the UI

* Move the blocking while model download to the correct position

* Remove unused imports

---------

Co-authored-by: Harisreedhar <46858047+harisreedhar@users.noreply.github.com>
This commit is contained in:
Henry Ruhs 2024-03-20 10:02:08 +01:00 committed by GitHub
parent 1e2031e149
commit 6e67d7bff6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 133 additions and 52 deletions

View File

@ -1,5 +1,6 @@
from typing import Any, Dict from typing import Any, Dict
from functools import lru_cache from functools import lru_cache
from time import sleep
import threading import threading
import cv2 import cv2
import numpy import numpy
@ -7,7 +8,7 @@ import onnxruntime
from tqdm import tqdm from tqdm import tqdm
import facefusion.globals import facefusion.globals
from facefusion import wording from facefusion import process_manager, wording
from facefusion.typing import VisionFrame, ModelValue, Fps from facefusion.typing import VisionFrame, ModelValue, Fps
from facefusion.execution import apply_execution_provider_options from facefusion.execution import apply_execution_provider_options
from facefusion.vision import get_video_frame, count_video_frame_total, read_image, detect_video_fps from facefusion.vision import get_video_frame, count_video_frame_total, read_image, detect_video_fps
@ -33,6 +34,8 @@ def get_content_analyser() -> Any:
global CONTENT_ANALYSER global CONTENT_ANALYSER
with THREAD_LOCK: with THREAD_LOCK:
while process_manager.is_checking():
sleep(0.5)
if CONTENT_ANALYSER is None: if CONTENT_ANALYSER is None:
model_path = MODELS.get('open_nsfw').get('path') model_path = MODELS.get('open_nsfw').get('path')
CONTENT_ANALYSER = onnxruntime.InferenceSession(model_path, providers = apply_execution_provider_options(facefusion.globals.execution_providers)) CONTENT_ANALYSER = onnxruntime.InferenceSession(model_path, providers = apply_execution_provider_options(facefusion.globals.execution_providers))
@ -49,7 +52,9 @@ def pre_check() -> bool:
if not facefusion.globals.skip_download: if not facefusion.globals.skip_download:
download_directory_path = resolve_relative_path('../.assets/models') download_directory_path = resolve_relative_path('../.assets/models')
model_url = MODELS.get('open_nsfw').get('url') model_url = MODELS.get('open_nsfw').get('url')
process_manager.check()
conditional_download(download_directory_path, [ model_url ]) conditional_download(download_directory_path, [ model_url ])
process_manager.end()
return True return True

View File

@ -22,19 +22,19 @@ def conditional_download(download_directory_path : str, urls : List[str]) -> Non
executor.submit(get_download_size, url) executor.submit(get_download_size, url)
for url in urls: for url in urls:
download_file_path = os.path.join(download_directory_path, os.path.basename(url)) download_file_path = os.path.join(download_directory_path, os.path.basename(url))
initial = os.path.getsize(download_file_path) if is_file(download_file_path) else 0 initial_size = os.path.getsize(download_file_path) if is_file(download_file_path) else 0
total = get_download_size(url) download_size = get_download_size(url)
if initial < total: if initial_size < download_size:
with tqdm(total = total, initial = initial, desc = wording.get('downloading'), unit = 'B', unit_scale = True, unit_divisor = 1024, ascii = ' =', disable = facefusion.globals.log_level in [ 'warn', 'error' ]) as progress: with tqdm(total = download_size, initial = initial_size, desc = wording.get('downloading'), unit = 'B', unit_scale = True, unit_divisor = 1024, ascii = ' =', disable = facefusion.globals.log_level in [ 'warn', 'error' ]) as progress:
subprocess.Popen([ 'curl', '--create-dirs', '--silent', '--insecure', '--location', '--continue-at', '-', '--output', download_file_path, url ]) subprocess.Popen([ 'curl', '--create-dirs', '--silent', '--insecure', '--location', '--continue-at', '-', '--output', download_file_path, url ])
current = initial current_size = initial_size
while current < total: while current_size < download_size:
if is_file(download_file_path): if is_file(download_file_path):
current = os.path.getsize(download_file_path) current_size = os.path.getsize(download_file_path)
progress.update(current - progress.n) progress.update(current_size - progress.n)
if not is_download_done(url, download_file_path): if download_size and not is_download_done(url, download_file_path):
os.remove(download_file_path) os.remove(download_file_path)
conditional_download(download_directory_path, [ url] ) conditional_download(download_directory_path, [ url ])
@lru_cache(maxsize = None) @lru_cache(maxsize = None)

View File

@ -1,10 +1,12 @@
from typing import Any, Optional, List, Tuple from typing import Any, Optional, List, Tuple
from time import sleep
import threading import threading
import cv2 import cv2
import numpy import numpy
import onnxruntime import onnxruntime
import facefusion.globals import facefusion.globals
from facefusion import process_manager
from facefusion.common_helper import get_first from facefusion.common_helper import get_first
from facefusion.face_helper import warp_face_by_face_landmark_5, warp_face_by_translation, create_static_anchors, distance_to_face_landmark_5, distance_to_bounding_box, convert_face_landmark_68_to_5, apply_nms, categorize_age, categorize_gender from facefusion.face_helper import warp_face_by_face_landmark_5, warp_face_by_translation, create_static_anchors, distance_to_face_landmark_5, distance_to_bounding_box, convert_face_landmark_68_to_5, apply_nms, categorize_age, categorize_gender
from facefusion.face_store import get_static_faces, set_static_faces from facefusion.face_store import get_static_faces, set_static_faces
@ -77,6 +79,8 @@ def get_face_analyser() -> Any:
face_detectors = {} face_detectors = {}
with THREAD_LOCK: with THREAD_LOCK:
while process_manager.is_checking():
sleep(0.5)
if FACE_ANALYSER is None: if FACE_ANALYSER is None:
if facefusion.globals.face_detector_model in [ 'many', 'retinaface' ]: if facefusion.globals.face_detector_model in [ 'many', 'retinaface' ]:
face_detector = onnxruntime.InferenceSession(MODELS.get('face_detector_retinaface').get('path'), providers = apply_execution_provider_options(facefusion.globals.execution_providers)) face_detector = onnxruntime.InferenceSession(MODELS.get('face_detector_retinaface').get('path'), providers = apply_execution_provider_options(facefusion.globals.execution_providers))
@ -121,18 +125,29 @@ def pre_check() -> bool:
download_directory_path = resolve_relative_path('../.assets/models') download_directory_path = resolve_relative_path('../.assets/models')
model_urls =\ model_urls =\
[ [
MODELS.get('face_detector_retinaface').get('url'),
MODELS.get('face_detector_scrfd').get('url'),
MODELS.get('face_detector_yoloface').get('url'),
MODELS.get('face_detector_yunet').get('url'),
MODELS.get('face_recognizer_arcface_blendswap').get('url'),
MODELS.get('face_recognizer_arcface_inswapper').get('url'),
MODELS.get('face_recognizer_arcface_simswap').get('url'),
MODELS.get('face_recognizer_arcface_uniface').get('url'),
MODELS.get('face_landmarker').get('url'), MODELS.get('face_landmarker').get('url'),
MODELS.get('gender_age').get('url'), MODELS.get('gender_age').get('url')
] ]
if facefusion.globals.face_detector_model in [ 'many', 'retinaface' ]:
model_urls.append(MODELS.get('face_detector_retinaface').get('url'))
if facefusion.globals.face_detector_model in [ 'many', 'scrfd' ]:
model_urls.append(MODELS.get('face_detector_scrfd').get('url'))
if facefusion.globals.face_detector_model in [ 'many', 'yoloface' ]:
model_urls.append(MODELS.get('face_detector_yoloface').get('url'))
if facefusion.globals.face_detector_model in [ 'yunet' ]:
model_urls.append(MODELS.get('face_detector_yunet').get('url'))
if facefusion.globals.face_recognizer_model == 'arcface_blendswap':
model_urls.append(MODELS.get('face_recognizer_arcface_blendswap').get('url'))
if facefusion.globals.face_recognizer_model == 'arcface_inswapper':
model_urls.append(MODELS.get('face_recognizer_arcface_inswapper').get('url'))
if facefusion.globals.face_recognizer_model == 'arcface_simswap':
model_urls.append(MODELS.get('face_recognizer_arcface_simswap').get('url'))
if facefusion.globals.face_recognizer_model == 'arcface_uniface':
model_urls.append(MODELS.get('face_recognizer_arcface_uniface').get('url'))
process_manager.check()
conditional_download(download_directory_path, model_urls) conditional_download(download_directory_path, model_urls)
process_manager.end()
return True return True

View File

@ -1,12 +1,14 @@
from typing import Any, Dict, List from typing import Any, Dict, List
from cv2.typing import Size from cv2.typing import Size
from functools import lru_cache from functools import lru_cache
from time import sleep
import threading import threading
import cv2 import cv2
import numpy import numpy
import onnxruntime import onnxruntime
import facefusion.globals import facefusion.globals
from facefusion import process_manager
from facefusion.typing import FaceLandmark68, VisionFrame, Mask, Padding, FaceMaskRegion, ModelSet from facefusion.typing import FaceLandmark68, VisionFrame, Mask, Padding, FaceMaskRegion, ModelSet
from facefusion.execution import apply_execution_provider_options from facefusion.execution import apply_execution_provider_options
from facefusion.filesystem import resolve_relative_path from facefusion.filesystem import resolve_relative_path
@ -57,6 +59,8 @@ def get_face_parser() -> Any:
global FACE_PARSER global FACE_PARSER
with THREAD_LOCK: with THREAD_LOCK:
while process_manager.is_checking():
sleep(0.5)
if FACE_PARSER is None: if FACE_PARSER is None:
model_path = MODELS.get('face_parser').get('path') model_path = MODELS.get('face_parser').get('path')
FACE_PARSER = onnxruntime.InferenceSession(model_path, providers = apply_execution_provider_options(facefusion.globals.execution_providers)) FACE_PARSER = onnxruntime.InferenceSession(model_path, providers = apply_execution_provider_options(facefusion.globals.execution_providers))
@ -83,7 +87,9 @@ def pre_check() -> bool:
MODELS.get('face_occluder').get('url'), MODELS.get('face_occluder').get('url'),
MODELS.get('face_parser').get('url'), MODELS.get('face_parser').get('url'),
] ]
process_manager.check()
conditional_download(download_directory_path, model_urls) conditional_download(download_directory_path, model_urls)
process_manager.end()
return True return True

View File

@ -15,7 +15,6 @@ if platform.system().lower() == 'darwin':
ONNXRUNTIMES['default'] = ('onnxruntime', '1.17.1') ONNXRUNTIMES['default'] = ('onnxruntime', '1.17.1')
else: else:
ONNXRUNTIMES['default'] = ('onnxruntime', '1.16.3') ONNXRUNTIMES['default'] = ('onnxruntime', '1.16.3')
if platform.system().lower() == 'linux' or platform.system().lower() == 'windows':
ONNXRUNTIMES['cuda-12.2'] = ('onnxruntime-gpu', '1.17.1') ONNXRUNTIMES['cuda-12.2'] = ('onnxruntime-gpu', '1.17.1')
ONNXRUNTIMES['cuda-11.8'] = ('onnxruntime-gpu', '1.16.3') ONNXRUNTIMES['cuda-11.8'] = ('onnxruntime-gpu', '1.16.3')
ONNXRUNTIMES['openvino'] = ('onnxruntime-openvino', '1.16.0') ONNXRUNTIMES['openvino'] = ('onnxruntime-openvino', '1.16.0')
@ -71,6 +70,6 @@ def run(program : ArgumentParser) -> None:
else: else:
subprocess.call([ 'pip', 'uninstall', 'onnxruntime', onnxruntime_name, '-y', '-q' ]) subprocess.call([ 'pip', 'uninstall', 'onnxruntime', onnxruntime_name, '-y', '-q' ])
if onnxruntime == 'cuda-12.2': if onnxruntime == 'cuda-12.2':
subprocess.call([ 'pip', 'install', onnxruntime_name + '==' + onnxruntime_version, '--extra-index-url', 'https://pkgs.dev.azure.com/onnxruntime/onnxruntime/_packaging/onnxruntime-cuda-12/pypi/simple', '--force-reinstall' ]) subprocess.call([ 'pip', 'install', onnxruntime_name + '==' + onnxruntime_version, '--extra-index-url', 'https://aiinfra.pkgs.visualstudio.com/PublicPackages/_packaging/onnxruntime-cuda-12/pypi/simple', '--force-reinstall' ])
else: else:
subprocess.call([ 'pip', 'install', onnxruntime_name + '==' + onnxruntime_version, '--force-reinstall' ]) subprocess.call([ 'pip', 'install', onnxruntime_name + '==' + onnxruntime_version, '--force-reinstall' ])

View File

@ -2,7 +2,7 @@ METADATA =\
{ {
'name': 'FaceFusion', 'name': 'FaceFusion',
'description': 'Next generation face swapper and enhancer', 'description': 'Next generation face swapper and enhancer',
'version': '2.4.0', 'version': '2.4.1',
'license': 'MIT', 'license': 'MIT',
'author': 'Henry Ruhs', 'author': 'Henry Ruhs',
'url': 'https://facefusion.io' 'url': 'https://facefusion.io'

View File

@ -15,6 +15,10 @@ def set_process_state(process_state : ProcessState) -> None:
PROCESS_STATE = process_state PROCESS_STATE = process_state
def is_checking() -> bool:
return get_process_state() == 'checking'
def is_processing() -> bool: def is_processing() -> bool:
return get_process_state() == 'processing' return get_process_state() == 'processing'
@ -27,6 +31,10 @@ def is_pending() -> bool:
return get_process_state() == 'pending' return get_process_state() == 'pending'
def check() -> None:
set_process_state('checking')
def start() -> None: def start() -> None:
set_process_state('processing') set_process_state('processing')

View File

@ -1,5 +1,6 @@
from typing import Any, List, Literal, Optional from typing import Any, List, Literal, Optional
from argparse import ArgumentParser from argparse import ArgumentParser
from time import sleep
import cv2 import cv2
import threading import threading
import numpy import numpy
@ -87,6 +88,8 @@ def get_frame_processor() -> Any:
global FRAME_PROCESSOR global FRAME_PROCESSOR
with THREAD_LOCK: with THREAD_LOCK:
while process_manager.is_checking():
sleep(0.5)
if FRAME_PROCESSOR is None: if FRAME_PROCESSOR is None:
model_path = get_options('model').get('path') model_path = get_options('model').get('path')
FRAME_PROCESSOR = onnxruntime.InferenceSession(model_path, providers = apply_execution_provider_options(facefusion.globals.execution_providers)) FRAME_PROCESSOR = onnxruntime.InferenceSession(model_path, providers = apply_execution_provider_options(facefusion.globals.execution_providers))
@ -131,7 +134,9 @@ def pre_check() -> bool:
if not facefusion.globals.skip_download: if not facefusion.globals.skip_download:
download_directory_path = resolve_relative_path('../.assets/models') download_directory_path = resolve_relative_path('../.assets/models')
model_url = get_options('model').get('url') model_url = get_options('model').get('url')
process_manager.check()
conditional_download(download_directory_path, [ model_url ]) conditional_download(download_directory_path, [ model_url ])
process_manager.end()
return True return True

View File

@ -1,5 +1,6 @@
from typing import Any, List, Literal, Optional from typing import Any, List, Literal, Optional
from argparse import ArgumentParser from argparse import ArgumentParser
from time import sleep
import threading import threading
import numpy import numpy
import onnx import onnx
@ -99,6 +100,8 @@ def get_frame_processor() -> Any:
global FRAME_PROCESSOR global FRAME_PROCESSOR
with THREAD_LOCK: with THREAD_LOCK:
while process_manager.is_checking():
sleep(0.5)
if FRAME_PROCESSOR is None: if FRAME_PROCESSOR is None:
model_path = get_options('model').get('path') model_path = get_options('model').get('path')
FRAME_PROCESSOR = onnxruntime.InferenceSession(model_path, providers = apply_execution_provider_options(facefusion.globals.execution_providers)) FRAME_PROCESSOR = onnxruntime.InferenceSession(model_path, providers = apply_execution_provider_options(facefusion.globals.execution_providers))
@ -115,6 +118,8 @@ def get_model_matrix() -> Any:
global MODEL_MATRIX global MODEL_MATRIX
with THREAD_LOCK: with THREAD_LOCK:
while process_manager.is_checking():
sleep(0.5)
if MODEL_MATRIX is None: if MODEL_MATRIX is None:
model_path = get_options('model').get('path') model_path = get_options('model').get('path')
model = onnx.load(model_path) model = onnx.load(model_path)
@ -171,7 +176,9 @@ def pre_check() -> bool:
if not facefusion.globals.skip_download: if not facefusion.globals.skip_download:
download_directory_path = resolve_relative_path('../.assets/models') download_directory_path = resolve_relative_path('../.assets/models')
model_url = get_options('model').get('url') model_url = get_options('model').get('url')
process_manager.check()
conditional_download(download_directory_path, [ model_url ]) conditional_download(download_directory_path, [ model_url ])
process_manager.end()
return True return True

View File

@ -1,5 +1,6 @@
from typing import Any, List, Literal, Optional from typing import Any, List, Literal, Optional
from argparse import ArgumentParser from argparse import ArgumentParser
from time import sleep
import threading import threading
import cv2 import cv2
import numpy import numpy
@ -69,6 +70,8 @@ def get_frame_processor() -> Any:
global FRAME_PROCESSOR global FRAME_PROCESSOR
with THREAD_LOCK: with THREAD_LOCK:
while process_manager.is_checking():
sleep(0.5)
if FRAME_PROCESSOR is None: if FRAME_PROCESSOR is None:
model_path = get_options('model').get('path') model_path = get_options('model').get('path')
FRAME_PROCESSOR = onnxruntime.InferenceSession(model_path, providers = apply_execution_provider_options(facefusion.globals.execution_providers)) FRAME_PROCESSOR = onnxruntime.InferenceSession(model_path, providers = apply_execution_provider_options(facefusion.globals.execution_providers))
@ -113,7 +116,9 @@ def pre_check() -> bool:
if not facefusion.globals.skip_download: if not facefusion.globals.skip_download:
download_directory_path = resolve_relative_path('../.assets/models') download_directory_path = resolve_relative_path('../.assets/models')
model_url = get_options('model').get('url') model_url = get_options('model').get('url')
process_manager.check()
conditional_download(download_directory_path, [ model_url ]) conditional_download(download_directory_path, [ model_url ])
process_manager.end()
return True return True

View File

@ -1,5 +1,6 @@
from typing import Any, List, Literal, Optional from typing import Any, List, Literal, Optional
from argparse import ArgumentParser from argparse import ArgumentParser
from time import sleep
import threading import threading
import cv2 import cv2
import numpy import numpy
@ -45,6 +46,8 @@ def get_frame_processor() -> Any:
global FRAME_PROCESSOR global FRAME_PROCESSOR
with THREAD_LOCK: with THREAD_LOCK:
while process_manager.is_checking():
sleep(0.5)
if FRAME_PROCESSOR is None: if FRAME_PROCESSOR is None:
model_path = get_options('model').get('path') model_path = get_options('model').get('path')
FRAME_PROCESSOR = onnxruntime.InferenceSession(model_path, providers = apply_execution_provider_options(facefusion.globals.execution_providers)) FRAME_PROCESSOR = onnxruntime.InferenceSession(model_path, providers = apply_execution_provider_options(facefusion.globals.execution_providers))
@ -87,7 +90,9 @@ def pre_check() -> bool:
if not facefusion.globals.skip_download: if not facefusion.globals.skip_download:
download_directory_path = resolve_relative_path('../.assets/models') download_directory_path = resolve_relative_path('../.assets/models')
model_url = get_options('model').get('url') model_url = get_options('model').get('url')
process_manager.check()
conditional_download(download_directory_path, [ model_url ]) conditional_download(download_directory_path, [ model_url ])
process_manager.end()
return True return True

View File

@ -49,7 +49,7 @@ Fps = float
Padding = Tuple[int, int, int, int] Padding = Tuple[int, int, int, int]
Resolution = Tuple[int, int] Resolution = Tuple[int, int]
ProcessState = Literal['processing', 'stopping', 'pending'] ProcessState = Literal['checking', 'processing', 'stopping', 'pending']
QueuePayload = TypedDict('QueuePayload', QueuePayload = TypedDict('QueuePayload',
{ {
'frame_number' : int, 'frame_number' : int,

View File

@ -1,10 +1,10 @@
from typing import Optional, Dict, Any from typing import Optional, Dict, Any, Tuple
import gradio import gradio
import facefusion.globals import facefusion.globals
import facefusion.choices import facefusion.choices
from facefusion import wording from facefusion import face_analyser, wording
from facefusion.typing import FaceAnalyserOrder, FaceAnalyserAge, FaceAnalyserGender, FaceDetectorModel from facefusion.typing import FaceAnalyserOrder, FaceAnalyserAge, FaceAnalyserGender, FaceDetectorModel
from facefusion.uis.core import register_ui_component from facefusion.uis.core import register_ui_component
@ -83,7 +83,7 @@ def listen() -> None:
FACE_ANALYSER_ORDER_DROPDOWN.change(update_face_analyser_order, inputs = FACE_ANALYSER_ORDER_DROPDOWN) FACE_ANALYSER_ORDER_DROPDOWN.change(update_face_analyser_order, inputs = FACE_ANALYSER_ORDER_DROPDOWN)
FACE_ANALYSER_AGE_DROPDOWN.change(update_face_analyser_age, inputs = FACE_ANALYSER_AGE_DROPDOWN) FACE_ANALYSER_AGE_DROPDOWN.change(update_face_analyser_age, inputs = FACE_ANALYSER_AGE_DROPDOWN)
FACE_ANALYSER_GENDER_DROPDOWN.change(update_face_analyser_gender, inputs = FACE_ANALYSER_GENDER_DROPDOWN) FACE_ANALYSER_GENDER_DROPDOWN.change(update_face_analyser_gender, inputs = FACE_ANALYSER_GENDER_DROPDOWN)
FACE_DETECTOR_MODEL_DROPDOWN.change(update_face_detector_model, inputs = FACE_DETECTOR_MODEL_DROPDOWN, outputs = FACE_DETECTOR_SIZE_DROPDOWN) FACE_DETECTOR_MODEL_DROPDOWN.change(update_face_detector_model, inputs = FACE_DETECTOR_MODEL_DROPDOWN, outputs = [ FACE_DETECTOR_MODEL_DROPDOWN, FACE_DETECTOR_SIZE_DROPDOWN ])
FACE_DETECTOR_SIZE_DROPDOWN.change(update_face_detector_size, inputs = FACE_DETECTOR_SIZE_DROPDOWN) FACE_DETECTOR_SIZE_DROPDOWN.change(update_face_detector_size, inputs = FACE_DETECTOR_SIZE_DROPDOWN)
FACE_DETECTOR_SCORE_SLIDER.release(update_face_detector_score, inputs = FACE_DETECTOR_SCORE_SLIDER) FACE_DETECTOR_SCORE_SLIDER.release(update_face_detector_score, inputs = FACE_DETECTOR_SCORE_SLIDER)
FACE_LANDMARKER_SCORE_SLIDER.release(update_face_landmarker_score, inputs = FACE_LANDMARKER_SCORE_SLIDER) FACE_LANDMARKER_SCORE_SLIDER.release(update_face_landmarker_score, inputs = FACE_LANDMARKER_SCORE_SLIDER)
@ -101,12 +101,14 @@ def update_face_analyser_gender(face_analyser_gender : FaceAnalyserGender) -> No
facefusion.globals.face_analyser_gender = face_analyser_gender if face_analyser_gender != 'none' else None facefusion.globals.face_analyser_gender = face_analyser_gender if face_analyser_gender != 'none' else None
def update_face_detector_model(face_detector_model : FaceDetectorModel) -> gradio.Dropdown: def update_face_detector_model(face_detector_model : FaceDetectorModel) -> Tuple[gradio.Dropdown, gradio.Dropdown]:
facefusion.globals.face_detector_model = face_detector_model facefusion.globals.face_detector_model = face_detector_model
facefusion.globals.face_detector_size = '640x640' update_face_detector_size('640x640')
if facefusion.globals.face_detector_size in facefusion.choices.face_detector_set[face_detector_model]: if face_analyser.pre_check():
return gradio.Dropdown(value = facefusion.globals.face_detector_size, choices = facefusion.choices.face_detector_set[face_detector_model]) if facefusion.globals.face_detector_size in facefusion.choices.face_detector_set[face_detector_model]:
return gradio.Dropdown(value = facefusion.globals.face_detector_size, choices = [ facefusion.globals.face_detector_size ]) return gradio.Dropdown(value = facefusion.globals.face_detector_model), gradio.Dropdown(value = facefusion.globals.face_detector_size, choices = facefusion.choices.face_detector_set[face_detector_model])
return gradio.Dropdown(value = facefusion.globals.face_detector_model), gradio.Dropdown(value = facefusion.globals.face_detector_size, choices = [ facefusion.globals.face_detector_size ])
return gradio.Dropdown(), gradio.Dropdown()
def update_face_detector_size(face_detector_size : str) -> None: def update_face_detector_size(face_detector_size : str) -> None:

View File

@ -2,7 +2,7 @@ from typing import List, Optional, Tuple
import gradio import gradio
import facefusion.globals import facefusion.globals
from facefusion import wording from facefusion import face_analyser, wording
from facefusion.processors.frame.core import load_frame_processor_module from facefusion.processors.frame.core import load_frame_processor_module
from facefusion.processors.frame import globals as frame_processors_globals, choices as frame_processors_choices from facefusion.processors.frame import globals as frame_processors_globals, choices as frame_processors_choices
from facefusion.processors.frame.typings import FaceDebuggerItem, FaceEnhancerModel, FaceSwapperModel, FrameEnhancerModel, LipSyncerModel from facefusion.processors.frame.typings import FaceDebuggerItem, FaceEnhancerModel, FaceSwapperModel, FrameEnhancerModel, LipSyncerModel
@ -134,7 +134,7 @@ def update_face_swapper_model(face_swapper_model : FaceSwapperModel) -> gradio.D
face_swapper_module = load_frame_processor_module('face_swapper') face_swapper_module = load_frame_processor_module('face_swapper')
face_swapper_module.clear_frame_processor() face_swapper_module.clear_frame_processor()
face_swapper_module.set_options('model', face_swapper_module.MODELS[face_swapper_model]) face_swapper_module.set_options('model', face_swapper_module.MODELS[face_swapper_model])
if face_swapper_module.pre_check(): if face_analyser.pre_check() and face_swapper_module.pre_check():
return gradio.Dropdown(value = frame_processors_globals.face_swapper_model) return gradio.Dropdown(value = frame_processors_globals.face_swapper_model)
return gradio.Dropdown() return gradio.Dropdown()

View File

@ -5,7 +5,7 @@ import gradio
import numpy import numpy
import facefusion.globals import facefusion.globals
from facefusion import wording, logger from facefusion import logger, wording
from facefusion.audio import get_audio_frame, create_empty_audio_frame from facefusion.audio import get_audio_frame, create_empty_audio_frame
from facefusion.common_helper import get_first from facefusion.common_helper import get_first
from facefusion.core import conditional_append_reference_faces from facefusion.core import conditional_append_reference_faces
@ -45,12 +45,11 @@ def render() -> None:
source_frames = read_static_images(facefusion.globals.source_paths) source_frames = read_static_images(facefusion.globals.source_paths)
source_face = get_average_face(source_frames) source_face = get_average_face(source_frames)
source_audio_path = get_first(filter_audio_paths(facefusion.globals.source_paths)) source_audio_path = get_first(filter_audio_paths(facefusion.globals.source_paths))
if source_audio_path and facefusion.globals.output_video_fps: source_audio_frame = create_empty_audio_frame()
source_audio_frame = get_audio_frame(source_audio_path, facefusion.globals.output_video_fps, facefusion.globals.reference_frame_number) if source_audio_path and facefusion.globals.output_video_fps and facefusion.globals.reference_frame_number:
if not numpy.any(source_audio_frame): temp_audio_frame = get_audio_frame(source_audio_path, facefusion.globals.output_video_fps, facefusion.globals.reference_frame_number)
source_audio_frame = create_empty_audio_frame() if numpy.any(temp_audio_frame):
else: source_audio_frame = temp_audio_frame
source_audio_frame = None
if is_image(facefusion.globals.target_path): if is_image(facefusion.globals.target_path):
target_vision_frame = read_static_image(facefusion.globals.target_path) target_vision_frame = read_static_image(facefusion.globals.target_path)
preview_vision_frame = process_preview_frame(reference_faces, source_face, source_audio_frame, target_vision_frame) preview_vision_frame = process_preview_frame(reference_faces, source_face, source_audio_frame, target_vision_frame)
@ -142,7 +141,6 @@ def clear_and_update_preview_image(frame_number : int = 0) -> gradio.Image:
clear_face_analyser() clear_face_analyser()
clear_reference_faces() clear_reference_faces()
clear_static_faces() clear_static_faces()
sleep(0.5)
return update_preview_image(frame_number) return update_preview_image(frame_number)
@ -158,15 +156,14 @@ def update_preview_image(frame_number : int = 0) -> gradio.Image:
source_frames = read_static_images(facefusion.globals.source_paths) source_frames = read_static_images(facefusion.globals.source_paths)
source_face = get_average_face(source_frames) source_face = get_average_face(source_frames)
source_audio_path = get_first(filter_audio_paths(facefusion.globals.source_paths)) source_audio_path = get_first(filter_audio_paths(facefusion.globals.source_paths))
if source_audio_path and facefusion.globals.output_video_fps: source_audio_frame = create_empty_audio_frame()
if source_audio_path and facefusion.globals.output_video_fps and facefusion.globals.reference_frame_number:
reference_audio_frame_number = facefusion.globals.reference_frame_number reference_audio_frame_number = facefusion.globals.reference_frame_number
if facefusion.globals.trim_frame_start: if facefusion.globals.trim_frame_start:
reference_audio_frame_number -= facefusion.globals.trim_frame_start reference_audio_frame_number -= facefusion.globals.trim_frame_start
source_audio_frame = get_audio_frame(source_audio_path, facefusion.globals.output_video_fps, reference_audio_frame_number) temp_audio_frame = get_audio_frame(source_audio_path, facefusion.globals.output_video_fps, reference_audio_frame_number)
if not numpy.any(source_audio_frame): if numpy.any(temp_audio_frame):
source_audio_frame = create_empty_audio_frame() source_audio_frame = temp_audio_frame
else:
source_audio_frame = None
if is_image(facefusion.globals.target_path): if is_image(facefusion.globals.target_path):
target_vision_frame = read_static_image(facefusion.globals.target_path) target_vision_frame = read_static_image(facefusion.globals.target_path)
preview_vision_frame = process_preview_frame(reference_faces, source_face, source_audio_frame, target_vision_frame) preview_vision_frame = process_preview_frame(reference_faces, source_face, source_audio_frame, target_vision_frame)

View File

@ -5,10 +5,14 @@ import sys
import gradio import gradio
import facefusion.globals import facefusion.globals
from facefusion.uis import overrides
from facefusion import metadata, logger, wording from facefusion import metadata, logger, wording
from facefusion.uis.typing import Component, ComponentName from facefusion.uis.typing import Component, ComponentName
from facefusion.filesystem import resolve_relative_path from facefusion.filesystem import resolve_relative_path
gradio.processing_utils.encode_array_to_base64 = overrides.encode_array_to_base64
gradio.processing_utils.encode_pil_to_base64 = overrides.encode_pil_to_base64
UI_COMPONENTS: Dict[ComponentName, Component] = {} UI_COMPONENTS: Dict[ComponentName, Component] = {}
UI_LAYOUT_MODULES : List[ModuleType] = [] UI_LAYOUT_MODULES : List[ModuleType] = []
UI_LAYOUT_METHODS =\ UI_LAYOUT_METHODS =\

View File

@ -1,3 +1,4 @@
import multiprocessing
import gradio import gradio
import facefusion.globals import facefusion.globals
@ -61,4 +62,5 @@ def listen() -> None:
def run(ui : gradio.Blocks) -> None: def run(ui : gradio.Blocks) -> None:
ui.queue(concurrency_count = 2).launch(show_api = False, quiet = True) concurrency_count = min(2, multiprocessing.cpu_count())
ui.queue(concurrency_count = concurrency_count).launch(show_api = False, quiet = True)

View File

@ -1,3 +1,4 @@
import multiprocessing
import gradio import gradio
from facefusion.uis.components import about, frame_processors, frame_processors_options, execution, execution_thread_count, execution_queue_count, memory, temp_frame, output_options, common_options, source, target, output, preview, trim_frame, face_analyser, face_selector, face_masker from facefusion.uis.components import about, frame_processors, frame_processors_options, execution, execution_thread_count, execution_queue_count, memory, temp_frame, output_options, common_options, source, target, output, preview, trim_frame, face_analyser, face_selector, face_masker
@ -75,4 +76,5 @@ def listen() -> None:
def run(ui : gradio.Blocks) -> None: def run(ui : gradio.Blocks) -> None:
ui.queue(concurrency_count = 4).launch(show_api = False, quiet = True) concurrency_count = min(8, multiprocessing.cpu_count())
ui.queue(concurrency_count = concurrency_count).launch(show_api = False, quiet = True)

View File

@ -1,3 +1,4 @@
import multiprocessing
import gradio import gradio
from facefusion.uis.components import about, frame_processors, frame_processors_options, execution, execution_thread_count, webcam_options, source, webcam from facefusion.uis.components import about, frame_processors, frame_processors_options, execution, execution_thread_count, webcam_options, source, webcam
@ -44,4 +45,5 @@ def listen() -> None:
def run(ui : gradio.Blocks) -> None: def run(ui : gradio.Blocks) -> None:
ui.queue(concurrency_count = 2).launch(show_api = False, quiet = True) concurrency_count = min(2, multiprocessing.cpu_count())
ui.queue(concurrency_count = concurrency_count).launch(show_api = False, quiet = True)

View File

@ -0,0 +1,13 @@
from typing import Any
import cv2
import numpy
import base64
def encode_array_to_base64(array : numpy.ndarray[Any, Any]) -> str:
buffer = cv2.imencode('.jpg', array[:, :, ::-1])[1]
return 'data:image/jpg;base64,' + base64.b64encode(buffer.tobytes()).decode('utf-8')
def encode_pil_to_base64(image : Any) -> str:
return encode_array_to_base64(numpy.asarray(image)[:, :, ::-1])

View File

@ -3,7 +3,7 @@ import pytest
import facefusion.globals import facefusion.globals
from facefusion.download import conditional_download from facefusion.download import conditional_download
from facefusion.face_analyser import clear_face_analyser, get_one_face from facefusion.face_analyser import pre_check, clear_face_analyser, get_one_face
from facefusion.typing import Face from facefusion.typing import Face
from facefusion.vision import read_static_image from facefusion.vision import read_static_image
@ -31,6 +31,7 @@ def test_get_one_face_with_retinaface() -> None:
facefusion.globals.face_detector_model = 'retinaface' facefusion.globals.face_detector_model = 'retinaface'
facefusion.globals.face_detector_size = '320x320' facefusion.globals.face_detector_size = '320x320'
pre_check()
source_paths =\ source_paths =\
[ [
'.assets/examples/source.jpg', '.assets/examples/source.jpg',
@ -49,6 +50,7 @@ def test_get_one_face_with_scrfd() -> None:
facefusion.globals.face_detector_model = 'scrfd' facefusion.globals.face_detector_model = 'scrfd'
facefusion.globals.face_detector_size = '640x640' facefusion.globals.face_detector_size = '640x640'
pre_check()
source_paths =\ source_paths =\
[ [
'.assets/examples/source.jpg', '.assets/examples/source.jpg',
@ -67,6 +69,7 @@ def test_get_one_face_with_yoloface() -> None:
facefusion.globals.face_detector_model = 'yoloface' facefusion.globals.face_detector_model = 'yoloface'
facefusion.globals.face_detector_size = '640x640' facefusion.globals.face_detector_size = '640x640'
pre_check()
source_paths =\ source_paths =\
[ [
'.assets/examples/source.jpg', '.assets/examples/source.jpg',
@ -85,6 +88,7 @@ def test_get_one_face_with_yunet() -> None:
facefusion.globals.face_detector_model = 'yunet' facefusion.globals.face_detector_model = 'yunet'
facefusion.globals.face_detector_size = '640x640' facefusion.globals.face_detector_size = '640x640'
pre_check()
source_paths =\ source_paths =\
[ [
'.assets/examples/source.jpg', '.assets/examples/source.jpg',