* Clear VRAM of face analyser on post process

* Mark as NEXT

* Reduce tensorflow memory to 512 MB

* Cosmetics on installer

* Add is_download_done to pre_process() hook to prevent errors

* Use latest onnxruntime

* Testing for download methods, Make get_download_size more robust

* Testing for download methods

* Introduce --skip-download argument

* Catch exception causes by a firewall

* Looks stable to me
This commit is contained in:
Henry Ruhs 2023-09-22 10:28:38 +02:00 committed by GitHub
parent 66ea4928f8
commit 95bac6668c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 110 additions and 47 deletions

BIN
.github/preview.png vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

@ -56,6 +56,7 @@ python run.py [options]
--execution-providers {cpu} [{cpu} ...] choose from the available execution providers (choices: cpu, ...) --execution-providers {cpu} [{cpu} ...] choose from the available execution providers (choices: cpu, ...)
--execution-thread-count EXECUTION_THREAD_COUNT specify the number of execution threads --execution-thread-count EXECUTION_THREAD_COUNT specify the number of execution threads
--execution-queue-count EXECUTION_QUEUE_COUNT specify the number of execution queries --execution-queue-count EXECUTION_QUEUE_COUNT specify the number of execution queries
--skip-download omit automate downloads and lookups
--headless run the program in headless mode --headless run the program in headless mode
-v, --version show program's version number and exit -v, --version show program's version number and exit
``` ```

View File

@ -55,6 +55,7 @@ def parse_args() -> None:
program.add_argument('--execution-providers', help = wording.get('execution_providers_help').format(choices = 'cpu'), dest = 'execution_providers', default = ['cpu'], choices = suggest_execution_providers_choices(), nargs = '+') program.add_argument('--execution-providers', help = wording.get('execution_providers_help').format(choices = 'cpu'), dest = 'execution_providers', default = ['cpu'], choices = suggest_execution_providers_choices(), nargs = '+')
program.add_argument('--execution-thread-count', help = wording.get('execution_thread_count_help'), dest = 'execution_thread_count', type = int, default = suggest_execution_thread_count_default()) program.add_argument('--execution-thread-count', help = wording.get('execution_thread_count_help'), dest = 'execution_thread_count', type = int, default = suggest_execution_thread_count_default())
program.add_argument('--execution-queue-count', help = wording.get('execution_queue_count_help'), dest = 'execution_queue_count', type = int, default = 1) program.add_argument('--execution-queue-count', help = wording.get('execution_queue_count_help'), dest = 'execution_queue_count', type = int, default = 1)
program.add_argument('--skip-download', help = wording.get('skip_download_help'), dest = 'skip_download', action = 'store_true')
program.add_argument('--headless', help = wording.get('headless_help'), dest = 'headless', action = 'store_true') program.add_argument('--headless', help = wording.get('headless_help'), dest = 'headless', action = 'store_true')
program.add_argument('-v', '--version', version = metadata.get('name') + ' ' + metadata.get('version'), action = 'version') program.add_argument('-v', '--version', version = metadata.get('name') + ' ' + metadata.get('version'), action = 'version')
@ -86,6 +87,7 @@ def parse_args() -> None:
facefusion.globals.execution_providers = decode_execution_providers(args.execution_providers) facefusion.globals.execution_providers = decode_execution_providers(args.execution_providers)
facefusion.globals.execution_thread_count = args.execution_thread_count facefusion.globals.execution_thread_count = args.execution_thread_count
facefusion.globals.execution_queue_count = args.execution_queue_count facefusion.globals.execution_queue_count = args.execution_queue_count
facefusion.globals.skip_download = args.skip_download
facefusion.globals.headless = args.headless facefusion.globals.headless = args.headless
@ -104,7 +106,7 @@ def limit_resources() -> None:
gpus = tensorflow.config.experimental.list_physical_devices('GPU') gpus = tensorflow.config.experimental.list_physical_devices('GPU')
for gpu in gpus: for gpu in gpus:
tensorflow.config.experimental.set_virtual_device_configuration(gpu, [ tensorflow.config.experimental.set_virtual_device_configuration(gpu, [
tensorflow.config.experimental.VirtualDeviceConfiguration(memory_limit = 1024) tensorflow.config.experimental.VirtualDeviceConfiguration(memory_limit = 512)
]) ])
# limit memory usage # limit memory usage
if facefusion.globals.max_memory: if facefusion.globals.max_memory:

View File

@ -5,7 +5,6 @@ from facefusion.typing import FaceRecognition, FaceAnalyserDirection, FaceAnalys
source_path : Optional[str] = None source_path : Optional[str] = None
target_path : Optional[str] = None target_path : Optional[str] = None
output_path : Optional[str] = None output_path : Optional[str] = None
headless : Optional[bool] = None
frame_processors : List[str] = [] frame_processors : List[str] = []
ui_layouts : List[str] = [] ui_layouts : List[str] = []
keep_fps : Optional[bool] = None keep_fps : Optional[bool] = None
@ -29,3 +28,5 @@ max_memory : Optional[int] = None
execution_providers : List[str] = [] execution_providers : List[str] = []
execution_thread_count : Optional[int] = None execution_thread_count : Optional[int] = None
execution_queue_count : Optional[int] = None execution_queue_count : Optional[int] = None
skip_download : Optional[bool] = None
headless : Optional[bool] = None

View File

@ -13,11 +13,11 @@ from facefusion import metadata, wording
ONNXRUNTIMES : Dict[str, Tuple[str, str]] =\ ONNXRUNTIMES : Dict[str, Tuple[str, str]] =\
{ {
'cpu': ('onnxruntime', '1.15.1'), 'cpu': ('onnxruntime', '1.16.0 '),
'cuda': ('onnxruntime-gpu', '1.15.1'), 'cuda': ('onnxruntime-gpu', '1.16.0'),
'coreml-legacy': ('onnxruntime-coreml', '1.13.1'), 'coreml-legacy': ('onnxruntime-coreml', '1.13.1'),
'coreml-silicon': ('onnxruntime-silicon', '1.14.2'), 'coreml-silicon': ('onnxruntime-silicon', '1.14.2'),
'directml': ('onnxruntime-directml', '1.15.1'), 'directml': ('onnxruntime-directml', '1.16.0'),
'openvino': ('onnxruntime-openvino', '1.15.0') 'openvino': ('onnxruntime-openvino', '1.15.0')
} }
@ -60,6 +60,6 @@ def run() -> None:
wheel_name = '-'.join([ 'onnxruntime_silicon', onnxruntime_version, python_id, python_id, 'macosx_12_0_arm64.whl' ]) wheel_name = '-'.join([ 'onnxruntime_silicon', onnxruntime_version, python_id, python_id, 'macosx_12_0_arm64.whl' ])
wheel_path = os.path.join(tempfile.gettempdir(), wheel_name) wheel_path = os.path.join(tempfile.gettempdir(), wheel_name)
wheel_url = 'https://github.com/cansik/onnxruntime-silicon/releases/download/v' + onnxruntime_version + '/' + wheel_name wheel_url = 'https://github.com/cansik/onnxruntime-silicon/releases/download/v' + onnxruntime_version + '/' + wheel_name
subprocess.call([ 'curl', wheel_url, '-o', wheel_path, '-L' ]) subprocess.call([ 'curl', '--silent', '--location', '--continue-at', '-', '--output', wheel_path, wheel_url ])
subprocess.call([ 'pip', 'install', wheel_path ]) subprocess.call([ 'pip', 'install', wheel_path ])
os.remove(wheel_path) os.remove(wheel_path)

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': '1.2.0', 'version': '1.2.1',
'license': 'MIT', 'license': 'MIT',
'author': 'Henry Ruhs', 'author': 'Henry Ruhs',
'url': 'https://facefusion.io' 'url': 'https://facefusion.io'

View File

@ -5,15 +5,17 @@ from gfpgan.utils import GFPGANer
import facefusion.globals import facefusion.globals
from facefusion import wording, utilities from facefusion import wording, utilities
from facefusion.core import update_status from facefusion.core import update_status
from facefusion.face_analyser import get_many_faces from facefusion.face_analyser import get_many_faces, clear_face_analyser
from facefusion.typing import Frame, Face, ProcessMode from facefusion.typing import Frame, Face, ProcessMode
from facefusion.utilities import conditional_download, resolve_relative_path, is_image, is_video from facefusion.utilities import conditional_download, resolve_relative_path, is_image, is_video, is_file, is_download_done
from facefusion.vision import read_image, read_static_image, write_image from facefusion.vision import read_image, read_static_image, write_image
FRAME_PROCESSOR = None FRAME_PROCESSOR = None
THREAD_SEMAPHORE : threading.Semaphore = threading.Semaphore() THREAD_SEMAPHORE : threading.Semaphore = threading.Semaphore()
THREAD_LOCK : threading.Lock = threading.Lock() THREAD_LOCK : threading.Lock = threading.Lock()
NAME = 'FACEFUSION.FRAME_PROCESSOR.FACE_ENHANCER' NAME = 'FACEFUSION.FRAME_PROCESSOR.FACE_ENHANCER'
MODEL_URL = 'https://github.com/facefusion/facefusion-assets/releases/download/models/GFPGANv1.4.pth'
MODEL_PATH = resolve_relative_path('../.assets/models/GFPGANv1.4.pth')
def get_frame_processor() -> Any: def get_frame_processor() -> Any:
@ -21,9 +23,8 @@ def get_frame_processor() -> Any:
with THREAD_LOCK: with THREAD_LOCK:
if FRAME_PROCESSOR is None: if FRAME_PROCESSOR is None:
model_path = resolve_relative_path('../.assets/models/GFPGANv1.4.pth')
FRAME_PROCESSOR = GFPGANer( FRAME_PROCESSOR = GFPGANer(
model_path = model_path, model_path = MODEL_PATH,
upscale = 1, upscale = 1,
device = utilities.get_device(facefusion.globals.execution_providers) device = utilities.get_device(facefusion.globals.execution_providers)
) )
@ -37,12 +38,19 @@ def clear_frame_processor() -> None:
def pre_check() -> bool: def pre_check() -> bool:
download_directory_path = resolve_relative_path('../.assets/models') if not facefusion.globals.skip_download:
conditional_download(download_directory_path, [ 'https://github.com/facefusion/facefusion-assets/releases/download/models/GFPGANv1.4.pth' ]) download_directory_path = resolve_relative_path('../.assets/models')
conditional_download(download_directory_path, [ MODEL_URL ])
return True return True
def pre_process(mode : ProcessMode) -> bool: def pre_process(mode : ProcessMode) -> bool:
if not is_download_done(MODEL_URL, MODEL_PATH):
update_status(wording.get('model_download_not_done') + wording.get('exclamation_mark'), NAME)
return False
elif not is_file(MODEL_PATH):
update_status(wording.get('model_file_not_present') + wording.get('exclamation_mark'), NAME)
return False
if mode in [ 'output', 'preview' ] and not is_image(facefusion.globals.target_path) and not is_video(facefusion.globals.target_path): if mode in [ 'output', 'preview' ] and not is_image(facefusion.globals.target_path) and not is_video(facefusion.globals.target_path):
update_status(wording.get('select_image_or_video_target') + wording.get('exclamation_mark'), NAME) update_status(wording.get('select_image_or_video_target') + wording.get('exclamation_mark'), NAME)
return False return False
@ -54,6 +62,7 @@ def pre_process(mode : ProcessMode) -> bool:
def post_process() -> None: def post_process() -> None:
clear_frame_processor() clear_frame_processor()
clear_face_analyser()
read_static_image.cache_clear() read_static_image.cache_clear()

View File

@ -6,15 +6,17 @@ import facefusion.globals
import facefusion.processors.frame.core as frame_processors import facefusion.processors.frame.core as frame_processors
from facefusion import wording from facefusion import wording
from facefusion.core import update_status from facefusion.core import update_status
from facefusion.face_analyser import get_one_face, get_many_faces, find_similar_faces from facefusion.face_analyser import get_one_face, get_many_faces, find_similar_faces, clear_face_analyser
from facefusion.face_reference import get_face_reference, set_face_reference from facefusion.face_reference import get_face_reference, set_face_reference
from facefusion.typing import Face, Frame, ProcessMode from facefusion.typing import Face, Frame, ProcessMode
from facefusion.utilities import conditional_download, resolve_relative_path, is_image, is_video from facefusion.utilities import conditional_download, resolve_relative_path, is_image, is_video, is_file, is_download_done
from facefusion.vision import read_image, read_static_image, write_image from facefusion.vision import read_image, read_static_image, write_image
FRAME_PROCESSOR = None FRAME_PROCESSOR = None
THREAD_LOCK : threading.Lock = threading.Lock() THREAD_LOCK : threading.Lock = threading.Lock()
NAME = 'FACEFUSION.FRAME_PROCESSOR.FACE_SWAPPER' NAME = 'FACEFUSION.FRAME_PROCESSOR.FACE_SWAPPER'
MODEL_URL = 'https://github.com/facefusion/facefusion-assets/releases/download/models/inswapper_128.onnx'
MODEL_PATH = resolve_relative_path('../.assets/models/inswapper_128.onnx')
def get_frame_processor() -> Any: def get_frame_processor() -> Any:
@ -22,8 +24,7 @@ def get_frame_processor() -> Any:
with THREAD_LOCK: with THREAD_LOCK:
if FRAME_PROCESSOR is None: if FRAME_PROCESSOR is None:
model_path = resolve_relative_path('../.assets/models/inswapper_128.onnx') FRAME_PROCESSOR = insightface.model_zoo.get_model(MODEL_PATH, providers = facefusion.globals.execution_providers)
FRAME_PROCESSOR = insightface.model_zoo.get_model(model_path, providers = facefusion.globals.execution_providers)
return FRAME_PROCESSOR return FRAME_PROCESSOR
@ -34,12 +35,19 @@ def clear_frame_processor() -> None:
def pre_check() -> bool: def pre_check() -> bool:
download_directory_path = resolve_relative_path('../.assets/models') if not facefusion.globals.skip_download:
conditional_download(download_directory_path, [ 'https://github.com/facefusion/facefusion-assets/releases/download/models/inswapper_128.onnx' ]) download_directory_path = resolve_relative_path('../.assets/models')
conditional_download(download_directory_path, [ MODEL_URL ])
return True return True
def pre_process(mode : ProcessMode) -> bool: def pre_process(mode : ProcessMode) -> bool:
if not facefusion.globals.skip_download and not is_download_done(MODEL_URL, MODEL_PATH):
update_status(wording.get('model_download_not_done') + wording.get('exclamation_mark'), NAME)
return False
elif not is_file(MODEL_PATH):
update_status(wording.get('model_file_not_present') + wording.get('exclamation_mark'), NAME)
return False
if not is_image(facefusion.globals.source_path): if not is_image(facefusion.globals.source_path):
update_status(wording.get('select_image_source') + wording.get('exclamation_mark'), NAME) update_status(wording.get('select_image_source') + wording.get('exclamation_mark'), NAME)
return False return False
@ -48,6 +56,7 @@ def pre_process(mode : ProcessMode) -> bool:
return False return False
if mode in [ 'output', 'preview' ] and not is_image(facefusion.globals.target_path) and not is_video(facefusion.globals.target_path): if mode in [ 'output', 'preview' ] and not is_image(facefusion.globals.target_path) and not is_video(facefusion.globals.target_path):
update_status(wording.get('select_image_or_video_target') + wording.get('exclamation_mark'), NAME) update_status(wording.get('select_image_or_video_target') + wording.get('exclamation_mark'), NAME)
return False
if mode == 'output' and not facefusion.globals.output_path: if mode == 'output' and not facefusion.globals.output_path:
update_status(wording.get('select_file_or_directory_output') + wording.get('exclamation_mark'), NAME) update_status(wording.get('select_file_or_directory_output') + wording.get('exclamation_mark'), NAME)
return False return False
@ -56,6 +65,7 @@ def pre_process(mode : ProcessMode) -> bool:
def post_process() -> None: def post_process() -> None:
clear_frame_processor() clear_frame_processor()
clear_face_analyser()
read_static_image.cache_clear() read_static_image.cache_clear()

View File

@ -3,18 +3,21 @@ import threading
from basicsr.archs.rrdbnet_arch import RRDBNet from basicsr.archs.rrdbnet_arch import RRDBNet
from realesrgan import RealESRGANer from realesrgan import RealESRGANer
import facefusion import facefusion.globals
import facefusion.processors.frame.core as frame_processors import facefusion.processors.frame.core as frame_processors
from facefusion import wording, utilities from facefusion import wording, utilities
from facefusion.core import update_status from facefusion.core import update_status
from facefusion.face_analyser import clear_face_analyser
from facefusion.typing import Frame, Face, ProcessMode from facefusion.typing import Frame, Face, ProcessMode
from facefusion.utilities import conditional_download, resolve_relative_path from facefusion.utilities import conditional_download, resolve_relative_path, is_file, is_download_done
from facefusion.vision import read_image, read_static_image, write_image from facefusion.vision import read_image, read_static_image, write_image
FRAME_PROCESSOR = None FRAME_PROCESSOR = None
THREAD_SEMAPHORE : threading.Semaphore = threading.Semaphore() THREAD_SEMAPHORE : threading.Semaphore = threading.Semaphore()
THREAD_LOCK : threading.Lock = threading.Lock() THREAD_LOCK : threading.Lock = threading.Lock()
NAME = 'FACEFUSION.FRAME_PROCESSOR.FRAME_ENHANCER' NAME = 'FACEFUSION.FRAME_PROCESSOR.FRAME_ENHANCER'
MODEL_URL = 'https://github.com/facefusion/facefusion-assets/releases/download/models/RealESRGAN_x4plus.pth'
MODEL_PATH = resolve_relative_path('../.assets/models/RealESRGAN_x4plus.pth')
def get_frame_processor() -> Any: def get_frame_processor() -> Any:
@ -22,9 +25,8 @@ def get_frame_processor() -> Any:
with THREAD_LOCK: with THREAD_LOCK:
if FRAME_PROCESSOR is None: if FRAME_PROCESSOR is None:
model_path = resolve_relative_path('../.assets/models/RealESRGAN_x4plus.pth')
FRAME_PROCESSOR = RealESRGANer( FRAME_PROCESSOR = RealESRGANer(
model_path = model_path, model_path = MODEL_PATH,
model = RRDBNet( model = RRDBNet(
num_in_ch = 3, num_in_ch = 3,
num_out_ch = 3, num_out_ch = 3,
@ -49,12 +51,19 @@ def clear_frame_processor() -> None:
def pre_check() -> bool: def pre_check() -> bool:
download_directory_path = resolve_relative_path('../.assets/models') if not facefusion.globals.skip_download:
conditional_download(download_directory_path, [ 'https://github.com/facefusion/facefusion-assets/releases/download/models/RealESRGAN_x4plus.pth' ]) download_directory_path = resolve_relative_path('../.assets/models')
conditional_download(download_directory_path, [ MODEL_URL ])
return True return True
def pre_process(mode : ProcessMode) -> bool: def pre_process(mode : ProcessMode) -> bool:
if not facefusion.globals.skip_download and not facefusion.globals.skip_download and not is_download_done(MODEL_URL, MODEL_PATH):
update_status(wording.get('model_download_not_done') + wording.get('exclamation_mark'), NAME)
return False
elif not is_file(MODEL_PATH):
update_status(wording.get('model_file_not_present') + wording.get('exclamation_mark'), NAME)
return False
if mode == 'output' and not facefusion.globals.output_path: if mode == 'output' and not facefusion.globals.output_path:
update_status(wording.get('select_file_or_directory_output') + wording.get('exclamation_mark'), NAME) update_status(wording.get('select_file_or_directory_output') + wording.get('exclamation_mark'), NAME)
return False return False
@ -63,6 +72,7 @@ def pre_process(mode : ProcessMode) -> bool:
def post_process() -> None: def post_process() -> None:
clear_frame_processor() clear_frame_processor()
clear_face_analyser()
read_static_image.cache_clear() read_static_image.cache_clear()

View File

@ -2,6 +2,6 @@ from typing import List
from facefusion.uis.typing import WebcamMode from facefusion.uis.typing import WebcamMode
settings : List[str] = [ 'keep-fps', 'keep-temp', 'skip-audio' ] settings : List[str] = [ 'keep-fps', 'keep-temp', 'skip-audio', 'skip-download' ]
webcam_mode : List[WebcamMode] = [ 'inline', 'stream_udp', 'stream_v4l2' ] webcam_mode : List[WebcamMode] = [ 'inline', 'stream_udp', 'stream_v4l2' ]
webcam_resolution : List[str] = [ '320x240', '640x480', '1280x720', '1920x1080', '2560x1440', '3840x2160' ] webcam_resolution : List[str] = [ '320x240', '640x480', '1280x720', '1920x1080', '2560x1440', '3840x2160' ]

View File

@ -29,9 +29,10 @@ def listen() -> None:
def update_frame_processors(frame_processors : List[str]) -> Update: def update_frame_processors(frame_processors : List[str]) -> Update:
clear_frame_processors_modules() clear_frame_processors_modules()
facefusion.globals.frame_processors = frame_processors facefusion.globals.frame_processors = frame_processors
for frame_processor in facefusion.globals.frame_processors: for frame_processor in frame_processors:
frame_processor_module = load_frame_processor_module(frame_processor) frame_processor_module = load_frame_processor_module(frame_processor)
frame_processor_module.pre_check() if not frame_processor_module.pre_check():
return gradio.update()
return gradio.update(value = frame_processors, choices = sort_frame_processors(frame_processors)) return gradio.update(value = frame_processors, choices = sort_frame_processors(frame_processors))

View File

@ -19,6 +19,8 @@ def render() -> None:
value.append('keep-temp') value.append('keep-temp')
if facefusion.globals.skip_audio: if facefusion.globals.skip_audio:
value.append('skip-audio') value.append('skip-audio')
if facefusion.globals.skip_download:
value.append('skip-download')
SETTINGS_CHECKBOX_GROUP = gradio.Checkboxgroup( SETTINGS_CHECKBOX_GROUP = gradio.Checkboxgroup(
label = wording.get('settings_checkbox_group_label'), label = wording.get('settings_checkbox_group_label'),
choices = choices.settings, choices = choices.settings,
@ -34,4 +36,5 @@ def update(settings : List[str]) -> Update:
facefusion.globals.keep_fps = 'keep-fps' in settings facefusion.globals.keep_fps = 'keep-fps' in settings
facefusion.globals.keep_temp = 'keep-temp' in settings facefusion.globals.keep_temp = 'keep-temp' in settings
facefusion.globals.skip_audio = 'skip-audio' in settings facefusion.globals.skip_audio = 'skip-audio' in settings
facefusion.globals.skip_download = 'skip-download' in settings
return gradio.update(value = settings) return gradio.update(value = settings)

View File

@ -1,22 +1,25 @@
import gradio import gradio
import facefusion.globals
from facefusion.uis.components import about, processors, execution, execution_thread_count, execution_queue_count, limit_resources, benchmark_settings, benchmark from facefusion.uis.components import about, processors, execution, execution_thread_count, execution_queue_count, limit_resources, benchmark_settings, benchmark
from facefusion.utilities import conditional_download from facefusion.utilities import conditional_download
def pre_check() -> bool: def pre_check() -> bool:
conditional_download('.assets/examples', if not facefusion.globals.skip_download:
[ conditional_download('.assets/examples',
'https://github.com/facefusion/facefusion-assets/releases/download/examples/source.jpg', [
'https://github.com/facefusion/facefusion-assets/releases/download/examples/target-240p.mp4', 'https://github.com/facefusion/facefusion-assets/releases/download/examples/source.jpg',
'https://github.com/facefusion/facefusion-assets/releases/download/examples/target-360p.mp4', 'https://github.com/facefusion/facefusion-assets/releases/download/examples/target-240p.mp4',
'https://github.com/facefusion/facefusion-assets/releases/download/examples/target-540p.mp4', 'https://github.com/facefusion/facefusion-assets/releases/download/examples/target-360p.mp4',
'https://github.com/facefusion/facefusion-assets/releases/download/examples/target-720p.mp4', 'https://github.com/facefusion/facefusion-assets/releases/download/examples/target-540p.mp4',
'https://github.com/facefusion/facefusion-assets/releases/download/examples/target-1080p.mp4', 'https://github.com/facefusion/facefusion-assets/releases/download/examples/target-720p.mp4',
'https://github.com/facefusion/facefusion-assets/releases/download/examples/target-1440p.mp4', 'https://github.com/facefusion/facefusion-assets/releases/download/examples/target-1080p.mp4',
'https://github.com/facefusion/facefusion-assets/releases/download/examples/target-2160p.mp4' 'https://github.com/facefusion/facefusion-assets/releases/download/examples/target-1440p.mp4',
]) 'https://github.com/facefusion/facefusion-assets/releases/download/examples/target-2160p.mp4'
return True ])
return True
return False
def pre_render() -> bool: def pre_render() -> bool:

View File

@ -1,4 +1,5 @@
from typing import List, Optional from typing import List, Optional
from functools import lru_cache
from pathlib import Path from pathlib import Path
from tqdm import tqdm from tqdm import tqdm
import glob import glob
@ -194,12 +195,19 @@ def conditional_download(download_directory_path : str, urls : List[str]) -> Non
progress.update(current - progress.n) progress.update(current - progress.n)
def get_download_size(url : str) -> int: @lru_cache(maxsize = None)
response = urllib.request.urlopen(url) # type: ignore[attr-defined] def get_download_size(url : str) -> Optional[int]:
content_length = response.getheader('Content-Length') try:
if content_length: response = urllib.request.urlopen(url) # type: ignore[attr-defined]
return int(content_length) return int(response.getheader('Content-Length'))
return 0 except (OSError, ValueError):
return None
def is_download_done(url : str, file_path : str) -> bool:
if is_file(file_path):
return get_download_size(url) == os.path.getsize(file_path)
return False
def resolve_relative_path(path : str) -> str: def resolve_relative_path(path : str) -> str:

View File

@ -29,6 +29,7 @@ WORDING =\
'execution_providers_help': 'choose from the available execution providers (choices: {choices}, ...)', 'execution_providers_help': 'choose from the available execution providers (choices: {choices}, ...)',
'execution_thread_count_help': 'specify the number of execution threads', 'execution_thread_count_help': 'specify the number of execution threads',
'execution_queue_count_help': 'specify the number of execution queries', 'execution_queue_count_help': 'specify the number of execution queries',
'skip_download_help': 'omit automate downloads and lookups',
'headless_help': 'run the program in headless mode', 'headless_help': 'run the program in headless mode',
'creating_temp': 'Creating temporary resources', 'creating_temp': 'Creating temporary resources',
'extracting_frames_fps': 'Extracting frames with {fps} FPS', 'extracting_frames_fps': 'Extracting frames with {fps} FPS',
@ -47,6 +48,8 @@ WORDING =\
'processing_image_failed': 'Processing to image failed', 'processing_image_failed': 'Processing to image failed',
'processing_video_succeed': 'Processing to video succeed', 'processing_video_succeed': 'Processing to video succeed',
'processing_video_failed': 'Processing to video failed', 'processing_video_failed': 'Processing to video failed',
'model_download_not_done': 'Download of the model is not done',
'model_file_not_present': 'File of the model is not present',
'select_image_source': 'Select an image for source path', 'select_image_source': 'Select an image for source path',
'select_image_or_video_target': 'Select an image or video for target path', 'select_image_or_video_target': 'Select an image or video for target path',
'select_file_or_directory_output': 'Select an file or directory for output path', 'select_file_or_directory_output': 'Select an file or directory for output path',

View File

@ -4,7 +4,7 @@ import subprocess
import pytest import pytest
import facefusion.globals import facefusion.globals
from facefusion.utilities import conditional_download, extract_frames, create_temp, get_temp_directory_path, clear_temp, normalize_output_path, is_file, is_directory, is_image, is_video, encode_execution_providers, decode_execution_providers from facefusion.utilities import conditional_download, extract_frames, create_temp, get_temp_directory_path, clear_temp, normalize_output_path, is_file, is_directory, is_image, is_video, get_download_size, is_download_done, encode_execution_providers, decode_execution_providers
@pytest.fixture(scope = 'module', autouse = True) @pytest.fixture(scope = 'module', autouse = True)
@ -140,6 +140,18 @@ def test_is_video() -> None:
assert is_video('invalid') is False assert is_video('invalid') is False
def test_get_download_size() -> None:
assert get_download_size('https://github.com/facefusion/facefusion-assets/releases/download/examples/target-240p.mp4') == 191675
assert get_download_size('https://github.com/facefusion/facefusion-assets/releases/download/examples/target-360p.mp4') == 370732
assert get_download_size('invalid') is None
def test_is_download_done() -> None:
assert is_download_done('https://github.com/facefusion/facefusion-assets/releases/download/examples/target-240p.mp4', '.assets/examples/target-240p.mp4') is True
assert is_download_done('https://github.com/facefusion/facefusion-assets/releases/download/examples/target-240p.mp4','invalid') is False
assert is_download_done('invalid', 'invalid') is False
def test_encode_execution_providers() -> None: def test_encode_execution_providers() -> None:
assert encode_execution_providers([ 'CPUExecutionProvider' ]) == [ 'cpu' ] assert encode_execution_providers([ 'CPUExecutionProvider' ]) == [ 'cpu' ]