* renaming and restructuring (#282)

* Renaming and restructuring

* Renaming and restructuring

* Renaming and restructuring

* Fix gender detection

* Implement distance to face debugger

* Implement distance to face debugger part2

* Implement distance to face debugger part3

* Mark as next

* Fix reference when face_debugger comes first

* Use official onnxruntime nightly

* CUDA on steroids

* CUDA on steroids

* Add some testing

* Set inswapper_128_fp16 as default

* Feat/block until post check (#292)

* Block until download is done

* Introduce post_check()

* Fix webcam

* Update dependencies

* Add --force-reinstall to installer

* Introduce config ini (#298)

* Introduce config ini

* Fix output video encoder

* Revert help listings back to commas, Move SSL hack to download.py

* Introduce output-video-preset which defaults to veryfast

* Mapping for nvenc encoders

* Rework on events and non-blocking UI

* Add fast bmp to temp_frame_formats

* Add fast bmp to temp_frame_formats

* Show total processing time on success

* Show total processing time on success

* Show total processing time on success

* Move are_images, is_image and is_video back to filesystem

* Fix some spacings

* Pissing everyone of by renaming stuff

* Fix seconds output

* feat/video output fps (#312)

* added output fps slider, removed 'keep fps' option (#311)

* added output fps slider, removed 'keep fps' option

* now uses passed fps instead of global fps for ffmpeg

* fps values are now floats instead of ints

* fix previous commit

* removed default value from fps slider

this is so we can implement a dynamic default value later

* Fix seconds output

* Some cleanup

---------

Co-authored-by: Ran Shaashua <47498956+ranshaa05@users.noreply.github.com>

* Allow 0.01 steps for fps

* Make fps unregulated

* Make fps unregulated

* Remove distance from face debugger again (does not work)

* Fix gender age

* Fix gender age

* Hotfix benchmark suite

* Warp face normalize (#313)

* use normalized kp templates

* Update face_helper.py

* My 50 cents to warp_face()

---------

Co-authored-by: Harisreedhar <46858047+harisreedhar@users.noreply.github.com>

* face-swapper-weight (#315)

* Move prepare_crop_frame and normalize_crop_frame out of apply_swap

* Fix UI bug with different range

* feat/output video resolution (#316)

* Introduce detect_video_resolution, Rename detect_fps to detect_video_fps

* Add calc_video_resolution_range

* Make output resolution work, does not auto-select yet

* Make output resolution work, does not auto-select yet

* Try to keep the origin resolution

* Split code into more fragments

* Add pack/unpack resolution

* Move video_template_sizes to choices

* Improve create_video_resolutions

* Reword benchmark suite

* Optimal speed for benchmark

* Introduce different video memory strategies, rename max_memory to max… (#317)

* Introduce different video memory strategies, rename max_memory to max_system_memory

* Update readme

* Fix limit_system_memory call

* Apply video_memory_strategy to face debugger

* Limit face swapper weight to 3.0

* Remove face swapper weight due bad render outputs

* Show/dide logic for output video preset

* fix uint8 conversion

* Fix whitespace

* Finalize layout and update preview

* Fix multi renders on face debugger

* Restore less restrictive rendering of preview and stream

* Fix block mode for model downloads

* Add testing

* Cosmetic changes

* Enforce valid fps and resolution via CLI

* Empty config

* Cosmetics on args processing

* Memory workover (#319)

* Cosmetics on args processing

* Fix for MacOS

* Rename all max_ to _limit

* More fixes

* Update preview

* Fix whitespace

---------

Co-authored-by: Ran Shaashua <47498956+ranshaa05@users.noreply.github.com>
Co-authored-by: Harisreedhar <46858047+harisreedhar@users.noreply.github.com>
This commit is contained in:
Henry Ruhs
2024-01-19 19:57:48 +01:00
committed by GitHub
parent 3e93f99eeb
commit f6e56a3d8c
61 changed files with 1097 additions and 432 deletions

View File

@@ -2,7 +2,6 @@ import subprocess
import sys
import pytest
from facefusion import wording
from facefusion.download import conditional_download
@@ -21,7 +20,7 @@ def test_image_to_image() -> None:
run = subprocess.run(commands, stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
assert run.returncode == 0
assert wording.get('processing_image_succeed') in run.stdout.decode()
assert 'image succeed' in run.stdout.decode()
def test_image_to_video() -> None:
@@ -29,4 +28,4 @@ def test_image_to_video() -> None:
run = subprocess.run(commands, stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
assert run.returncode == 0
assert wording.get('processing_video_succeed') in run.stdout.decode()
assert 'video succeed' in run.stdout.decode()

View File

@@ -1,10 +1,15 @@
from facefusion.common_helper import create_metavar, create_range
from facefusion.common_helper import create_metavar, create_int_range, create_float_range
def test_create_metavar() -> None:
assert create_metavar([ 1, 2, 3, 4, 5 ]) == '[1-5]'
def test_create_range() -> None:
assert create_range(0.0, 1.0, 0.5) == [ 0.0, 0.5, 1.0 ]
assert create_range(0.0, 0.2, 0.05) == [ 0.0, 0.05, 0.10, 0.15, 0.20 ]
def test_create_int_range() -> None:
assert create_int_range(0, 2, 1) == [ 0, 1, 2 ]
assert create_float_range(0, 1, 1) == [ 0, 1 ]
def test_create_float_range() -> None:
assert create_float_range(0.0, 1.0, 0.5) == [ 0.0, 0.5, 1.0 ]
assert create_float_range(0.0, 0.2, 0.05) == [ 0.0, 0.05, 0.10, 0.15, 0.20 ]

96
tests/test_config.py Normal file
View File

@@ -0,0 +1,96 @@
from configparser import ConfigParser
import pytest
from facefusion import config
@pytest.fixture(scope = 'module', autouse = True)
def before_all() -> None:
config.CONFIG = ConfigParser()
config.CONFIG.read_dict(
{
'str':
{
'valid': 'a',
'unset': ''
},
'int':
{
'valid': '1',
'unset': ''
},
'float':
{
'valid': '1.0',
'unset': ''
},
'bool':
{
'valid': 'True',
'unset': ''
},
'str_list':
{
'valid': 'a b c',
'unset': ''
},
'int_list':
{
'valid': '1 2 3',
'unset': ''
},
'float_list':
{
'valid': '1.0 2.0 3.0',
'unset': ''
}
})
def test_get_str_value() -> None:
assert config.get_str_value('str.valid') == 'a'
assert config.get_str_value('str.unset', 'b') == 'b'
assert config.get_str_value('str.unset') is None
assert config.get_str_value('str.invalid') is None
def test_get_int_value() -> None:
assert config.get_int_value('int.valid') == 1
assert config.get_int_value('int.unset', '1') == 1
assert config.get_int_value('int.unset') is None
assert config.get_int_value('int.invalid') is None
def test_get_float_value() -> None:
assert config.get_float_value('float.valid') == 1.0
assert config.get_float_value('float.unset', '1.0') == 1.0
assert config.get_float_value('float.unset') is None
assert config.get_float_value('float.invalid') is None
def test_get_bool_value() -> None:
assert config.get_bool_value('bool.valid') is True
assert config.get_bool_value('bool.unset', 'False') is False
assert config.get_bool_value('bool.unset') is None
assert config.get_bool_value('bool.invalid') is None
def test_get_str_list() -> None:
assert config.get_str_list('str_list.valid') == [ 'a', 'b', 'c' ]
assert config.get_str_list('str_list.unset', 'c b a') == [ 'c', 'b', 'a' ]
assert config.get_str_list('str_list.unset') is None
assert config.get_str_list('str_list.invalid') is None
def test_get_int_list() -> None:
assert config.get_int_list('int_list.valid') == [ 1, 2, 3 ]
assert config.get_int_list('int_list.unset', '3 2 1') == [ 3, 2, 1 ]
assert config.get_int_list('int_list.unset') is None
assert config.get_int_list('int_list.invalid') is None
def test_get_float_list() -> None:
assert config.get_float_list('float_list.valid') == [ 1.0, 2.0, 3.0 ]
assert config.get_float_list('float_list.unset', '3.0 2.0 1.0') == [ 3.0, 2.0, 1.0 ]
assert config.get_float_list('float_list.unset') is None
assert config.get_float_list('float_list.invalid') is None

View File

@@ -1,4 +1,4 @@
from facefusion.execution_helper import encode_execution_providers, decode_execution_providers
from facefusion.execution_helper import encode_execution_providers, decode_execution_providers, apply_execution_provider_options, map_torch_backend
def test_encode_execution_providers() -> None:
@@ -7,3 +7,20 @@ def test_encode_execution_providers() -> None:
def test_decode_execution_providers() -> None:
assert decode_execution_providers([ 'cpu' ]) == [ 'CPUExecutionProvider' ]
def test_multiple_execution_providers() -> None:
execution_provider_with_options =\
[
'CPUExecutionProvider',
('CUDAExecutionProvider',
{
'cudnn_conv_algo_search': 'DEFAULT'
})
]
assert apply_execution_provider_options([ 'CPUExecutionProvider', 'CUDAExecutionProvider' ]) == execution_provider_with_options
def test_map_device() -> None:
assert map_torch_backend([ 'CPUExecutionProvider' ]) == 'cpu'
assert map_torch_backend([ 'CPUExecutionProvider', 'CUDAExecutionProvider' ]) == 'cuda'

View File

@@ -39,7 +39,7 @@ def test_extract_frames() -> None:
temp_directory_path = get_temp_directory_path(target_path)
create_temp(target_path)
assert extract_frames(target_path, 30.0) is True
assert extract_frames(target_path, '452x240', 30.0) is True
assert len(glob.glob1(temp_directory_path, '*.jpg')) == 324
clear_temp(target_path)
@@ -57,7 +57,7 @@ def test_extract_frames_with_trim_start() -> None:
temp_directory_path = get_temp_directory_path(target_path)
create_temp(target_path)
assert extract_frames(target_path, 30.0) is True
assert extract_frames(target_path, '452x240', 30.0) is True
assert len(glob.glob1(temp_directory_path, '*.jpg')) == frame_total
clear_temp(target_path)
@@ -76,7 +76,7 @@ def test_extract_frames_with_trim_start_and_trim_end() -> None:
temp_directory_path = get_temp_directory_path(target_path)
create_temp(target_path)
assert extract_frames(target_path, 30.0) is True
assert extract_frames(target_path, '452x240', 30.0) is True
assert len(glob.glob1(temp_directory_path, '*.jpg')) == frame_total
clear_temp(target_path)
@@ -94,7 +94,7 @@ def test_extract_frames_with_trim_end() -> None:
temp_directory_path = get_temp_directory_path(target_path)
create_temp(target_path)
assert extract_frames(target_path, 30.0) is True
assert extract_frames(target_path, '426x240', 30.0) is True
assert len(glob.glob1(temp_directory_path, '*.jpg')) == frame_total
clear_temp(target_path)

View File

@@ -1,4 +1,15 @@
from facefusion.filesystem import is_file, is_directory, is_image, are_images, is_video
import pytest
from facefusion.download import conditional_download
from facefusion.filesystem import is_file, is_directory, is_image, are_images, is_video, list_directory
@pytest.fixture(scope = 'module', autouse = True)
def before_all() -> None:
conditional_download('.assets/examples',
[
'https://github.com/facefusion/facefusion-assets/releases/download/examples/source.jpg'
])
def test_is_file() -> None:
@@ -29,3 +40,9 @@ def test_is_video() -> None:
assert is_video('.assets/examples/target-240p.mp4') is True
assert is_video('.assets/examples/source.jpg') is False
assert is_video('invalid') is False
def test_list_directory() -> None:
assert list_directory('.assets/examples')
assert list_directory('.assets/examples/source.jpg') is None
assert list_directory('invalid') is None

9
tests/test_memory.py Normal file
View File

@@ -0,0 +1,9 @@
import platform
from facefusion.memory import limit_system_memory
def test_limit_system_memory() -> None:
assert limit_system_memory(4) is True
if platform.system().lower() == 'darwin' or platform.system().lower() == 'linux':
assert limit_system_memory(1024) is False

View File

@@ -1,6 +1,6 @@
import platform
from facefusion.normalizer import normalize_output_path, normalize_padding
from facefusion.normalizer import normalize_output_path, normalize_padding, normalize_fps
def test_normalize_output_path() -> None:
@@ -23,3 +23,10 @@ def test_normalize_padding() -> None:
assert normalize_padding([ 1, 2 ]) == (1, 2, 1, 2)
assert normalize_padding([ 1, 2, 3 ]) == (1, 2, 3, 2)
assert normalize_padding(None) is None
def test_normalize_fps() -> None:
assert normalize_fps(0.0) == 1.0
assert normalize_fps(25.0) == 25.0
assert normalize_fps(61.0) == 60.0
assert normalize_fps(None) is None

View File

@@ -2,7 +2,7 @@ import subprocess
import pytest
from facefusion.download import conditional_download
from facefusion.vision import get_video_frame, detect_fps, count_video_frame_total
from facefusion.vision import get_video_frame, count_video_frame_total, detect_video_fps, detect_video_resolution, pack_resolution, unpack_resolution, create_video_resolutions
@pytest.fixture(scope = 'module', autouse = True)
@@ -10,11 +10,14 @@ def before_all() -> None:
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/target-240p.mp4',
'https://github.com/facefusion/facefusion-assets/releases/download/examples/target-1080p.mp4'
])
subprocess.run([ 'ffmpeg', '-i', '.assets/examples/target-240p.mp4', '-vf', 'fps=25', '.assets/examples/target-240p-25fps.mp4' ])
subprocess.run([ 'ffmpeg', '-i', '.assets/examples/target-240p.mp4', '-vf', 'fps=30', '.assets/examples/target-240p-30fps.mp4' ])
subprocess.run([ 'ffmpeg', '-i', '.assets/examples/target-240p.mp4', '-vf', 'fps=60', '.assets/examples/target-240p-60fps.mp4' ])
subprocess.run([ 'ffmpeg', '-i', '.assets/examples/target-240p.mp4', '-vf', 'transpose=0', '.assets/examples/target-240p-90deg.mp4' ])
subprocess.run([ 'ffmpeg', '-i', '.assets/examples/target-1080p.mp4', '-vf', 'transpose=0', '.assets/examples/target-1080p-90deg.mp4' ])
def test_get_video_frame() -> None:
@@ -22,15 +25,39 @@ def test_get_video_frame() -> None:
assert get_video_frame('invalid') is None
def test_detect_fps() -> None:
assert detect_fps('.assets/examples/target-240p-25fps.mp4') == 25.0
assert detect_fps('.assets/examples/target-240p-30fps.mp4') == 30.0
assert detect_fps('.assets/examples/target-240p-60fps.mp4') == 60.0
assert detect_fps('invalid') is None
def test_count_video_frame_total() -> None:
assert count_video_frame_total('.assets/examples/target-240p-25fps.mp4') == 270
assert count_video_frame_total('.assets/examples/target-240p-30fps.mp4') == 324
assert count_video_frame_total('.assets/examples/target-240p-60fps.mp4') == 648
assert count_video_frame_total('invalid') == 0
def test_detect_video_fps() -> None:
assert detect_video_fps('.assets/examples/target-240p-25fps.mp4') == 25.0
assert detect_video_fps('.assets/examples/target-240p-30fps.mp4') == 30.0
assert detect_video_fps('.assets/examples/target-240p-60fps.mp4') == 60.0
assert detect_video_fps('invalid') is None
def test_detect_video_resolution() -> None:
assert detect_video_resolution('.assets/examples/target-240p.mp4') == (426.0, 226.0)
assert detect_video_resolution('.assets/examples/target-1080p.mp4') == (2048.0, 1080.0)
assert detect_video_resolution('invalid') is None
def test_pack_resolution() -> None:
assert pack_resolution((1.0, 1.0)) == '0x0'
assert pack_resolution((2.0, 2.0)) == '2x2'
def test_unpack_resolution() -> None:
assert unpack_resolution('0x0') == (0, 0)
assert unpack_resolution('2x2') == (2, 2)
def test_create_video_resolutions() -> None:
assert create_video_resolutions('.assets/examples/target-240p.mp4') == [ '426x226', '452x240', '678x360', '904x480', '1018x540', '1358x720', '2036x1080', '2714x1440', '4072x2160' ]
assert create_video_resolutions('.assets/examples/target-240p-90deg.mp4') == [ '226x426', '240x452', '360x678', '480x904', '540x1018', '720x1358', '1080x2036', '1440x2714', '2160x4072' ]
assert create_video_resolutions('.assets/examples/target-1080p.mp4') == [ '456x240', '682x360', '910x480', '1024x540', '1366x720', '2048x1080', '2730x1440', '4096x2160' ]
assert create_video_resolutions('.assets/examples/target-1080p-90deg.mp4') == [ '240x456', '360x682', '480x910', '540x1024', '720x1366', '1080x2048', '1440x2730', '2160x4096' ]
assert create_video_resolutions('invalid') is None