* Cleanup after age modifier PR

* Cleanup after age modifier PR

* Use OpenVino 2024.2.0 for installer

* Prepare 3.0.0 for installer

* Fix benchmark suite, Introduce sync_item() for state manager

* Fix lint

* Render slide preview also in lower res

* Lower thread and queue count to avoid false usage

* Fix spacing

* Feat/jobs UI (#627)

* Jobs UI part1

* Change naming

* Jobs UI part2

* Jobs UI part3

* Jobs UI part4

* Jobs UI part4

* Jobs UI part5

* Jobs UI part6

* Jobs UI part7

* Jobs UI part8

* Jobs UI part9

* Jobs UI part10

* Jobs UI part11

* Jobs UI part12

* Fix rebase

* Jobs UI part13

* Jobs UI part14

* Jobs UI part15

* changes (#626)

* Remove useless ui registration

* Remove useless ui registration

* move job_list.py
replace [0] with get_first()

* optimize imports

* fix date None problem
add test job list

* Jobs UI part16

* Jobs UI part17

* Jobs UI part18

* Jobs UI part19

* Jobs UI part20

* Jobs UI part21

* Jobs UI part22

* move job_list_options

* Add label to job status checkbox group

* changes

* changes

---------

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

* Update some dependencies

* UI helper to convert 'none'

* validate job (#628)

* changes

* changes

* add test

* changes

* changes

* Minor adjustments

* Replace is_json with is_file

* Handle empty and invalid json in job_list

* Handle empty and invalid json in job_list

* Handle empty and invalid json in job_list

* Work on the job manager UI

* Cosmetic changes on common helper

* Just make it work for now

* Just make it work for now

* Just make it work for now

* Streamline the step index lookups

* Hide footer

* Simplify instant runner

* Simplify instant runner UI and job manager UI

* Fix empty step choices

* Fix empty step choices

* Fix none values in UI

* Rework on benchmark (add warmup) and job list

* Improve ValueAndUnit

* Add step 1 of x output

* Cosmetic changes on the UI

* Fix invalid job file names

* Update preview

* Introducing has_step() and sorting out insert behaviour

* Introducing has_step() and sorting out insert behaviour

* Add [ none ] to some job id dropdowns

* Make updated dropdown values kinda perfect

* Make updated dropdown values kinda perfect

* Fix testing

* Minor improvement on UI

* Fix false config lookup

* Remove TensorRT as our models are not made for it

* Feat/cli commands second try rev2 (#640)

* Refactor CLI to commands

* Refactor CLI to commands part2

* Refactor CLI to commands part3

* Refactor CLI to commands part4

* Rename everything to facefusion.py

* Refactor CLI to commands part5

* Refactor CLI to commands part6

* Adjust testing

* Fix lint

* Fix lint

* Fix lint

* Refactor CLI to commands part7

* Extend State typing

* Fix false config lookup, adjust logical orders

* Move away from passing program part1

* Move away from passing program part2

* Move away from passing program part3

* Fix lint

* Move away from passing program part4

* ui-args update

* ui-args update

* ui-args update

* temporary type fix

* Move away from passing program part5

* remove unused

* creates args.py

* Move away from passing program part6

* Move away from passing program part7

---------

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

* Minor optimizations

* Update commands in README

* Fix job-retry command

* Fix multi runs via UI

* add more job keys

* Cleanup codebase

* One method to create inference session (#641)

* One method to create inference session

* Remove warnings, as there are none

* Remember job id during processing

* Fix face masker config block

* Change wording

* Prevent age modifier from using CoreML

* add expression restorer (#642)

* add expression restorer

* fix import

* fix lint

* changes

* changes

* changes

* Host the final model for expression restorer

* Insert step on the given index

* UI workover (#644)

* UI workover part1

* Introduce ComponentOptions

* Only set Media components to None when visibility changes

* Clear static faces and reference faces between step processing

* Minor changes

* Minor changes

* Fix testing

* Enable test_sanitize_path_for_windows (#646)

* Dynamic download during job processing (#647)

* Fix face masker UI

* Rename run-headless to headless-run

* Feat/split frame processor UI (#649)

* Split frame processor UI

* Split frame processor UI part3, Refactor get_model_initializer

* Split frame processor UI part4

* Feat/rename frame processors (#651)

* Rename frame processors

* Rename frame processors part2

* Fix imports

 Conflicts:
	facefusion/uis/layouts/benchmark.py
	facefusion/uis/layouts/default.py

* Fix imports

* Cosmetic changes

* Fix multi threading for ROCm

* Change temp frames pattern

* Adjust terminal help

* remove expression restorer (#653)

* Expression restorer as processor (#655)

* add expression restorer

* changes

* Cleanup code

* Add TensorRT support back

* Add TensorRT support back

* Add TensorRT support back

* changes (#656)

* Change minor wording

* Fix face enhancer slider

* Add more typing

* Fix expression-restorer when using trim (#659)

* changes

* changes

* Rework/model and inference pool part2 (#660)

* Rework on model and inference pool

* Introduce inference sources and pools part1

* Introduce inference sources and pools part2

* Introduce inference sources and pools part3

* Introduce inference sources and pools part4

* Introduce inference sources and pools part5

* Introduce inference sources and pools part6

* Introduce inference sources and pools part6

* Introduce inference sources and pools part6

* Introduce inference sources and pools part7

* Introduce inference sources and pools part7

* Introduce inference sources and pools part8

* Introduce inference sources and pools part9

* Introduce inference sources and pools part10

* Introduce inference sources and pools part11

* Introduce inference sources and pools part11

* Introduce inference sources and pools part11

* Introduce inference sources and pools part12

* Reorganize the face masker UI

* Fix trim in UI

* Feat/hashed sources (#668)

* Introduce source helper

* Remove post_check() and just use process_manager

* Remove post_check() part2

* Add hash based downloads

* Add hash based downloads part2

* Add hash based downloads part3

* Add hash based downloads part4

* Add hash based downloads part5

* Add hash based downloads part6

* Add hash based downloads part7

* Add hash based downloads part7

* Add hash based downloads part8

* Remove print

* Prepare 3.0.0 release

* Fix UI

* Release the check when really done

* Update inputs for live portrait

* Update to 3.0.0 releases, extend download postfix

* Move files to the right place

* Logging for the hash and source validation

* Changing logic to handle corrupt sources

* Fix typo

* Use names over get_inputs(), Remove set_options() call

* Age modifier now works for CoreML too

* Update age_modifier.py

* Add video encoder h264_videotoolbox and hevc_videotoolbox

* Face editor add eye gaze & remove open factor sliders (#670)

* changes

* add eye gaze

* changes

* cleanup

* add eyebrow control

* changes

* changes

* Feat/terminal UI (#671)

* Introduce terminal to the UI

* Introduce terminal to the UI part2

* Introduce terminal to the UI part2

* Introduce terminal to the UI part2

* Calc range step to avoid weird values

* Use Sequence for ranges

* Use Sequence for ranges

* changes (#673)

* Use Sequence for ranges

* Finalize terminal UI

* Finalize terminal UI

* Webcam cosmetics, Fix normalize fps to accept int

* Cosmetic changes

* Finalize terminal UI

* Rename leftover typings

* Fix wording

* Fix rounding in metavar

* Fix rounding in metavar

* Rename to face classifier

* Face editor lip moves (#677)

* changes

* changes

* changes

* Fix rounding in metavar

* Rename to face classifier

* changes

* changes

* update naming

---------

Co-authored-by: henryruhs <info@henryruhs.com>

* Fix wording

* Feat/many landmarker + face analyser breakdown (#678)

* Basic multi landmarker integration

* Simplify some method names

* Break into face_detector and face_landmarker

* Fix cosmetics

* Fix testing

* Break into face_attributor and face_recognizer

* Clear them all

* Clear them all

* Rename to face classifier

* Rename to face classifier

* Fix testing

* Fix stuff

* Add face landmarker model to UI

* Add face landmarker model to UI part2

* Split the config

* Split the UI

* Improvement from code review

* Improvement from code review

* Validate args also for sub parsers

* Remove clear of processors in process step

* Allow finder control for the face editor

* Fix lint

* Improve testing performance

* Remove unused file, Clear processors from the UI before job runs

* Update the installer

* Uniform set handler for swapper and detector in the UI

* Fix example urls

* Feat/inference manager (#684)

* Introduce inference manager

* Migrate all to inference manager

* clean ini

* Introduce app context based inference pools

* Fix lint

* Fix typing

* Adjust layout

* Less border radius

* Rename app context names

* Fix/live portrait directml (#691)

* changes (#690)

* Adjust naming

* Use our assets release

* Adjust naming

---------

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

* Add caches to gitignore

* Update dependencies and drop CUDA 11.8 support (#693)

* Update dependencies and drop CUDA 11.8 support

* Play save and keep numpy 1.x.x

* Improve TensorRT optimization

* changes

* changes

* changes

* changes

* changes

* changes

* changes

* changes

* changes

* Reuse inference sessions (#696)

* Fix force-download command

* Refactor processors to forward() (#698)

* Install tensorrt when selecting cuda

* Minor changes

* Use latest numpy

* Fix limit system memory

* Implement forward() for every inference (#699)

* Implement forward() for every inference

* Implement forward() for every inference

* Implement forward() for every inference

* Implement forward() for every inference

* changes

* changes

* changes

* changes

* Feat/fairface (#710)

* Replace gender_age model with fair face (#709)

* changes

* changes

* changes

* age dropdown to range-slider

* Cleanup code

* Cleanup code

---------

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

* Extend installer to set library paths for cuda and tensorrt (#707)

* Extend installer to set library paths for cuda and tensorrt

* Add refresh of conda env

* Remove invalid commands

* Set the conda env according to operating system

* Update for ROCm 6.2

* fix installer

* Aktualisieren von installer.py

* Add missing face selector keys

* Try to keep original LD_LIBRARY_PATH

* windows support installer

* Final touch to the installer

* Remove spaces

* Simplidy collect_model_downloads()

* Fix force download for once and forever

* Housekeeping (#715)

* changes

* changes

* changes

* Fix performance part1

* Fix mixed states (#689)

* Fix mixed states

* Add missing sync for job args

* Move UnionStateXXX to base typing

* Undo

* Remove UnionStateXXX

* Fix app context performance lookup (#717)

* Restore performance for inswapper

* Mover upper() to the logger

* Undo debugging

* Move TensorRT installation to docs

* Sort out log level typing, Add log level UI dropdown (#719)

* Fix inference pool part1

* Validate conda library paths existence

* Default face selector order to large-small

* Fix inference pool context according to execution provider (#720)

* Fix app context under Windows

* CUDA and TensorRT update for the installer

* Remove concept of static processor modules

* Revert false commit

* Change event order makes a difference

* Fix multi model context in inference pool (#721)

* Fix multi model context in inference pool

* Fix multi model context in inference pool part2

* Use latest gradio to avoid fastapi bug

* Rework on the Windows Installer

* Use embedding converter (#724)

* changes (#723)

* Upload models to official assets repo

---------

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

* Rework on the Windows Installer part2

* Resolve subprocess calls (#726)

* Experiment

* Resolve subprocess calls to cover edge cases like broken PATH

* Adjust wording

* Simplify code

* Rework on the Windows Installer part3

* Rework on the Windows Installer part4

* Numpy fix for older onnxruntime

* changes (#729)

* Add space

* Add MacOS installer

* Use favicon

* Fix disabled logger

* Layout polishing (#731)

* Update dependencies, Adjust many face landmarker logic

* Cosmetics changes

* Should be button

* Introduce randomized action button

* Fix update of lip syncer and expression restorer

* Stop sharing inference session this prevents flushing VRAM

* Fix test

* Fix urls

* Prepare release

* Vanish inquirer

* Sticky preview does not work on portrait images

* Sticky preview only for landscape images and videos

* remove gradio tunnel env

* Change wording and deeplinks

* increase peppa landmark score offset

* Change wording

* Graceful exit install.py

* Just adding a required

* Cannot use the exit_helper

* Rename our model

* Change color of face-landmark-68/5

* Limit liveportrait (#739)

* changes

* changes

* changes

* Cleanup

* Cleanup

---------

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

* limit expression restorer

* change expression restorer 0-100 range

* Use 256x icon

* changes

* changes

* changes

* changes

* Limit face editor rotation (#745)

* changes (#743)

* Finish euler methods

---------

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

* Use different coveralls badge

* Move about wording

* Shorten scope in the logger

* changes

* changes

* Shorten scope in the logger

* fix typo

* Simplify the arcface converter names

* Update preview

---------

Co-authored-by: Harisreedhar <46858047+harisreedhar@users.noreply.github.com>
Co-authored-by: harisreedhar <h4harisreedhar.s.s@gmail.com>
This commit is contained in:
Henry Ruhs
2024-09-20 17:27:50 +02:00
committed by GitHub
parent 57016d7c77
commit 13761af044
171 changed files with 11598 additions and 5115 deletions

44
tests/helper.py Normal file
View File

@@ -0,0 +1,44 @@
import os
from facefusion.filesystem import create_directory, is_directory, is_file, remove_directory
from facefusion.temp_helper import get_base_directory_path
from facefusion.typing import JobStatus
def is_test_job_file(file_path : str, job_status : JobStatus) -> bool:
return is_file(get_test_job_file(file_path, job_status))
def get_test_job_file(file_path : str, job_status : JobStatus) -> str:
return os.path.join(get_test_jobs_directory(), job_status, file_path)
def get_test_jobs_directory() -> str:
return os.path.join(get_base_directory_path(), 'test-jobs')
def get_test_example_file(file_path : str) -> str:
return os.path.join(get_test_examples_directory(), file_path)
def get_test_examples_directory() -> str:
return os.path.join(get_base_directory_path(), 'test-examples')
def is_test_output_file(file_path : str) -> bool:
return is_file(get_test_output_file(file_path))
def get_test_output_file(file_path : str) -> str:
return os.path.join(get_test_outputs_directory(), file_path)
def get_test_outputs_directory() -> str:
return os.path.join(get_base_directory_path(), 'test-outputs')
def prepare_test_output_directory() -> bool:
test_outputs_directory = get_test_outputs_directory()
remove_directory(test_outputs_directory)
create_directory(test_outputs_directory)
return is_directory(test_outputs_directory)

View File

@@ -1,26 +1,28 @@
import subprocess
import pytest
from facefusion.audio import get_audio_frame, read_static_audio
from facefusion.download import conditional_download
from .helper import get_test_example_file, get_test_examples_directory
@pytest.fixture(scope = 'module', autouse = True)
def before_all() -> None:
conditional_download('.assets/examples',
conditional_download(get_test_examples_directory(),
[
'https://github.com/facefusion/facefusion-assets/releases/download/examples/source.mp3'
'https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/source.mp3'
])
subprocess.run([ 'ffmpeg', '-i', '.assets/examples/source.mp3', '.assets/examples/source.wav' ])
subprocess.run([ 'ffmpeg', '-i', get_test_example_file('source.mp3'), get_test_example_file('source.wav') ])
def test_get_audio_frame() -> None:
assert get_audio_frame('.assets/examples/source.mp3', 25) is not None
assert get_audio_frame('.assets/examples/source.wav', 25) is not None
assert get_audio_frame(get_test_example_file('source.mp3'), 25) is not None
assert get_audio_frame(get_test_example_file('source.wav'), 25) is not None
assert get_audio_frame('invalid', 25) is None
def test_read_static_audio() -> None:
assert len(read_static_audio('.assets/examples/source.mp3', 25)) == 280
assert len(read_static_audio('.assets/examples/source.wav', 25)) == 280
assert len(read_static_audio(get_test_example_file('source.mp3'), 25)) == 280
assert len(read_static_audio(get_test_example_file('source.wav'), 25)) == 280
assert read_static_audio('invalid', 25) is None

View File

@@ -0,0 +1,38 @@
import subprocess
import sys
import pytest
from facefusion.download import conditional_download
from facefusion.jobs.job_manager import clear_jobs, init_jobs
from .helper import get_test_example_file, get_test_examples_directory, get_test_jobs_directory, get_test_output_file, is_test_output_file, prepare_test_output_directory
@pytest.fixture(scope = 'module', autouse = True)
def before_all() -> None:
conditional_download(get_test_examples_directory(),
[
'https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/target-240p.mp4'
])
subprocess.run([ 'ffmpeg', '-i', get_test_example_file('target-240p.mp4'), '-vframes', '1', get_test_example_file('target-240p.jpg') ])
@pytest.fixture(scope = 'function', autouse = True)
def before_each() -> None:
clear_jobs(get_test_jobs_directory())
init_jobs(get_test_jobs_directory())
prepare_test_output_directory()
def test_modify_age_to_image() -> None:
commands = [ sys.executable, 'facefusion.py', 'headless-run', '-j', get_test_jobs_directory(), '--processors', 'age_modifier', '--age-modifier-direction', '100', '-t', get_test_example_file('target-240p.jpg'), '-o', get_test_output_file('test-age-face-to-image.jpg') ]
assert subprocess.run(commands).returncode == 0
assert is_test_output_file('test-age-face-to-image.jpg') is True
def test_modify_age_to_video() -> None:
commands = [ sys.executable, 'facefusion.py', 'headless-run', '-j', get_test_jobs_directory(), '--processors', 'age_modifier', '--age-modifier-direction', '100', '-t', get_test_example_file('target-240p.mp4'), '-o', get_test_output_file('test-age-face-to-video.mp4'), '--trim-frame-end', '1' ]
assert subprocess.run(commands).returncode == 0
assert is_test_output_file('test-age-face-to-video.mp4') is True

View File

@@ -0,0 +1,38 @@
import subprocess
import sys
import pytest
from facefusion.download import conditional_download
from facefusion.jobs.job_manager import clear_jobs, init_jobs
from .helper import get_test_example_file, get_test_examples_directory, get_test_jobs_directory, get_test_output_file, is_test_output_file, prepare_test_output_directory
@pytest.fixture(scope = 'module', autouse = True)
def before_all() -> None:
conditional_download(get_test_examples_directory(),
[
'https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/target-240p.mp4'
])
subprocess.run([ 'ffmpeg', '-i', get_test_example_file('target-240p.mp4'), '-vframes', '1', get_test_example_file('target-240p.jpg') ])
@pytest.fixture(scope = 'function', autouse = True)
def before_each() -> None:
clear_jobs(get_test_jobs_directory())
init_jobs(get_test_jobs_directory())
prepare_test_output_directory()
def test_restore_expression_to_image() -> None:
commands = [ sys.executable, 'facefusion.py', 'headless-run', '-j', get_test_jobs_directory(), '--processors', 'expression_restorer', '-t', get_test_example_file('target-240p.jpg'), '-o', get_test_output_file('test-restore-expression-to-image.jpg') ]
assert subprocess.run(commands).returncode == 0
assert is_test_output_file('test-restore-expression-to-image.jpg') is True
def test_restore_expression_to_video() -> None:
commands = [ sys.executable, 'facefusion.py', 'headless-run', '-j', get_test_jobs_directory(), '--processors', 'expression_restorer', '-t', get_test_example_file('target-240p.mp4'), '-o', get_test_output_file('test-restore-expression-to-video.mp4'), '--trim-frame-end', '1' ]
assert subprocess.run(commands).returncode == 0
assert is_test_output_file('test-restore-expression-to-video.mp4') is True

View File

@@ -1,31 +1,39 @@
import subprocess
import sys
import pytest
from facefusion.download import conditional_download
from facefusion.jobs.job_manager import clear_jobs, init_jobs
from .helper import get_test_example_file, get_test_examples_directory, get_test_jobs_directory, get_test_output_file, is_test_output_file, prepare_test_output_directory
@pytest.fixture(scope = 'module', autouse = True)
def before_all() -> None:
conditional_download('.assets/examples',
conditional_download(get_test_examples_directory(),
[
'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-3.0.0/source.jpg',
'https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/target-240p.mp4'
])
subprocess.run([ 'ffmpeg', '-i', '.assets/examples/target-240p.mp4', '-vframes', '1', '.assets/examples/target-240p.jpg' ])
subprocess.run([ 'ffmpeg', '-i', get_test_example_file('target-240p.mp4'), '-vframes', '1', get_test_example_file('target-240p.jpg') ])
@pytest.fixture(scope = 'function', autouse = True)
def before_each() -> None:
clear_jobs(get_test_jobs_directory())
init_jobs(get_test_jobs_directory())
prepare_test_output_directory()
def test_debug_face_to_image() -> None:
commands = [ sys.executable, 'run.py', '--frame-processors', 'face_debugger', '-t', '.assets/examples/target-240p.jpg', '-o', '.assets/examples/test_debug_face_to_image.jpg', '--headless' ]
run = subprocess.run(commands, stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
commands = [ sys.executable, 'facefusion.py', 'headless-run', '-j', get_test_jobs_directory(), '--processors', 'face_debugger', '-t', get_test_example_file('target-240p.jpg'), '-o', get_test_output_file('test-debug-face-to-image.jpg') ]
assert run.returncode == 0
assert 'image succeed' in run.stdout.decode()
assert subprocess.run(commands).returncode == 0
assert is_test_output_file('test-debug-face-to-image.jpg') is True
def test_debug_face_to_video() -> None:
commands = [ sys.executable, 'run.py', '--frame-processors', 'face_debugger', '-t', '.assets/examples/target-240p.mp4', '-o', '.assets/examples/test_debug_face_to_video.mp4', '--trim-frame-end', '10', '--headless' ]
run = subprocess.run(commands, stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
commands = [ sys.executable, 'facefusion.py', 'headless-run', '-j', get_test_jobs_directory(), '--processors', 'face_debugger', '-t', get_test_example_file('target-240p.mp4'), '-o', get_test_output_file('test-debug-face-to-video.mp4'), '--trim-frame-end', '1' ]
assert run.returncode == 0
assert 'video succeed' in run.stdout.decode()
assert subprocess.run(commands).returncode == 0
assert is_test_output_file('test-debug-face-to-video.mp4') is True

View File

@@ -0,0 +1,39 @@
import subprocess
import sys
import pytest
from facefusion.download import conditional_download
from facefusion.jobs.job_manager import clear_jobs, init_jobs
from .helper import get_test_example_file, get_test_examples_directory, get_test_jobs_directory, get_test_output_file, is_test_output_file, prepare_test_output_directory
@pytest.fixture(scope = 'module', autouse = True)
def before_all() -> None:
conditional_download(get_test_examples_directory(),
[
'https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/source.jpg',
'https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/target-240p.mp4'
])
subprocess.run([ 'ffmpeg', '-i', get_test_example_file('target-240p.mp4'), '-vframes', '1', get_test_example_file('target-240p.jpg') ])
@pytest.fixture(scope = 'function', autouse = True)
def before_each() -> None:
clear_jobs(get_test_jobs_directory())
init_jobs(get_test_jobs_directory())
prepare_test_output_directory()
def test_edit_face_to_image() -> None:
commands = [ sys.executable, 'facefusion.py', 'headless-run', '-j', get_test_jobs_directory(), '--processors', 'face_editor', '-t', get_test_example_file('target-240p.jpg'), '-o', get_test_output_file('test-edit-face-to-image.jpg') ]
assert subprocess.run(commands).returncode == 0
assert is_test_output_file('test-edit-face-to-image.jpg') is True
def test_edit_face_to_video() -> None:
commands = [ sys.executable, 'facefusion.py', 'headless-run', '-j', get_test_jobs_directory(), '--processors', 'face_editor', '-t', get_test_example_file('target-240p.mp4'), '-o', get_test_output_file('test-edit-face-to-video.mp4'), '--trim-frame-end', '1' ]
assert subprocess.run(commands).returncode == 0
assert is_test_output_file('test-edit-face-to-video.mp4') is True

View File

@@ -1,32 +1,39 @@
import subprocess
import sys
import pytest
from facefusion.download import conditional_download
from facefusion.jobs.job_manager import clear_jobs, init_jobs
from .helper import get_test_example_file, get_test_examples_directory, get_test_jobs_directory, get_test_output_file, is_test_output_file, prepare_test_output_directory
@pytest.fixture(scope = 'module', autouse = True)
def before_all() -> None:
conditional_download('.assets/examples',
conditional_download(get_test_examples_directory(),
[
'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-3.0.0/source.jpg',
'https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/target-240p.mp4'
])
subprocess.run([ 'ffmpeg', '-i', '.assets/examples/target-240p.mp4', '-vframes', '1', '.assets/examples/target-240p.jpg' ])
subprocess.run([ 'ffmpeg', '-i', get_test_example_file('target-240p.mp4'), '-vframes', '1', get_test_example_file('target-240p.jpg') ])
@pytest.fixture(scope = 'function', autouse = True)
def before_each() -> None:
clear_jobs(get_test_jobs_directory())
init_jobs(get_test_jobs_directory())
prepare_test_output_directory()
def test_enhance_face_to_image() -> None:
commands = [ sys.executable, 'run.py', '--frame-processors', 'face_enhancer', '-t', '.assets/examples/target-240p.jpg', '-o', '.assets/examples/test_enhance_face_to_image.jpg', '--headless' ]
run = subprocess.run(commands, stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
commands = [ sys.executable, 'facefusion.py', 'headless-run', '-j', get_test_jobs_directory(), '--processors', 'face_enhancer', '-t', get_test_example_file('target-240p.jpg'), '-o', get_test_output_file('test-enhance-face-to-image.jpg') ]
assert run.returncode == 0
assert 'image succeed' in run.stdout.decode()
assert subprocess.run(commands).returncode == 0
assert is_test_output_file('test-enhance-face-to-image.jpg') is True
def test_enhance_face_to_video() -> None:
commands = [ sys.executable, 'run.py', '--frame-processors', 'face_enhancer', '-t', '.assets/examples/target-240p.mp4', '-o', '.assets/examples/test_enhance_face_to_video.mp4', '--trim-frame-end', '10', '--headless' ]
run = subprocess.run(commands, stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
assert run.returncode == 0
assert 'video succeed' in run.stdout.decode()
commands = [ sys.executable, 'facefusion.py', 'headless-run', '-j', get_test_jobs_directory(), '--processors', 'face_enhancer', '-t', get_test_example_file('target-240p.mp4'), '-o', get_test_output_file('test-enhance-face-to-video.mp4'), '--trim-frame-end', '1' ]
assert subprocess.run(commands).returncode == 0
assert is_test_output_file('test-enhance-face-to-video.mp4') is True

View File

@@ -1,31 +1,39 @@
import subprocess
import sys
import pytest
from facefusion.download import conditional_download
from facefusion.jobs.job_manager import clear_jobs, init_jobs
from .helper import get_test_example_file, get_test_examples_directory, get_test_jobs_directory, get_test_output_file, is_test_output_file, prepare_test_output_directory
@pytest.fixture(scope = 'module', autouse = True)
def before_all() -> None:
conditional_download('.assets/examples',
conditional_download(get_test_examples_directory(),
[
'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-3.0.0/source.jpg',
'https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/target-240p.mp4'
])
subprocess.run([ 'ffmpeg', '-i', '.assets/examples/target-240p.mp4', '-vframes', '1', '.assets/examples/target-240p.jpg' ])
subprocess.run([ 'ffmpeg', '-i', get_test_example_file('target-240p.mp4'), '-vframes', '1', get_test_example_file('target-240p.jpg') ])
@pytest.fixture(scope = 'function', autouse = True)
def before_each() -> None:
clear_jobs(get_test_jobs_directory())
init_jobs(get_test_jobs_directory())
prepare_test_output_directory()
def test_swap_face_to_image() -> None:
commands = [ sys.executable, 'run.py', '--frame-processors', 'face_swapper', '-s', '.assets/examples/source.jpg', '-t', '.assets/examples/target-240p.jpg', '-o', '.assets/examples/test_swap_face_to_image.jpg', '--headless' ]
run = subprocess.run(commands, stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
commands = [ sys.executable, 'facefusion.py', 'headless-run', '-j', get_test_jobs_directory(), '--processors', 'face_swapper', '-s', get_test_example_file('source.jpg'), '-t', get_test_example_file('target-240p.jpg'), '-o', get_test_output_file('test-swap-face-to-image.jpg') ]
assert run.returncode == 0
assert 'image succeed' in run.stdout.decode()
assert subprocess.run(commands).returncode == 0
assert is_test_output_file('test-swap-face-to-image.jpg') is True
def test_swap_face_to_video() -> None:
commands = [ sys.executable, 'run.py', '--frame-processors', 'face_swapper', '-s', '.assets/examples/source.jpg', '-t', '.assets/examples/target-240p.mp4', '-o', '.assets/examples/test_swap_face_to_video.mp4', '--trim-frame-end', '10', '--headless' ]
run = subprocess.run(commands, stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
commands = [ sys.executable, 'facefusion.py', 'headless-run', '-j', get_test_jobs_directory(), '--processors', 'face_swapper', '-s', get_test_example_file('source.jpg'), '-t', get_test_example_file('target-240p.mp4'), '-o', get_test_output_file('test-swap-face-to-video.mp4'), '--trim-frame-end', '1' ]
assert run.returncode == 0
assert 'video succeed' in run.stdout.decode()
assert subprocess.run(commands).returncode == 0
assert is_test_output_file('test-swap-face-to-video.mp4') is True

View File

@@ -1,32 +1,40 @@
import subprocess
import sys
import pytest
from facefusion.download import conditional_download
from facefusion.jobs.job_manager import clear_jobs, init_jobs
from .helper import get_test_example_file, get_test_examples_directory, get_test_jobs_directory, get_test_output_file, is_test_output_file, prepare_test_output_directory
@pytest.fixture(scope = 'module', autouse = True)
def before_all() -> None:
conditional_download('.assets/examples',
conditional_download(get_test_examples_directory(),
[
'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-3.0.0/source.jpg',
'https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/target-240p.mp4'
])
subprocess.run([ 'ffmpeg', '-i', '.assets/examples/target-240p.mp4', '-vframes', '1', '-vf', 'hue=s=0', '.assets/examples/target-240p-0sat.jpg' ])
subprocess.run([ 'ffmpeg', '-i', '.assets/examples/target-240p.mp4', '-vf', 'hue=s=0', '.assets/examples/target-240p-0sat.mp4' ])
subprocess.run([ 'ffmpeg', '-i', get_test_example_file('target-240p.mp4'), '-vframes', '1', '-vf', 'hue=s=0', get_test_example_file('target-240p-0sat.jpg') ])
subprocess.run([ 'ffmpeg', '-i', get_test_example_file('target-240p.mp4'), '-vf', 'hue=s=0', get_test_example_file('target-240p-0sat.mp4') ])
@pytest.fixture(scope = 'function', autouse = True)
def before_each() -> None:
clear_jobs(get_test_jobs_directory())
init_jobs(get_test_jobs_directory())
prepare_test_output_directory()
def test_colorize_frame_to_image() -> None:
commands = [ sys.executable, 'run.py', '--frame-processors', 'frame_colorizer', '-t', '.assets/examples/target-240p-0sat.jpg', '-o', '.assets/examples/test_colorize_frame_to_image.jpg', '--headless' ]
run = subprocess.run(commands, stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
commands = [ sys.executable, 'facefusion.py', 'headless-run', '-j', get_test_jobs_directory(), '--processors', 'frame_colorizer', '-t', get_test_example_file('target-240p-0sat.jpg'), '-o', get_test_output_file('test_colorize-frame-to-image.jpg') ]
assert run.returncode == 0
assert 'image succeed' in run.stdout.decode()
assert subprocess.run(commands).returncode == 0
assert is_test_output_file('test_colorize-frame-to-image.jpg') is True
def test_colorize_frame_to_video() -> None:
commands = [ sys.executable, 'run.py', '--frame-processors', 'frame_colorizer', '-t', '.assets/examples/target-240p-0sat.mp4', '-o', '.assets/examples/test_colorize_frame_to_video.mp4', '--trim-frame-end', '10', '--headless' ]
run = subprocess.run(commands, stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
commands = [ sys.executable, 'facefusion.py', 'headless-run', '-j', get_test_jobs_directory(), '--processors', 'frame_colorizer', '-t', get_test_example_file('target-240p-0sat.mp4'), '-o', get_test_output_file('test-colorize-frame-to-video.mp4'), '--trim-frame-end', '1' ]
assert run.returncode == 0
assert 'video succeed' in run.stdout.decode()
assert subprocess.run(commands).returncode == 0
assert is_test_output_file('test-colorize-frame-to-video.mp4') is True

View File

@@ -1,31 +1,39 @@
import subprocess
import sys
import pytest
from facefusion.download import conditional_download
from facefusion.jobs.job_manager import clear_jobs, init_jobs
from .helper import get_test_example_file, get_test_examples_directory, get_test_jobs_directory, get_test_output_file, is_test_output_file, prepare_test_output_directory
@pytest.fixture(scope = 'module', autouse = True)
def before_all() -> None:
conditional_download('.assets/examples',
conditional_download(get_test_examples_directory(),
[
'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-3.0.0/source.jpg',
'https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/target-240p.mp4'
])
subprocess.run([ 'ffmpeg', '-i', '.assets/examples/target-240p.mp4', '-vframes', '1', '.assets/examples/target-240p.jpg' ])
subprocess.run([ 'ffmpeg', '-i', get_test_example_file('target-240p.mp4'), '-vframes', '1', get_test_example_file('target-240p.jpg') ])
@pytest.fixture(scope = 'function', autouse = True)
def before_each() -> None:
clear_jobs(get_test_jobs_directory())
init_jobs(get_test_jobs_directory())
prepare_test_output_directory()
def test_enhance_frame_to_image() -> None:
commands = [ sys.executable, 'run.py', '--frame-processors', 'frame_enhancer', '-t', '.assets/examples/target-240p.jpg', '-o', '.assets/examples/test_enhance_frame_to_image.jpg', '--headless' ]
run = subprocess.run(commands, stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
commands = [ sys.executable, 'facefusion.py', 'headless-run', '-j', get_test_jobs_directory(), '--processors', 'frame_enhancer', '-t', get_test_example_file('target-240p.jpg'), '-o', get_test_output_file('test-enhance-frame-to-image.jpg') ]
assert run.returncode == 0
assert 'image succeed' in run.stdout.decode()
assert subprocess.run(commands).returncode == 0
assert is_test_output_file('test-enhance-frame-to-image.jpg') is True
def test_enhance_frame_to_video() -> None:
commands = [ sys.executable, 'run.py', '--frame-processors', 'frame_enhancer', '-t', '.assets/examples/target-240p.mp4', '-o', '.assets/examples/test_enhance_frame_to_video.mp4', '--trim-frame-end', '10', '--headless' ]
run = subprocess.run(commands, stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
commands = [ sys.executable, 'facefusion.py', 'headless-run', '-j', get_test_jobs_directory(), '--processors', 'frame_enhancer', '-t', get_test_example_file('target-240p.mp4'), '-o', get_test_output_file('test-enhance-frame-to-video.mp4'), '--trim-frame-end', '1' ]
assert run.returncode == 0
assert 'video succeed' in run.stdout.decode()
assert subprocess.run(commands).returncode == 0
assert is_test_output_file('test-enhance-frame-to-video.mp4') is True

View File

@@ -0,0 +1,204 @@
import subprocess
import sys
import pytest
from facefusion.download import conditional_download
from facefusion.jobs.job_manager import clear_jobs, count_step_total, init_jobs
from .helper import get_test_example_file, get_test_examples_directory, get_test_jobs_directory, get_test_output_file, is_test_job_file
@pytest.fixture(scope = 'module', autouse = True)
def before_all() -> None:
conditional_download(get_test_examples_directory(),
[
'https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/source.jpg',
'https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/target-240p.mp4'
])
subprocess.run([ 'ffmpeg', '-i', get_test_example_file('target-240p.mp4'), '-vframes', '1', get_test_example_file('target-240p.jpg') ])
@pytest.fixture(scope = 'function', autouse = True)
def before_each() -> None:
clear_jobs(get_test_jobs_directory())
init_jobs(get_test_jobs_directory())
def test_job_create() -> None:
commands = [ sys.executable, 'facefusion.py', 'job-create', 'test-job-create', '-j', get_test_jobs_directory() ]
assert subprocess.run(commands).returncode == 0
assert is_test_job_file('test-job-create.json', 'drafted') is True
commands = [ sys.executable, 'facefusion.py', 'job-create', 'test-job-create', '-j', get_test_jobs_directory() ]
assert subprocess.run(commands).returncode == 1
def test_job_submit() -> None:
commands = [ sys.executable, 'facefusion.py', 'job-submit', 'test-job-submit', '-j', get_test_jobs_directory() ]
assert subprocess.run(commands).returncode == 1
commands = [ sys.executable, 'facefusion.py', 'job-create', 'test-job-submit', '-j', get_test_jobs_directory() ]
subprocess.run(commands)
assert subprocess.run(commands).returncode == 1
commands = [ sys.executable, 'facefusion.py', 'job-add-step', 'test-job-submit', '-j', get_test_jobs_directory(), '-s', get_test_example_file('source.jpg'), '-t', get_test_example_file('target-240p.jpg'), '-o', get_test_output_file('test-job-remix-step.jpg') ]
subprocess.run(commands)
commands = [ sys.executable, 'facefusion.py', 'job-submit', 'test-job-submit', '-j', get_test_jobs_directory() ]
assert subprocess.run(commands).returncode == 0
assert is_test_job_file('test-job-submit.json', 'queued') is True
assert subprocess.run(commands).returncode == 1
def test_submit_all() -> None:
commands = [ sys.executable, 'facefusion.py', 'job-submit-all', '-j', get_test_jobs_directory() ]
assert subprocess.run(commands).returncode == 1
commands = [ sys.executable, 'facefusion.py', 'job-create', 'test-job-submit-all-1', '-j', get_test_jobs_directory() ]
subprocess.run(commands)
commands = [ sys.executable, 'facefusion.py', 'job-create', 'test-job-submit-all-2', '-j', get_test_jobs_directory() ]
subprocess.run(commands)
assert subprocess.run(commands).returncode == 1
commands = [ sys.executable, 'facefusion.py', 'job-add-step', 'test-job-submit-all-1', '-j', get_test_jobs_directory(), '-s', get_test_example_file('source.jpg'), '-t', get_test_example_file('target-240p.jpg'), '-o', get_test_output_file('test-job-remix-step.jpg') ]
subprocess.run(commands)
commands = [ sys.executable, 'facefusion.py', 'job-add-step', 'test-job-submit-all-2', '-j', get_test_jobs_directory(), '-s', get_test_example_file('source.jpg'), '-t', get_test_example_file('target-240p.jpg'), '-o', get_test_output_file('test-job-remix-step.jpg') ]
subprocess.run(commands)
commands = [ sys.executable, 'facefusion.py', 'job-submit-all', '-j', get_test_jobs_directory() ]
assert subprocess.run(commands).returncode == 0
assert is_test_job_file('test-job-submit-all-1.json', 'queued') is True
assert is_test_job_file('test-job-submit-all-2.json', 'queued') is True
assert subprocess.run(commands).returncode == 1
def test_job_delete() -> None:
commands = [ sys.executable, 'facefusion.py', 'job-delete', 'test-job-delete', '-j', get_test_jobs_directory() ]
assert subprocess.run(commands).returncode == 1
commands = [ sys.executable, 'facefusion.py', 'job-create', 'test-job-delete', '-j', get_test_jobs_directory() ]
subprocess.run(commands)
commands = [ sys.executable, 'facefusion.py', 'job-delete', 'test-job-delete', '-j', get_test_jobs_directory() ]
assert subprocess.run(commands).returncode == 0
assert is_test_job_file('test-job-delete.json', 'drafted') is False
assert subprocess.run(commands).returncode == 1
def test_job_delete_all() -> None:
commands = [ sys.executable, 'facefusion.py', 'job-delete-all', '-j', get_test_jobs_directory() ]
assert subprocess.run(commands).returncode == 1
commands = [ sys.executable, 'facefusion.py', 'job-create', 'test-job-delete-all-1', '-j', get_test_jobs_directory() ]
subprocess.run(commands)
commands = [ sys.executable, 'facefusion.py', 'job-create', 'test-job-delete-all-2', '-j', get_test_jobs_directory() ]
subprocess.run(commands)
commands = [ sys.executable, 'facefusion.py', 'job-delete-all', '-j', get_test_jobs_directory() ]
assert subprocess.run(commands).returncode == 0
assert is_test_job_file('test-job-delete-all-1.json', 'drafted') is False
assert is_test_job_file('test-job-delete-all-2.json', 'drafted') is False
assert subprocess.run(commands).returncode == 1
def test_job_add_step() -> None:
commands = [ sys.executable, 'facefusion.py', 'job-add-step', 'test-job-add-step', '-j', get_test_jobs_directory(), '-s', get_test_example_file('source.jpg'), '-t', get_test_example_file('target-240p.jpg'), '-o', get_test_output_file('test-job-remix-step.jpg') ]
assert subprocess.run(commands).returncode == 1
assert count_step_total('test-job-add-step') == 0
commands = [ sys.executable, 'facefusion.py', 'job-create', 'test-job-add-step', '-j', get_test_jobs_directory() ]
subprocess.run(commands)
commands = [ sys.executable, 'facefusion.py', 'job-add-step', 'test-job-add-step', '-j', get_test_jobs_directory(), '-s', get_test_example_file('source.jpg'), '-t', get_test_example_file('target-240p.jpg'), '-o', get_test_output_file('test-job-remix-step.jpg') ]
assert subprocess.run(commands).returncode == 0
assert count_step_total('test-job-add-step') == 1
def test_job_remix() -> None:
commands = [ sys.executable, 'facefusion.py', 'job-remix-step', 'test-job-remix-step', '0', '-j', get_test_jobs_directory(), '-s', get_test_example_file('source.jpg'), '-o', get_test_output_file('test-job-remix-step.jpg') ]
assert subprocess.run(commands).returncode == 1
assert count_step_total('test-job-remix-step') == 0
commands = [ sys.executable, 'facefusion.py', 'job-create', 'test-job-remix-step', '-j', get_test_jobs_directory() ]
subprocess.run(commands)
commands = [ sys.executable, 'facefusion.py', 'job-add-step', 'test-job-remix-step', '-j', get_test_jobs_directory(), '-s', get_test_example_file('source.jpg'), '-t', get_test_example_file('target-240p.jpg'), '-o', get_test_output_file('test-job-remix-step.jpg') ]
subprocess.run(commands)
commands = [ sys.executable, 'facefusion.py', 'job-remix-step', 'test-job-remix-step', '0', '-j', get_test_jobs_directory(), '-s', get_test_example_file('source.jpg'), '-o', get_test_output_file('test-job-remix-step.jpg') ]
assert count_step_total('test-job-remix-step') == 1
assert subprocess.run(commands).returncode == 0
assert count_step_total('test-job-remix-step') == 2
commands = [ sys.executable, 'facefusion.py', 'job-remix-step', 'test-job-remix-step', '-1', '-j', get_test_jobs_directory(), '-s', get_test_example_file('source.jpg'), '-o', get_test_output_file('test-job-remix-step.jpg') ]
assert subprocess.run(commands).returncode == 0
assert count_step_total('test-job-remix-step') == 3
def test_job_insert_step() -> None:
commands = [ sys.executable, 'facefusion.py', 'job-insert-step', 'test-job-insert-step', '0', '-j', get_test_jobs_directory(), '-s', get_test_example_file('source.jpg'), '-t', get_test_example_file('target-240p.jpg'), '-o', get_test_output_file('test-job-remix-step.jpg') ]
assert subprocess.run(commands).returncode == 1
assert count_step_total('test-job-insert-step') == 0
commands = [ sys.executable, 'facefusion.py', 'job-create', 'test-job-insert-step', '-j', get_test_jobs_directory() ]
subprocess.run(commands)
commands = [ sys.executable, 'facefusion.py', 'job-add-step', 'test-job-insert-step', '-j', get_test_jobs_directory(), '-s', get_test_example_file('source.jpg'), '-t', get_test_example_file('target-240p.jpg'), '-o', get_test_output_file('test-job-remix-step.jpg') ]
subprocess.run(commands)
commands = [ sys.executable, 'facefusion.py', 'job-insert-step', 'test-job-insert-step', '0', '-j', get_test_jobs_directory(), '-s', get_test_example_file('source.jpg'), '-t', get_test_example_file('target-240p.jpg'), '-o', get_test_output_file('test-job-remix-step.jpg') ]
assert count_step_total('test-job-insert-step') == 1
assert subprocess.run(commands).returncode == 0
assert count_step_total('test-job-insert-step') == 2
commands = [ sys.executable, 'facefusion.py', 'job-insert-step', 'test-job-insert-step', '-1', '-j', get_test_jobs_directory(), '-s', get_test_example_file('source.jpg'), '-t', get_test_example_file('target-240p.jpg'), '-o', get_test_output_file('test-job-remix-step.jpg') ]
assert subprocess.run(commands).returncode == 0
assert count_step_total('test-job-insert-step') == 3
def test_job_remove_step() -> None:
commands = [ sys.executable, 'facefusion.py', 'job-remove-step', 'test-job-remove-step', '0', '-j', get_test_jobs_directory() ]
assert subprocess.run(commands).returncode == 1
commands = [ sys.executable, 'facefusion.py', 'job-create', 'test-job-remove-step', '-j', get_test_jobs_directory() ]
subprocess.run(commands)
commands = [ sys.executable, 'facefusion.py', 'job-add-step', 'test-job-remove-step', '-j', get_test_jobs_directory(), '-s', get_test_example_file('source.jpg'), '-t', get_test_example_file('target-240p.jpg'), '-o', get_test_output_file('test-job-remix-step.jpg') ]
subprocess.run(commands)
subprocess.run(commands)
commands = [ sys.executable, 'facefusion.py', 'job-remove-step', 'test-job-remove-step', '0', '-j', get_test_jobs_directory() ]
assert count_step_total('test-job-remove-step') == 2
assert subprocess.run(commands).returncode == 0
assert count_step_total('test-job-remove-step') == 1
commands = [ sys.executable, 'facefusion.py', 'job-remove-step', 'test-job-remove-step', '-1', '-j', get_test_jobs_directory() ]
assert subprocess.run(commands).returncode == 0
assert subprocess.run(commands).returncode == 1
assert count_step_total('test-job-remove-step') == 0

View File

@@ -0,0 +1,147 @@
import subprocess
import sys
import pytest
from facefusion.download import conditional_download
from facefusion.jobs.job_manager import clear_jobs, init_jobs, move_job_file, set_steps_status
from .helper import get_test_example_file, get_test_examples_directory, get_test_jobs_directory, get_test_output_file, is_test_output_file, prepare_test_output_directory
@pytest.fixture(scope = 'module', autouse = True)
def before_all() -> None:
conditional_download(get_test_examples_directory(),
[
'https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/source.jpg',
'https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/target-240p.mp4'
])
subprocess.run([ 'ffmpeg', '-i', get_test_example_file('target-240p.mp4'), '-vframes', '1', get_test_example_file('target-240p.jpg') ])
@pytest.fixture(scope = 'function', autouse = True)
def before_each() -> None:
clear_jobs(get_test_jobs_directory())
init_jobs(get_test_jobs_directory())
prepare_test_output_directory()
def test_job_run() -> None:
commands = [ sys.executable, 'facefusion.py', 'job-run', 'test-job-run', '-j', get_test_jobs_directory() ]
assert subprocess.run(commands).returncode == 1
commands = [ sys.executable, 'facefusion.py', 'job-create', 'test-job-run', '-j', get_test_jobs_directory() ]
subprocess.run(commands)
commands = [ sys.executable, 'facefusion.py', 'job-add-step', 'test-job-run', '-j', get_test_jobs_directory(), '--processors', 'face_debugger', '-t', get_test_example_file('target-240p.jpg'), '-o', get_test_output_file('test-job-run.jpg') ]
subprocess.run(commands)
commands = [ sys.executable, 'facefusion.py', 'job-run', 'test-job-run', '-j', get_test_jobs_directory() ]
assert subprocess.run(commands).returncode == 1
commands = [ sys.executable, 'facefusion.py', 'job-submit', 'test-job-run', '-j', get_test_jobs_directory() ]
subprocess.run(commands)
commands = [ sys.executable, 'facefusion.py', 'job-run', 'test-job-run', '-j', get_test_jobs_directory() ]
assert subprocess.run(commands).returncode == 0
assert subprocess.run(commands).returncode == 1
assert is_test_output_file('test-job-run.jpg') is True
def test_job_run_all() -> None:
commands = [ sys.executable, 'facefusion.py', 'job-run-all', '-j', get_test_jobs_directory() ]
assert subprocess.run(commands).returncode == 1
commands = [ sys.executable, 'facefusion.py', 'job-create', 'test-job-run-all-1', '-j', get_test_jobs_directory() ]
subprocess.run(commands)
commands = [ sys.executable, 'facefusion.py', 'job-create', 'test-job-run-all-2', '-j', get_test_jobs_directory() ]
subprocess.run(commands)
commands = [ sys.executable, 'facefusion.py', 'job-add-step', 'test-job-run-all-1', '-j', get_test_jobs_directory(), '--processors', 'face_debugger', '-t', get_test_example_file('target-240p.jpg'), '-o', get_test_output_file('test-job-run-all-1.jpg') ]
subprocess.run(commands)
commands = [ sys.executable, 'facefusion.py', 'job-add-step', 'test-job-run-all-2', '-j', get_test_jobs_directory(), '--processors', 'face_debugger', '-t', get_test_example_file('target-240p.mp4'), '-o', get_test_output_file('test-job-run-all-2.mp4'), '--trim-frame-end', '1' ]
subprocess.run(commands)
commands = [ sys.executable, 'facefusion.py', 'job-add-step', 'test-job-run-all-2', '-j', get_test_jobs_directory(), '--processors', 'face_debugger', '-t', get_test_example_file('target-240p.mp4'), '-o', get_test_output_file('test-job-run-all-2.mp4'), '--trim-frame-start', '0', '--trim-frame-end', '1' ]
subprocess.run(commands)
commands = [ sys.executable, 'facefusion.py', 'job-run-all', '-j', get_test_jobs_directory() ]
assert subprocess.run(commands).returncode == 1
commands = [ sys.executable, 'facefusion.py', 'job-submit-all', '-j', get_test_jobs_directory() ]
subprocess.run(commands)
commands = [ sys.executable, 'facefusion.py', 'job-run-all', '-j', get_test_jobs_directory() ]
assert subprocess.run(commands).returncode == 0
assert subprocess.run(commands).returncode == 1
assert is_test_output_file('test-job-run-all-1.jpg') is True
assert is_test_output_file('test-job-run-all-2.mp4') is True
def test_job_retry() -> None:
commands = [ sys.executable, 'facefusion.py', 'job-retry', 'test-job-retry', '-j', get_test_jobs_directory() ]
assert subprocess.run(commands).returncode == 1
commands = [ sys.executable, 'facefusion.py', 'job-create', 'test-job-retry', '-j', get_test_jobs_directory() ]
subprocess.run(commands)
commands = [ sys.executable, 'facefusion.py', 'job-add-step', 'test-job-retry', '-j', get_test_jobs_directory(), '--processors', 'face_debugger', '-t', get_test_example_file('target-240p.jpg'), '-o', get_test_output_file('test-job-retry.jpg') ]
subprocess.run(commands)
commands = [ sys.executable, 'facefusion.py', 'job-retry', 'test-job-retry', '-j', get_test_jobs_directory() ]
assert subprocess.run(commands).returncode == 1
set_steps_status('test-job-retry', 'failed')
move_job_file('test-job-retry', 'failed')
commands = [ sys.executable, 'facefusion.py', 'job-retry', 'test-job-retry', '-j', get_test_jobs_directory() ]
assert subprocess.run(commands).returncode == 0
assert subprocess.run(commands).returncode == 1
assert is_test_output_file('test-job-retry.jpg') is True
def test_job_retry_all() -> None:
commands = [ sys.executable, 'facefusion.py', 'job-retry-all', '-j', get_test_jobs_directory() ]
assert subprocess.run(commands).returncode == 1
commands = [ sys.executable, 'facefusion.py', 'job-create', 'test-job-retry-all-1', '-j', get_test_jobs_directory() ]
subprocess.run(commands)
commands = [ sys.executable, 'facefusion.py', 'job-create', 'test-job-retry-all-2', '-j', get_test_jobs_directory() ]
subprocess.run(commands)
commands = [ sys.executable, 'facefusion.py', 'job-add-step', 'test-job-retry-all-1', '-j', get_test_jobs_directory(), '--processors', 'face_debugger', '-t', get_test_example_file('target-240p.jpg'), '-o', get_test_output_file('test-job-retry-all-1.jpg') ]
subprocess.run(commands)
commands = [ sys.executable, 'facefusion.py', 'job-add-step', 'test-job-retry-all-2', '-j', get_test_jobs_directory(), '--processors', 'face_debugger', '-t', get_test_example_file('target-240p.mp4'), '-o', get_test_output_file('test-job-retry-all-2.mp4'), '--trim-frame-end', '1' ]
subprocess.run(commands)
commands = [ sys.executable, 'facefusion.py', 'job-add-step', 'test-job-retry-all-2', '-j', get_test_jobs_directory(), '--processors', 'face_debugger', '-t', get_test_example_file('target-240p.mp4'), '-o', get_test_output_file('test-job-retry-all-2.mp4'), '--trim-frame-start', '0', '--trim-frame-end', '1' ]
subprocess.run(commands)
commands = [ sys.executable, 'facefusion.py', 'job-retry-all', '-j', get_test_jobs_directory() ]
assert subprocess.run(commands).returncode == 1
set_steps_status('test-job-retry-all-1', 'failed')
set_steps_status('test-job-retry-all-2', 'failed')
move_job_file('test-job-retry-all-1', 'failed')
move_job_file('test-job-retry-all-2', 'failed')
commands = [ sys.executable, 'facefusion.py', 'job-retry-all', '-j', get_test_jobs_directory() ]
assert subprocess.run(commands).returncode == 0
assert subprocess.run(commands).returncode == 1
assert is_test_output_file('test-job-retry-all-1.jpg') is True
assert is_test_output_file('test-job-retry-all-2.mp4') is True

View File

@@ -1,32 +1,40 @@
import subprocess
import sys
import pytest
from facefusion.download import conditional_download
from facefusion.jobs.job_manager import clear_jobs, init_jobs
from .helper import get_test_example_file, get_test_examples_directory, get_test_jobs_directory, get_test_output_file, is_test_output_file, prepare_test_output_directory
@pytest.fixture(scope = 'module', autouse = True)
def before_all() -> None:
conditional_download('.assets/examples',
conditional_download(get_test_examples_directory(),
[
'https://github.com/facefusion/facefusion-assets/releases/download/examples/source.jpg',
'https://github.com/facefusion/facefusion-assets/releases/download/examples/source.mp3',
'https://github.com/facefusion/facefusion-assets/releases/download/examples/target-240p.mp4'
'https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/source.jpg',
'https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/source.mp3',
'https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/target-240p.mp4'
])
subprocess.run([ 'ffmpeg', '-i', '.assets/examples/target-240p.mp4', '-vframes', '1', '.assets/examples/target-240p.jpg' ])
subprocess.run([ 'ffmpeg', '-i', get_test_example_file('target-240p.mp4'), '-vframes', '1', get_test_example_file('target-240p.jpg') ])
@pytest.fixture(scope = 'function', autouse = True)
def before_each() -> None:
clear_jobs(get_test_jobs_directory())
init_jobs(get_test_jobs_directory())
prepare_test_output_directory()
def test_sync_lip_to_image() -> None:
commands = [ sys.executable, 'run.py', '--frame-processors', 'lip_syncer', '-s', '.assets/examples/source.mp3', '-t', '.assets/examples/target-240p.jpg', '-o', '.assets/examples/test_sync_lip_to_image.jpg', '--headless' ]
run = subprocess.run(commands, stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
commands = [ sys.executable, 'facefusion.py', 'headless-run', '-j', get_test_jobs_directory(), '--processors', 'lip_syncer', '-s', get_test_example_file('source.mp3'), '-t', get_test_example_file('target-240p.jpg'), '-o', get_test_output_file('test_sync_lip_to_image.jpg') ]
assert run.returncode == 0
assert 'image succeed' in run.stdout.decode()
assert subprocess.run(commands).returncode == 0
assert is_test_output_file('test_sync_lip_to_image.jpg') is True
def test_sync_lip_to_video() -> None:
commands = [ sys.executable, 'run.py', '--frame-processors', 'lip_syncer', '-s', '.assets/examples/source.mp3', '-t', '.assets/examples/target-240p.mp4', '-o', '.assets/examples/test_sync_lip_to_video.mp4', '--trim-frame-end', '10', '--headless' ]
run = subprocess.run(commands, stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
commands = [ sys.executable, 'facefusion.py', 'headless-run', '-j', get_test_jobs_directory(), '--processors', 'lip_syncer', '-s', get_test_example_file('source.mp3'), '-t', get_test_example_file('target-240p.mp4'), '-o', get_test_output_file('test_sync_lip_to_video.mp4'), '--trim-frame-end', '1' ]
assert run.returncode == 0
assert 'video succeed' in run.stdout.decode()
assert subprocess.run(commands).returncode == 0
assert is_test_output_file('test_sync_lip_to_video.mp4') is True

View File

@@ -1,8 +1,12 @@
from facefusion.common_helper import create_metavar, create_int_range, create_float_range
from facefusion.common_helper import calc_float_step, calc_int_step, create_float_metavar, create_float_range, create_int_metavar, create_int_range
def test_create_metavar() -> None:
assert create_metavar([ 1, 2, 3, 4, 5 ]) == '[1-5]'
def test_create_int_metavar() -> None:
assert create_int_metavar([ 1, 2, 3, 4, 5 ]) == '[1..5:1]'
def test_create_float_metavar() -> None:
assert create_float_metavar([ 0.1, 0.2, 0.3, 0.4, 0.5 ]) == '[0.1..0.5:0.1]'
def test_create_int_range() -> None:
@@ -13,3 +17,11 @@ def test_create_int_range() -> None:
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, 1.0, 0.05) == [ 0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.50, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.0 ]
def test_calc_int_step() -> None:
assert calc_int_step([ 0, 1 ]) == 1
def test_calc_float_step() -> None:
assert calc_float_step([ 0.1, 0.2 ]) == 0.1

View File

@@ -1,4 +1,5 @@
from configparser import ConfigParser
import pytest
from facefusion import config

15
tests/test_date_helper.py Normal file
View File

@@ -0,0 +1,15 @@
from datetime import datetime, timedelta
from facefusion.date_helper import describe_time_ago
def get_time_ago(days : int, hours : int, minutes : int) -> datetime:
previous_time = datetime.now() - timedelta(days = days, hours = hours, minutes = minutes)
return previous_time.astimezone()
def test_describe_time_ago() -> None:
assert describe_time_ago(get_time_ago(0, 0, 0)) == 'just now'
assert describe_time_ago(get_time_ago(0, 0, 5)) == '5 minutes ago'
assert describe_time_ago(get_time_ago(0, 5, 10)) == '5 hours and 10 minutes ago'
assert describe_time_ago(get_time_ago(5, 10, 15)) == '5 days, 10 hours and 15 minutes ago'

View File

@@ -1,23 +1,24 @@
import pytest
from facefusion.download import conditional_download, get_download_size, is_download_done
from .helper import get_test_example_file, get_test_examples_directory
@pytest.fixture(scope = 'module', autouse = True)
def before_all() -> None:
conditional_download('.assets/examples',
conditional_download(get_test_examples_directory(),
[
'https://github.com/facefusion/facefusion-assets/releases/download/examples/target-240p.mp4'
'https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/target-240p.mp4'
])
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('https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/target-240p.mp4') == 191675
assert get_download_size('https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/target-360p.mp4') == 370732
assert get_download_size('invalid') == 0
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('https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/target-240p.mp4', get_test_example_file('target-240p.mp4')) is True
assert is_download_done('https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/target-240p.mp4', 'invalid') is False
assert is_download_done('invalid', 'invalid') is False

View File

@@ -1,27 +1,24 @@
from facefusion.execution import encode_execution_providers, decode_execution_providers, has_execution_provider, apply_execution_provider_options
from facefusion.execution import create_execution_providers, get_execution_provider_choices, has_execution_provider
def test_encode_execution_providers() -> None:
assert encode_execution_providers([ 'CPUExecutionProvider' ]) == [ 'cpu' ]
def test_decode_execution_providers() -> None:
assert decode_execution_providers([ 'cpu' ]) == [ 'CPUExecutionProvider' ]
def test_get_execution_provider_choices() -> None:
assert 'cpu' in get_execution_provider_choices()
def test_has_execution_provider() -> None:
assert has_execution_provider('CPUExecutionProvider') is True
assert has_execution_provider('InvalidExecutionProvider') is False
assert has_execution_provider('cpu') is True
assert has_execution_provider('openvino') is False
def test_multiple_execution_providers() -> None:
execution_provider_with_options =\
[
'CPUExecutionProvider',
('CUDAExecutionProvider',
{
'device_id': '1',
'cudnn_conv_algo_search': 'DEFAULT'
})
}),
'CPUExecutionProvider'
]
assert apply_execution_provider_options('1', [ 'CPUExecutionProvider', 'CUDAExecutionProvider' ]) == execution_provider_with_options
assert create_execution_providers('1', [ 'cpu', 'cuda' ]) == execution_provider_with_options

View File

@@ -1,103 +1,109 @@
import subprocess
import pytest
import facefusion.globals
from facefusion import face_classifier, face_detector, face_landmarker, face_recognizer, state_manager
from facefusion.download import conditional_download
from facefusion.face_analyser import pre_check, clear_face_analyser, get_one_face
from facefusion.face_analyser import get_many_faces, get_one_face
from facefusion.typing import Face
from facefusion.vision import read_static_image
from .helper import get_test_example_file, get_test_examples_directory
@pytest.fixture(scope = 'module', autouse = True)
def before_all() -> None:
conditional_download('.assets/examples',
conditional_download(get_test_examples_directory(),
[
'https://github.com/facefusion/facefusion-assets/releases/download/examples/source.jpg'
'https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/source.jpg'
])
subprocess.run([ 'ffmpeg', '-i', '.assets/examples/source.jpg', '-vf', 'crop=iw*0.8:ih*0.8', '.assets/examples/source-80crop.jpg' ])
subprocess.run([ 'ffmpeg', '-i', '.assets/examples/source.jpg', '-vf', 'crop=iw*0.7:ih*0.7', '.assets/examples/source-70crop.jpg' ])
subprocess.run([ 'ffmpeg', '-i', '.assets/examples/source.jpg', '-vf', 'crop=iw*0.6:ih*0.6', '.assets/examples/source-60crop.jpg' ])
subprocess.run([ 'ffmpeg', '-i', get_test_example_file('source.jpg'), '-vf', 'crop=iw*0.8:ih*0.8', get_test_example_file('source-80crop.jpg') ])
subprocess.run([ 'ffmpeg', '-i', get_test_example_file('source.jpg'), '-vf', 'crop=iw*0.7:ih*0.7', get_test_example_file('source-70crop.jpg') ])
subprocess.run([ 'ffmpeg', '-i', get_test_example_file('source.jpg'), '-vf', 'crop=iw*0.6:ih*0.6', get_test_example_file('source-60crop.jpg') ])
state_manager.init_item('execution_device_id', 0)
state_manager.init_item('execution_providers', [ 'cpu' ])
state_manager.init_item('face_detector_angles', [ 0 ])
state_manager.init_item('face_detector_model', 'many')
state_manager.init_item('face_detector_score', 0.5)
state_manager.init_item('face_landmarker_model', 'many')
state_manager.init_item('face_landmarker_score', 0.5)
face_classifier.pre_check()
face_landmarker.pre_check()
face_recognizer.pre_check()
@pytest.fixture(autouse = True)
def before_each() -> None:
facefusion.globals.face_detector_score = 0.5
facefusion.globals.face_landmarker_score = 0.5
facefusion.globals.face_recognizer_model = 'arcface_inswapper'
clear_face_analyser()
face_classifier.clear_inference_pool()
face_detector.clear_inference_pool()
face_landmarker.clear_inference_pool()
face_recognizer.clear_inference_pool()
def test_get_one_face_with_retinaface() -> None:
facefusion.globals.face_detector_model = 'retinaface'
facefusion.globals.face_detector_size = '320x320'
state_manager.init_item('face_detector_model', 'retinaface')
state_manager.init_item('face_detector_size', '320x320')
face_detector.pre_check()
pre_check()
source_paths =\
[
'.assets/examples/source.jpg',
'.assets/examples/source-80crop.jpg',
'.assets/examples/source-70crop.jpg',
'.assets/examples/source-60crop.jpg'
get_test_example_file('source.jpg'),
get_test_example_file('source-80crop.jpg'),
get_test_example_file('source-70crop.jpg'),
get_test_example_file('source-60crop.jpg')
]
for source_path in source_paths:
source_frame = read_static_image(source_path)
face = get_one_face(source_frame)
many_faces = get_many_faces([ source_frame ])
face = get_one_face(many_faces)
assert isinstance(face, Face)
def test_get_one_face_with_scrfd() -> None:
facefusion.globals.face_detector_model = 'scrfd'
facefusion.globals.face_detector_size = '640x640'
state_manager.init_item('face_detector_model', 'scrfd')
state_manager.init_item('face_detector_size', '640x640')
face_detector.pre_check()
pre_check()
source_paths =\
[
'.assets/examples/source.jpg',
'.assets/examples/source-80crop.jpg',
'.assets/examples/source-70crop.jpg',
'.assets/examples/source-60crop.jpg'
get_test_example_file('source.jpg'),
get_test_example_file('source-80crop.jpg'),
get_test_example_file('source-70crop.jpg'),
get_test_example_file('source-60crop.jpg')
]
for source_path in source_paths:
source_frame = read_static_image(source_path)
face = get_one_face(source_frame)
many_faces = get_many_faces([ source_frame ])
face = get_one_face(many_faces)
assert isinstance(face, Face)
def test_get_one_face_with_yoloface() -> None:
facefusion.globals.face_detector_model = 'yoloface'
facefusion.globals.face_detector_size = '640x640'
state_manager.init_item('face_detector_model', 'yoloface')
state_manager.init_item('face_detector_size', '640x640')
face_detector.pre_check()
pre_check()
source_paths =\
[
'.assets/examples/source.jpg',
'.assets/examples/source-80crop.jpg',
'.assets/examples/source-70crop.jpg',
'.assets/examples/source-60crop.jpg'
get_test_example_file('source.jpg'),
get_test_example_file('source-80crop.jpg'),
get_test_example_file('source-70crop.jpg'),
get_test_example_file('source-60crop.jpg')
]
for source_path in source_paths:
source_frame = read_static_image(source_path)
face = get_one_face(source_frame)
many_faces = get_many_faces([ source_frame ])
face = get_one_face(many_faces)
assert isinstance(face, Face)
def test_get_one_face_with_yunet() -> None:
facefusion.globals.face_detector_model = 'yunet'
facefusion.globals.face_detector_size = '640x640'
def test_get_many_faces() -> None:
source_path = get_test_example_file('source.jpg')
source_frame = read_static_image(source_path)
many_faces = get_many_faces([ source_frame, source_frame, source_frame ])
pre_check()
source_paths =\
[
'.assets/examples/source.jpg',
'.assets/examples/source-80crop.jpg',
'.assets/examples/source-70crop.jpg',
'.assets/examples/source-60crop.jpg'
]
for source_path in source_paths:
source_frame = read_static_image(source_path)
face = get_one_face(source_frame)
assert isinstance(face, Face)
assert isinstance(many_faces[0], Face)
assert isinstance(many_faces[1], Face)
assert isinstance(many_faces[2], Face)

View File

@@ -1,113 +1,127 @@
import glob
import subprocess
import pytest
import facefusion.globals
from facefusion import process_manager
from facefusion.filesystem import get_temp_directory_path, create_temp, clear_temp
from facefusion import process_manager, state_manager
from facefusion.download import conditional_download
from facefusion.ffmpeg import extract_frames, read_audio_buffer
from facefusion.ffmpeg import concat_video, extract_frames, read_audio_buffer
from facefusion.temp_helper import clear_temp_directory, create_temp_directory, get_temp_directory_path
from .helper import get_test_example_file, get_test_examples_directory, get_test_output_file, prepare_test_output_directory
@pytest.fixture(scope = 'module', autouse = True)
def before_all() -> None:
process_manager.start()
conditional_download('.assets/examples',
conditional_download(get_test_examples_directory(),
[
'https://github.com/facefusion/facefusion-assets/releases/download/examples/source.jpg',
'https://github.com/facefusion/facefusion-assets/releases/download/examples/source.mp3',
'https://github.com/facefusion/facefusion-assets/releases/download/examples/target-240p.mp4'
'https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/source.jpg',
'https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/source.mp3',
'https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/target-240p.mp4'
])
subprocess.run([ 'ffmpeg', '-i', '.assets/examples/source.mp3', '.assets/examples/source.wav' ])
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', get_test_example_file('source.mp3'), get_test_example_file('source.wav') ])
subprocess.run([ 'ffmpeg', '-i', get_test_example_file('target-240p.mp4'), '-vf', 'fps=25', get_test_example_file('target-240p-25fps.mp4') ])
subprocess.run([ 'ffmpeg', '-i', get_test_example_file('target-240p.mp4'), '-vf', 'fps=30', get_test_example_file('target-240p-30fps.mp4') ])
subprocess.run([ 'ffmpeg', '-i', get_test_example_file('target-240p.mp4'), '-vf', 'fps=60', get_test_example_file('target-240p-60fps.mp4') ])
state_manager.init_item('temp_frame_format', 'jpg')
state_manager.init_item('output_audio_encoder', 'aac')
@pytest.fixture(scope = 'function', autouse = True)
def before_each() -> None:
facefusion.globals.trim_frame_start = None
facefusion.globals.trim_frame_end = None
facefusion.globals.temp_frame_format = 'jpg'
state_manager.clear_item('trim_frame_start')
state_manager.clear_item('trim_frame_end')
prepare_test_output_directory()
def test_extract_frames() -> None:
target_paths =\
[
'.assets/examples/target-240p-25fps.mp4',
'.assets/examples/target-240p-30fps.mp4',
'.assets/examples/target-240p-60fps.mp4'
get_test_example_file('target-240p-25fps.mp4'),
get_test_example_file('target-240p-30fps.mp4'),
get_test_example_file('target-240p-60fps.mp4')
]
for target_path in target_paths:
temp_directory_path = get_temp_directory_path(target_path)
create_temp(target_path)
create_temp_directory(target_path)
assert extract_frames(target_path, '452x240', 30.0) is True
assert len(glob.glob1(temp_directory_path, '*.jpg')) == 324
clear_temp(target_path)
clear_temp_directory(target_path)
def test_extract_frames_with_trim_start() -> None:
facefusion.globals.trim_frame_start = 224
data_provider =\
state_manager.init_item('trim_frame_start', 224)
providers =\
[
('.assets/examples/target-240p-25fps.mp4', 55),
('.assets/examples/target-240p-30fps.mp4', 100),
('.assets/examples/target-240p-60fps.mp4', 212)
(get_test_example_file('target-240p-25fps.mp4'), 55),
(get_test_example_file('target-240p-30fps.mp4'), 100),
(get_test_example_file('target-240p-60fps.mp4'), 212)
]
for target_path, frame_total in data_provider:
for target_path, frame_total in providers:
temp_directory_path = get_temp_directory_path(target_path)
create_temp(target_path)
create_temp_directory(target_path)
assert extract_frames(target_path, '452x240', 30.0) is True
assert len(glob.glob1(temp_directory_path, '*.jpg')) == frame_total
clear_temp(target_path)
clear_temp_directory(target_path)
def test_extract_frames_with_trim_start_and_trim_end() -> None:
facefusion.globals.trim_frame_start = 124
facefusion.globals.trim_frame_end = 224
data_provider =\
state_manager.init_item('trim_frame_start', 124)
state_manager.init_item('trim_frame_end', 224)
providers =\
[
('.assets/examples/target-240p-25fps.mp4', 120),
('.assets/examples/target-240p-30fps.mp4', 100),
('.assets/examples/target-240p-60fps.mp4', 50)
(get_test_example_file('target-240p-25fps.mp4'), 120),
(get_test_example_file('target-240p-30fps.mp4'), 100),
(get_test_example_file('target-240p-60fps.mp4'), 50)
]
for target_path, frame_total in data_provider:
for target_path, frame_total in providers:
temp_directory_path = get_temp_directory_path(target_path)
create_temp(target_path)
create_temp_directory(target_path)
assert extract_frames(target_path, '452x240', 30.0) is True
assert len(glob.glob1(temp_directory_path, '*.jpg')) == frame_total
clear_temp(target_path)
clear_temp_directory(target_path)
def test_extract_frames_with_trim_end() -> None:
facefusion.globals.trim_frame_end = 100
data_provider =\
state_manager.init_item('trim_frame_end', 100)
providers =\
[
('.assets/examples/target-240p-25fps.mp4', 120),
('.assets/examples/target-240p-30fps.mp4', 100),
('.assets/examples/target-240p-60fps.mp4', 50)
(get_test_example_file('target-240p-25fps.mp4'), 120),
(get_test_example_file('target-240p-30fps.mp4'), 100),
(get_test_example_file('target-240p-60fps.mp4'), 50)
]
for target_path, frame_total in data_provider:
for target_path, frame_total in providers:
temp_directory_path = get_temp_directory_path(target_path)
create_temp(target_path)
create_temp_directory(target_path)
assert extract_frames(target_path, '426x240', 30.0) is True
assert len(glob.glob1(temp_directory_path, '*.jpg')) == frame_total
clear_temp(target_path)
clear_temp_directory(target_path)
def test_concat_video() -> None:
output_path = get_test_output_file('test-concat-video.mp4')
temp_output_paths =\
[
get_test_example_file('target-240p.mp4'),
get_test_example_file('target-240p.mp4')
]
assert concat_video(output_path, temp_output_paths) is True
def test_read_audio_buffer() -> None:
assert isinstance(read_audio_buffer('.assets/examples/source.mp3', 1, 1), bytes)
assert isinstance(read_audio_buffer('.assets/examples/source.wav', 1, 1), bytes)
assert read_audio_buffer('.assets/examples/invalid.mp3', 1, 1) is None
assert isinstance(read_audio_buffer(get_test_example_file('source.mp3'), 1, 1), bytes)
assert isinstance(read_audio_buffer(get_test_example_file('source.wav'), 1, 1), bytes)
assert read_audio_buffer(get_test_example_file('invalid.mp3'), 1, 1) is None

View File

@@ -1,91 +1,119 @@
import shutil
import os.path
import pytest
from facefusion.common_helper import is_windows
from facefusion.download import conditional_download
from facefusion.filesystem import get_file_size, is_file, is_directory, is_audio, has_audio, is_image, has_image, is_video, filter_audio_paths, filter_image_paths, list_directory, sanitize_path_for_windows
from facefusion.filesystem import copy_file, create_directory, filter_audio_paths, filter_image_paths, get_file_size, has_audio, has_image, in_directory, is_audio, is_directory, is_file, is_image, is_video, list_directory, remove_directory, same_file_extension, sanitize_path_for_windows
from .helper import get_test_example_file, get_test_examples_directory, get_test_outputs_directory
@pytest.fixture(scope = 'module', autouse = True)
def before_all() -> None:
conditional_download('.assets/examples',
conditional_download(get_test_examples_directory(),
[
'https://github.com/facefusion/facefusion-assets/releases/download/examples/source.jpg',
'https://github.com/facefusion/facefusion-assets/releases/download/examples/source.mp3',
'https://github.com/facefusion/facefusion-assets/releases/download/examples/target-240p.mp4'
'https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/source.jpg',
'https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/source.mp3',
'https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/target-240p.mp4'
])
shutil.copyfile('.assets/examples/source.jpg', '.assets/examples/söurce.jpg')
copy_file(get_test_example_file('source.jpg'), get_test_example_file('söurce.jpg'))
def test_get_file_size() -> None:
assert get_file_size('.assets/examples/source.jpg') > 0
assert get_file_size(get_test_example_file('source.jpg')) > 0
assert get_file_size('invalid') == 0
def test_same_file_extension() -> None:
assert same_file_extension([ 'target.jpg', 'output.jpg' ]) is True
assert same_file_extension([ 'target.jpg', 'output.mp4' ]) is False
def test_is_file() -> None:
assert is_file('.assets/examples/source.jpg') is True
assert is_file('.assets/examples') is False
assert is_file(get_test_example_file('source.jpg')) is True
assert is_file(get_test_examples_directory()) is False
assert is_file('invalid') is False
def test_is_directory() -> None:
assert is_directory('.assets/examples') is True
assert is_directory('.assets/examples/source.jpg') is False
assert is_directory(get_test_examples_directory()) is True
assert is_directory(get_test_example_file('source.jpg')) is False
assert is_directory('invalid') is False
def test_in_directory() -> None:
assert in_directory(get_test_example_file('source.jpg')) is True
assert in_directory('source.jpg') is False
assert in_directory('invalid') is False
def test_is_audio() -> None:
assert is_audio('.assets/examples/source.mp3') is True
assert is_audio('.assets/examples/source.jpg') is False
assert is_audio(get_test_example_file('source.mp3')) is True
assert is_audio(get_test_example_file('source.jpg')) is False
assert is_audio('invalid') is False
def test_has_audio() -> None:
assert has_audio([ '.assets/examples/source.mp3' ]) is True
assert has_audio([ '.assets/examples/source.mp3', '.assets/examples/source.jpg' ]) is True
assert has_audio([ '.assets/examples/source.jpg', '.assets/examples/source.jpg' ]) is False
assert has_audio([ get_test_example_file('source.mp3') ]) is True
assert has_audio([ get_test_example_file('source.mp3'), get_test_example_file('source.jpg') ]) is True
assert has_audio([ get_test_example_file('source.jpg'), get_test_example_file('source.jpg') ]) is False
assert has_audio([ 'invalid' ]) is False
def test_is_image() -> None:
assert is_image('.assets/examples/source.jpg') is True
assert is_image('.assets/examples/target-240p.mp4') is False
assert is_image(get_test_example_file('source.jpg')) is True
assert is_image(get_test_example_file('target-240p.mp4')) is False
assert is_image('invalid') is False
def test_has_image() -> None:
assert has_image([ '.assets/examples/source.jpg' ]) is True
assert has_image([ '.assets/examples/source.jpg', '.assets/examples/source.mp3' ]) is True
assert has_image([ '.assets/examples/source.mp3', '.assets/examples/source.mp3' ]) is False
assert has_image([ get_test_example_file('source.jpg') ]) is True
assert has_image([ get_test_example_file('source.jpg'), get_test_example_file('source.mp3') ]) is True
assert has_image([ get_test_example_file('source.mp3'), get_test_example_file('source.mp3') ]) is False
assert has_image([ 'invalid' ]) is False
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(get_test_example_file('target-240p.mp4')) is True
assert is_video(get_test_example_file('source.jpg')) is False
assert is_video('invalid') is False
def test_filter_audio_paths() -> None:
assert filter_audio_paths([ '.assets/examples/source.jpg', '.assets/examples/source.mp3' ]) == [ '.assets/examples/source.mp3' ]
assert filter_audio_paths([ '.assets/examples/source.jpg', '.assets/examples/source.jpg' ]) == []
assert filter_audio_paths([ get_test_example_file('source.jpg'), get_test_example_file('source.mp3') ]) == [ get_test_example_file('source.mp3') ]
assert filter_audio_paths([ get_test_example_file('source.jpg'), get_test_example_file('source.jpg') ]) == []
assert filter_audio_paths([ 'invalid' ]) == []
def test_filter_image_paths() -> None:
assert filter_image_paths([ '.assets/examples/source.jpg', '.assets/examples/source.mp3' ]) == [ '.assets/examples/source.jpg' ]
assert filter_image_paths([ '.assets/examples/source.mp3', '.assets/examples/source.mp3' ]) == []
assert filter_image_paths([ get_test_example_file('source.jpg'), get_test_example_file('source.mp3') ]) == [ get_test_example_file('source.jpg') ]
assert filter_image_paths([ get_test_example_file('source.mp3'), get_test_example_file('source.mp3') ]) == []
assert filter_audio_paths([ 'invalid' ]) == []
def test_sanitize_path_for_windows() -> None:
if is_windows():
assert sanitize_path_for_windows(get_test_example_file('söurce.jpg')).endswith('SURCE~1.JPG')
assert sanitize_path_for_windows('invalid') is None
def test_create_directory() -> None:
create_directory_path = os.path.join(get_test_outputs_directory(), 'create_directory')
assert create_directory(create_directory_path) is True
assert create_directory(get_test_example_file('source.jpg')) is False
def test_list_directory() -> None:
assert list_directory('.assets/examples')
assert list_directory('.assets/examples/source.jpg') is None
assert list_directory(get_test_examples_directory())
assert list_directory(get_test_example_file('source.jpg')) is None
assert list_directory('invalid') is None
@pytest.mark.skip()
def test_sanitize_path_for_windows() -> None:
if is_windows():
assert sanitize_path_for_windows('.assets/examples/söurce.jpg') == 'ASSETS~1/examples/SURCE~1.JPG'
assert sanitize_path_for_windows('invalid') is None
def test_remove_directory() -> None:
remove_directory_path = os.path.join(get_test_outputs_directory(), 'remove_directory')
create_directory(remove_directory_path)
assert remove_directory(remove_directory_path) is True
assert remove_directory(get_test_example_file('source.jpg')) is False
assert remove_directory('invalid') is False

View File

@@ -0,0 +1,29 @@
from unittest.mock import patch
import pytest
from onnxruntime import InferenceSession
from facefusion import content_analyser, state_manager
from facefusion.inference_manager import INFERENCE_POOLS, get_inference_pool
@pytest.fixture(scope = 'module', autouse = True)
def before_all() -> None:
content_analyser.pre_check()
state_manager.init_item('execution_device_id', 0)
state_manager.init_item('execution_providers', [ 'cpu' ])
def test_get_inference_pool() -> None:
model_sources = content_analyser.get_model_options().get('sources')
with patch('facefusion.inference_manager.detect_app_context', return_value = 'cli'):
get_inference_pool('test', model_sources)
assert isinstance(INFERENCE_POOLS.get('cli').get('test.cpu').get('content_analyser'), InferenceSession)
with patch('facefusion.inference_manager.detect_app_context', return_value = 'ui'):
get_inference_pool('test', model_sources)
assert isinstance(INFERENCE_POOLS.get('ui').get('test.cpu').get('content_analyser'), InferenceSession)

8
tests/test_job_helper.py Normal file
View File

@@ -0,0 +1,8 @@
import os
from facefusion.jobs.job_helper import get_step_output_path
def test_get_step_output_path() -> None:
assert get_step_output_path('test-job', 0, 'test.mp4') == 'test-test-job-0.mp4'
assert get_step_output_path('test-job', 0, 'test/test.mp4') == os.path.join('test', 'test-test-job-0.mp4')

24
tests/test_job_list.py Normal file
View File

@@ -0,0 +1,24 @@
from time import sleep
import pytest
from facefusion.jobs.job_list import compose_job_list
from facefusion.jobs.job_manager import clear_jobs, create_job, init_jobs
from .helper import get_test_jobs_directory
@pytest.fixture(scope = 'function', autouse = True)
def before_each() -> None:
clear_jobs(get_test_jobs_directory())
init_jobs(get_test_jobs_directory())
def test_compose_job_list() -> None:
create_job('job-test-compose-job-list-1')
sleep(0.5)
create_job('job-test-compose-job-list-2')
job_headers, job_contents = compose_job_list('drafted')
assert job_headers == [ 'job id', 'steps', 'date created', 'date updated', 'job status' ]
assert job_contents[0] == [ 'job-test-compose-job-list-1', 0, 'just now', None, 'drafted' ]
assert job_contents[1] == [ 'job-test-compose-job-list-2', 0, 'just now', None, 'drafted' ]

373
tests/test_job_manager.py Normal file
View File

@@ -0,0 +1,373 @@
from time import sleep
import pytest
from facefusion.jobs.job_helper import get_step_output_path
from facefusion.jobs.job_manager import add_step, clear_jobs, count_step_total, create_job, delete_job, delete_jobs, find_job_ids, get_steps, init_jobs, insert_step, move_job_file, remix_step, remove_step, set_step_status, set_steps_status, submit_job, submit_jobs
from .helper import get_test_jobs_directory
@pytest.fixture(scope = 'function', autouse = True)
def before_each() -> None:
clear_jobs(get_test_jobs_directory())
init_jobs(get_test_jobs_directory())
def test_create_job() -> None:
args_1 =\
{
'source_path': 'source-1.jpg',
'target_path': 'target-1.jpg',
'output_path': 'output-1.jpg'
}
assert create_job('job-test-create-job') is True
assert create_job('job-test-create-job') is False
add_step('job-test-submit-job', args_1)
submit_job('job-test-create-job')
assert create_job('job-test-create-job') is False
def test_submit_job() -> None:
args_1 =\
{
'source_path': 'source-1.jpg',
'target_path': 'target-1.jpg',
'output_path': 'output-1.jpg'
}
assert submit_job('job-invalid') is False
create_job('job-test-submit-job')
assert submit_job('job-test-submit-job') is False
add_step('job-test-submit-job', args_1)
assert submit_job('job-test-submit-job') is True
assert submit_job('job-test-submit-job') is False
def test_submit_jobs() -> None:
args_1 =\
{
'source_path': 'source-1.jpg',
'target_path': 'target-1.jpg',
'output_path': 'output-1.jpg'
}
args_2 =\
{
'source_path': 'source-2.jpg',
'target_path': 'target-2.jpg',
'output_path': 'output-2.jpg'
}
assert submit_jobs() is False
create_job('job-test-submit-jobs-1')
create_job('job-test-submit-jobs-2')
assert submit_jobs() is False
add_step('job-test-submit-jobs-1', args_1)
add_step('job-test-submit-jobs-2', args_2)
assert submit_jobs() is True
assert submit_jobs() is False
def test_delete_job() -> None:
assert delete_job('job-invalid') is False
create_job('job-test-delete-job')
assert delete_job('job-test-delete-job') is True
assert delete_job('job-test-delete-job') is False
def test_delete_jobs() -> None:
assert delete_jobs() is False
create_job('job-test-delete-jobs-1')
create_job('job-test-delete-jobs-2')
assert delete_jobs() is True
@pytest.mark.skip()
def test_find_jobs() -> None:
pass
def test_find_job_ids() -> None:
create_job('job-test-find-job-ids-1')
sleep(0.5)
create_job('job-test-find-job-ids-2')
sleep(0.5)
create_job('job-test-find-job-ids-3')
assert find_job_ids('drafted') == [ 'job-test-find-job-ids-1', 'job-test-find-job-ids-2', 'job-test-find-job-ids-3' ]
assert find_job_ids('queued') == []
assert find_job_ids('completed') == []
assert find_job_ids('failed') == []
move_job_file('job-test-find-job-ids-1', 'queued')
move_job_file('job-test-find-job-ids-2', 'queued')
move_job_file('job-test-find-job-ids-3', 'queued')
assert find_job_ids('drafted') == []
assert find_job_ids('queued') == [ 'job-test-find-job-ids-1', 'job-test-find-job-ids-2', 'job-test-find-job-ids-3' ]
assert find_job_ids('completed') == []
assert find_job_ids('failed') == []
move_job_file('job-test-find-job-ids-1', 'completed')
assert find_job_ids('drafted') == []
assert find_job_ids('queued') == [ 'job-test-find-job-ids-2', 'job-test-find-job-ids-3' ]
assert find_job_ids('completed') == [ 'job-test-find-job-ids-1' ]
assert find_job_ids('failed') == []
move_job_file('job-test-find-job-ids-2', 'failed')
assert find_job_ids('drafted') == []
assert find_job_ids('queued') == [ 'job-test-find-job-ids-3' ]
assert find_job_ids('completed') == [ 'job-test-find-job-ids-1' ]
assert find_job_ids('failed') == [ 'job-test-find-job-ids-2' ]
move_job_file('job-test-find-job-ids-3', 'completed')
assert find_job_ids('drafted') == []
assert find_job_ids('queued') == []
assert find_job_ids('completed') == [ 'job-test-find-job-ids-1', 'job-test-find-job-ids-3' ]
assert find_job_ids('failed') == [ 'job-test-find-job-ids-2' ]
def test_add_step() -> None:
args_1 =\
{
'source_path': 'source-1.jpg',
'target_path': 'target-1.jpg',
'output_path': 'output-1.jpg'
}
args_2 =\
{
'source_path': 'source-2.jpg',
'target_path': 'target-2.jpg',
'output_path': 'output-2.jpg'
}
assert add_step('job-invalid', args_1) is False
create_job('job-test-add-step')
assert add_step('job-test-add-step', args_1) is True
assert add_step('job-test-add-step', args_2) is True
steps = get_steps('job-test-add-step')
assert steps[0].get('args') == args_1
assert steps[1].get('args') == args_2
assert count_step_total('job-test-add-step') == 2
def test_remix_step() -> None:
args_1 =\
{
'source_path': 'source-1.jpg',
'target_path': 'target-1.jpg',
'output_path': 'output-1.jpg'
}
args_2 =\
{
'source_path': 'source-2.jpg',
'target_path': 'target-2.jpg',
'output_path': 'output-2.jpg'
}
assert remix_step('job-invalid', 0, args_1) is False
create_job('job-test-remix-step')
add_step('job-test-remix-step', args_1)
add_step('job-test-remix-step', args_2)
assert remix_step('job-test-remix-step', 99, args_1) is False
assert remix_step('job-test-remix-step', 0, args_2) is True
assert remix_step('job-test-remix-step', -1, args_2) is True
steps = get_steps('job-test-remix-step')
assert steps[0].get('args') == args_1
assert steps[1].get('args') == args_2
assert steps[2].get('args').get('source_path') == args_2.get('source_path')
assert steps[2].get('args').get('target_path') == get_step_output_path('job-test-remix-step', 0, args_1.get('output_path'))
assert steps[2].get('args').get('output_path') == args_2.get('output_path')
assert steps[3].get('args').get('source_path') == args_2.get('source_path')
assert steps[3].get('args').get('target_path') == get_step_output_path('job-test-remix-step', 2, args_2.get('output_path'))
assert steps[3].get('args').get('output_path') == args_2.get('output_path')
assert count_step_total('job-test-remix-step') == 4
def test_insert_step() -> None:
args_1 =\
{
'source_path': 'source-1.jpg',
'target_path': 'target-1.jpg',
'output_path': 'output-1.jpg'
}
args_2 =\
{
'source_path': 'source-2.jpg',
'target_path': 'target-2.jpg',
'output_path': 'output-2.jpg'
}
args_3 =\
{
'source_path': 'source-3.jpg',
'target_path': 'target-3.jpg',
'output_path': 'output-3.jpg'
}
assert insert_step('job-invalid', 0, args_1) is False
create_job('job-test-insert-step')
add_step('job-test-insert-step', args_1)
add_step('job-test-insert-step', args_1)
assert insert_step('job-test-insert-step', 99, args_1) is False
assert insert_step('job-test-insert-step', 0, args_2) is True
assert insert_step('job-test-insert-step', -1, args_3) is True
steps = get_steps('job-test-insert-step')
assert steps[0].get('args') == args_2
assert steps[1].get('args') == args_1
assert steps[2].get('args') == args_3
assert steps[3].get('args') == args_1
assert count_step_total('job-test-insert-step') == 4
def test_remove_step() -> None:
args_1 =\
{
'source_path': 'source-1.jpg',
'target_path': 'target-1.jpg',
'output_path': 'output-1.jpg'
}
args_2 =\
{
'source_path': 'source-2.jpg',
'target_path': 'target-2.jpg',
'output_path': 'output-2.jpg'
}
args_3 =\
{
'source_path': 'source-3.jpg',
'target_path': 'target-3.jpg',
'output_path': 'output-3.jpg'
}
assert remove_step('job-invalid', 0) is False
create_job('job-test-remove-step')
add_step('job-test-remove-step', args_1)
add_step('job-test-remove-step', args_2)
add_step('job-test-remove-step', args_1)
add_step('job-test-remove-step', args_3)
assert remove_step('job-test-remove-step', 99) is False
assert remove_step('job-test-remove-step', 0) is True
assert remove_step('job-test-remove-step', -1) is True
steps = get_steps('job-test-remove-step')
assert steps[0].get('args') == args_2
assert steps[1].get('args') == args_1
assert count_step_total('job-test-remove-step') == 2
def test_get_steps() -> None:
args_1 =\
{
'source_path': 'source-1.jpg',
'target_path': 'target-1.jpg',
'output_path': 'output-1.jpg'
}
args_2 =\
{
'source_path': 'source-2.jpg',
'target_path': 'target-2.jpg',
'output_path': 'output-2.jpg'
}
assert get_steps('job-invalid') == []
create_job('job-test-get-steps')
add_step('job-test-get-steps', args_1)
add_step('job-test-get-steps', args_2)
steps = get_steps('job-test-get-steps')
assert steps[0].get('args') == args_1
assert steps[1].get('args') == args_2
assert count_step_total('job-test-get-steps') == 2
def test_set_step_status() -> None:
args_1 =\
{
'source_path': 'source-1.jpg',
'target_path': 'target-1.jpg',
'output_path': 'output-1.jpg'
}
args_2 =\
{
'source_path': 'source-2.jpg',
'target_path': 'target-2.jpg',
'output_path': 'output-2.jpg'
}
assert set_step_status('job-invalid', 0, 'completed') is False
create_job('job-test-set-step-status')
add_step('job-test-set-step-status', args_1)
add_step('job-test-set-step-status', args_2)
assert set_step_status('job-test-set-step-status', 99, 'completed') is False
assert set_step_status('job-test-set-step-status', 0, 'completed') is True
assert set_step_status('job-test-set-step-status', 1, 'failed') is True
steps = get_steps('job-test-set-step-status')
assert steps[0].get('status') == 'completed'
assert steps[1].get('status') == 'failed'
assert count_step_total('job-test-set-step-status') == 2
def test_set_steps_status() -> None:
args_1 =\
{
'source_path': 'source-1.jpg',
'target_path': 'target-1.jpg',
'output_path': 'output-1.jpg'
}
args_2 =\
{
'source_path': 'source-2.jpg',
'target_path': 'target-2.jpg',
'output_path': 'output-2.jpg'
}
assert set_steps_status('job-invalid', 'queued') is False
create_job('job-test-set-steps-status')
add_step('job-test-set-steps-status', args_1)
add_step('job-test-set-steps-status', args_2)
assert set_steps_status('job-test-set-steps-status', 'queued') is True
steps = get_steps('job-test-set-steps-status')
assert steps[0].get('status') == 'queued'
assert steps[1].get('status') == 'queued'
assert count_step_total('job-test-set-steps-status') == 2

228
tests/test_job_runner.py Normal file
View File

@@ -0,0 +1,228 @@
import subprocess
import pytest
from facefusion import state_manager
from facefusion.download import conditional_download
from facefusion.filesystem import copy_file
from facefusion.jobs.job_manager import add_step, clear_jobs, create_job, init_jobs, submit_job, submit_jobs
from facefusion.jobs.job_runner import collect_output_set, finalize_steps, run_job, run_jobs, run_steps
from facefusion.typing import Args
from .helper import get_test_example_file, get_test_examples_directory, get_test_jobs_directory, get_test_output_file, is_test_output_file, prepare_test_output_directory
@pytest.fixture(scope = 'module', autouse = True)
def before_all() -> None:
conditional_download(get_test_examples_directory(),
[
'https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/source.jpg',
'https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/target-240p.mp4'
])
subprocess.run([ 'ffmpeg', '-i', get_test_example_file('target-240p.mp4'), '-vframes', '1', get_test_example_file('target-240p.jpg') ])
state_manager.init_item('output_audio_encoder', 'aac')
@pytest.fixture(scope = 'function', autouse = True)
def before_each() -> None:
clear_jobs(get_test_jobs_directory())
init_jobs(get_test_jobs_directory())
prepare_test_output_directory()
def process_step(job_id : str, step_index : int, step_args : Args) -> bool:
return copy_file(step_args.get('target_path'), step_args.get('output_path'))
def test_run_job() -> None:
args_1 =\
{
'source_path': get_test_example_file('source.jpg'),
'target_path': get_test_example_file('target-240p.mp4'),
'output_path': get_test_output_file('output-1.mp4')
}
args_2 =\
{
'source_path': get_test_example_file('source.jpg'),
'target_path': get_test_example_file('target-240p.mp4'),
'output_path': get_test_output_file('output-2.mp4')
}
args_3 =\
{
'source_path': get_test_example_file('source.jpg'),
'target_path': get_test_example_file('target-240p.jpg'),
'output_path': get_test_output_file('output-1.jpg')
}
assert run_job('job-invalid', process_step) is False
create_job('job-test-run-job')
add_step('job-test-run-job', args_1)
add_step('job-test-run-job', args_2)
add_step('job-test-run-job', args_2)
add_step('job-test-run-job', args_3)
assert run_job('job-test-run-job', process_step) is False
submit_job('job-test-run-job')
assert run_job('job-test-run-job', process_step) is True
def test_run_jobs() -> None:
args_1 =\
{
'source_path': get_test_example_file('source.jpg'),
'target_path': get_test_example_file('target-240p.mp4'),
'output_path': get_test_output_file('output-1.mp4')
}
args_2 =\
{
'source_path': get_test_example_file('source.jpg'),
'target_path': get_test_example_file('target-240p.mp4'),
'output_path': get_test_output_file('output-2.mp4')
}
args_3 =\
{
'source_path': get_test_example_file('source.jpg'),
'target_path': get_test_example_file('target-240p.jpg'),
'output_path': get_test_output_file('output-1.jpg')
}
assert run_jobs(process_step) is False
create_job('job-test-run-jobs-1')
create_job('job-test-run-jobs-2')
add_step('job-test-run-jobs-1', args_1)
add_step('job-test-run-jobs-1', args_1)
add_step('job-test-run-jobs-2', args_2)
add_step('job-test-run-jobs-3', args_3)
assert run_jobs(process_step) is False
submit_jobs()
assert run_jobs(process_step) is True
@pytest.mark.skip()
def test_retry_job() -> None:
pass
@pytest.mark.skip()
def test_retry_jobs() -> None:
pass
def test_run_steps() -> None:
args_1 =\
{
'source_path': get_test_example_file('source.jpg'),
'target_path': get_test_example_file('target-240p.mp4'),
'output_path': get_test_output_file('output-1.mp4')
}
args_2 =\
{
'source_path': get_test_example_file('source.jpg'),
'target_path': get_test_example_file('target-240p.mp4'),
'output_path': get_test_output_file('output-2.mp4')
}
args_3 =\
{
'source_path': get_test_example_file('source.jpg'),
'target_path': get_test_example_file('target-240p.jpg'),
'output_path': get_test_output_file('output-1.jpg')
}
assert run_steps('job-invalid', process_step) is False
create_job('job-test-run-steps')
add_step('job-test-run-steps', args_1)
add_step('job-test-run-steps', args_1)
add_step('job-test-run-steps', args_2)
add_step('job-test-run-steps', args_3)
assert run_steps('job-test-run-steps', process_step) is True
def test_finalize_steps() -> None:
args_1 =\
{
'source_path': get_test_example_file('source.jpg'),
'target_path': get_test_example_file('target-240p.mp4'),
'output_path': get_test_output_file('output-1.mp4')
}
args_2 =\
{
'source_path': get_test_example_file('source.jpg'),
'target_path': get_test_example_file('target-240p.mp4'),
'output_path': get_test_output_file('output-2.mp4')
}
args_3 =\
{
'source_path': get_test_example_file('source.jpg'),
'target_path': get_test_example_file('target-240p.jpg'),
'output_path': get_test_output_file('output-1.jpg')
}
create_job('job-test-finalize-steps')
add_step('job-test-finalize-steps', args_1)
add_step('job-test-finalize-steps', args_1)
add_step('job-test-finalize-steps', args_2)
add_step('job-test-finalize-steps', args_3)
copy_file(args_1.get('target_path'), get_test_output_file('output-1-job-test-finalize-steps-0.mp4'))
copy_file(args_1.get('target_path'), get_test_output_file('output-1-job-test-finalize-steps-1.mp4'))
copy_file(args_2.get('target_path'), get_test_output_file('output-2-job-test-finalize-steps-2.mp4'))
copy_file(args_3.get('target_path'), get_test_output_file('output-1-job-test-finalize-steps-3.jpg'))
assert finalize_steps('job-test-finalize-steps') is True
assert is_test_output_file('output-1.mp4') is True
assert is_test_output_file('output-2.mp4') is True
assert is_test_output_file('output-1.jpg') is True
def test_collect_output_set() -> None:
args_1 =\
{
'source_path': get_test_example_file('source.jpg'),
'target_path': get_test_example_file('target-240p.mp4'),
'output_path': get_test_output_file('output-1.mp4')
}
args_2 =\
{
'source_path': get_test_example_file('source.jpg'),
'target_path': get_test_example_file('target-240p.mp4'),
'output_path': get_test_output_file('output-2.mp4')
}
args_3 =\
{
'source_path': get_test_example_file('source.jpg'),
'target_path': get_test_example_file('target-240p.jpg'),
'output_path': get_test_output_file('output-1.jpg')
}
create_job('job-test-collect-output-set')
add_step('job-test-collect-output-set', args_1)
add_step('job-test-collect-output-set', args_1)
add_step('job-test-collect-output-set', args_2)
add_step('job-test-collect-output-set', args_3)
output_set =\
{
get_test_output_file('output-1.mp4'):
[
get_test_output_file('output-1-job-test-collect-output-set-0.mp4'),
get_test_output_file('output-1-job-test-collect-output-set-1.mp4')
],
get_test_output_file('output-2.mp4'):
[
get_test_output_file('output-2-job-test-collect-output-set-2.mp4')
],
get_test_output_file('output-1.jpg'):
[
get_test_output_file('output-1-job-test-collect-output-set-3.jpg')
]
}
assert collect_output_set('job-test-collect-output-set') == output_set

19
tests/test_json.py Normal file
View File

@@ -0,0 +1,19 @@
import tempfile
from facefusion.json import read_json, write_json
def test_read_json() -> None:
_, json_path = tempfile.mkstemp(suffix = '.json')
assert not read_json(json_path)
write_json(json_path, {})
assert read_json(json_path) == {}
def test_write_json() -> None:
_, json_path = tempfile.mkstemp(suffix = '.json')
assert write_json(json_path, {})

View File

@@ -1,18 +1,4 @@
from facefusion.common_helper import is_linux, is_macos
from facefusion.normalizer import normalize_output_path, normalize_padding, normalize_fps
def test_normalize_output_path() -> None:
if is_linux() or is_macos():
assert normalize_output_path('.assets/examples/target-240p.mp4', '.assets/examples/target-240p.mp4') == '.assets/examples/target-240p.mp4'
assert normalize_output_path('.assets/examples/target-240p.mp4', '.assets/examples').startswith('.assets/examples/target-240p')
assert normalize_output_path('.assets/examples/target-240p.mp4', '.assets/examples').endswith('.mp4')
assert normalize_output_path('.assets/examples/target-240p.mp4', '.assets/examples/output.mp4') == '.assets/examples/output.mp4'
assert normalize_output_path('.assets/examples/target-240p.mp4', '.assets/examples/invalid') is None
assert normalize_output_path('.assets/examples/target-240p.mp4', '.assets/invalid/output.mp4') is None
assert normalize_output_path('.assets/examples/target-240p.mp4', 'invalid') is None
assert normalize_output_path('.assets/examples/target-240p.mp4', None) is None
assert normalize_output_path(None, '.assets/examples/output.mp4') is None
from facefusion.normalizer import normalize_fps, normalize_padding
def test_normalize_padding() -> None:

View File

@@ -1,4 +1,4 @@
from facefusion.process_manager import set_process_state, is_processing, is_stopping, is_pending, start, stop, end
from facefusion.process_manager import end, is_pending, is_processing, is_stopping, set_process_state, start, stop
def test_start() -> None:

View File

@@ -0,0 +1,40 @@
from argparse import ArgumentParser
import pytest
from facefusion.program_helper import find_argument_group, validate_actions
def test_find_argument_group() -> None:
program = ArgumentParser()
program.add_argument_group('test-1')
program.add_argument_group('test-2')
assert find_argument_group(program, 'test-1')
assert find_argument_group(program, 'test-2')
assert find_argument_group(program, 'invalid') is None
@pytest.mark.skip()
def test_validate_args() -> None:
pass
def test_validate_actions() -> None:
program = ArgumentParser()
program.add_argument('--test-1', default = 'test_1', choices = [ 'test_1', 'test_2' ])
program.add_argument('--test-2', default = 'test_2', choices= [ 'test_1', 'test_2' ], nargs = '+')
assert validate_actions(program) is True
args =\
{
'test_1': 'test_2',
'test_2': [ 'test_1', 'test_3' ]
}
for action in program._actions:
if action.dest in args:
action.default = args[action.dest]
assert validate_actions(program) is False

33
tests/test_temp_helper.py Normal file
View File

@@ -0,0 +1,33 @@
import os.path
import tempfile
import pytest
from facefusion import state_manager
from facefusion.download import conditional_download
from facefusion.temp_helper import get_temp_directory_path, get_temp_file_path, get_temp_frames_pattern
from .helper import get_test_example_file, get_test_examples_directory
@pytest.fixture(scope = 'module', autouse = True)
def before_all() -> None:
conditional_download(get_test_examples_directory(),
[
'https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/target-240p.mp4'
])
state_manager.init_item('temp_frame_format', 'png')
def test_get_temp_file_path() -> None:
temp_directory = tempfile.gettempdir()
assert get_temp_file_path(get_test_example_file('target-240p.mp4')) == os.path.join(temp_directory, 'facefusion', 'target-240p', 'temp.mp4')
def test_get_temp_directory_path() -> None:
temp_directory = tempfile.gettempdir()
assert get_temp_directory_path(get_test_example_file('target-240p.mp4')) == os.path.join(temp_directory, 'facefusion', 'target-240p')
def test_get_temp_frames_pattern() -> None:
temp_directory = tempfile.gettempdir()
assert get_temp_frames_pattern(get_test_example_file('target-240p.mp4'), '%04d') == os.path.join(temp_directory, 'facefusion', 'target-240p', '%04d.png')

View File

@@ -1,41 +1,43 @@
import subprocess
import pytest
from facefusion.download import conditional_download
from facefusion.vision import detect_image_resolution, restrict_image_resolution, create_image_resolutions, get_video_frame, count_video_frame_total, detect_video_fps, restrict_video_fps, detect_video_resolution, restrict_video_resolution, create_video_resolutions, normalize_resolution, pack_resolution, unpack_resolution
from facefusion.vision import count_video_frame_total, create_image_resolutions, create_video_resolutions, detect_image_resolution, detect_video_fps, detect_video_resolution, get_video_frame, normalize_resolution, pack_resolution, restrict_image_resolution, restrict_video_fps, restrict_video_resolution, unpack_resolution
from .helper import get_test_example_file, get_test_examples_directory
@pytest.fixture(scope = 'module', autouse = True)
def before_all() -> None:
conditional_download('.assets/examples',
conditional_download(get_test_examples_directory(),
[
'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-1080p.mp4'
'https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/source.jpg',
'https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/target-240p.mp4',
'https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/target-1080p.mp4'
])
subprocess.run([ 'ffmpeg', '-i', '.assets/examples/target-240p.mp4', '-vframes', '1', '.assets/examples/target-240p.jpg' ])
subprocess.run([ 'ffmpeg', '-i', '.assets/examples/target-1080p.mp4', '-vframes', '1', '.assets/examples/target-1080p.jpg' ])
subprocess.run([ 'ffmpeg', '-i', '.assets/examples/target-240p.mp4', '-vframes', '1', '-vf', 'transpose=0', '.assets/examples/target-240p-90deg.jpg' ])
subprocess.run([ 'ffmpeg', '-i', '.assets/examples/target-1080p.mp4', '-vframes', '1', '-vf', 'transpose=0', '.assets/examples/target-1080p-90deg.jpg' ])
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' ])
subprocess.run([ 'ffmpeg', '-i', get_test_example_file('target-240p.mp4'), '-vframes', '1', get_test_example_file('target-240p.jpg') ])
subprocess.run([ 'ffmpeg', '-i', get_test_example_file('target-1080p.mp4'), '-vframes', '1', get_test_example_file('target-1080p.jpg') ])
subprocess.run([ 'ffmpeg', '-i', get_test_example_file('target-240p.mp4'), '-vframes', '1', '-vf', 'transpose=0', get_test_example_file('target-240p-90deg.jpg') ])
subprocess.run([ 'ffmpeg', '-i', get_test_example_file('target-1080p.mp4'), '-vframes', '1', '-vf', 'transpose=0', get_test_example_file('target-1080p-90deg.jpg') ])
subprocess.run([ 'ffmpeg', '-i', get_test_example_file('target-240p.mp4'), '-vf', 'fps=25', get_test_example_file('target-240p-25fps.mp4') ])
subprocess.run([ 'ffmpeg', '-i', get_test_example_file('target-240p.mp4'), '-vf', 'fps=30', get_test_example_file('target-240p-30fps.mp4') ])
subprocess.run([ 'ffmpeg', '-i', get_test_example_file('target-240p.mp4'), '-vf', 'fps=60', get_test_example_file('target-240p-60fps.mp4') ])
subprocess.run([ 'ffmpeg', '-i', get_test_example_file('target-240p.mp4'), '-vf', 'transpose=0', get_test_example_file('target-240p-90deg.mp4') ])
subprocess.run([ 'ffmpeg', '-i', get_test_example_file('target-1080p.mp4'), '-vf', 'transpose=0', get_test_example_file('target-1080p-90deg.mp4') ])
def test_detect_image_resolution() -> None:
assert detect_image_resolution('.assets/examples/target-240p.jpg') == (426, 226)
assert detect_image_resolution('.assets/examples/target-240p-90deg.jpg') == (226, 426)
assert detect_image_resolution('.assets/examples/target-1080p.jpg') == (2048, 1080)
assert detect_image_resolution('.assets/examples/target-1080p-90deg.jpg') == (1080, 2048)
assert detect_image_resolution(get_test_example_file('target-240p.jpg')) == (426, 226)
assert detect_image_resolution(get_test_example_file('target-240p-90deg.jpg')) == (226, 426)
assert detect_image_resolution(get_test_example_file('target-1080p.jpg')) == (2048, 1080)
assert detect_image_resolution(get_test_example_file('target-1080p-90deg.jpg')) == (1080, 2048)
assert detect_image_resolution('invalid') is None
def test_restrict_image_resolution() -> None:
assert restrict_image_resolution('.assets/examples/target-1080p.jpg', (426, 226)) == (426, 226)
assert restrict_image_resolution('.assets/examples/target-1080p.jpg', (2048, 1080)) == (2048, 1080)
assert restrict_image_resolution('.assets/examples/target-1080p.jpg', (4096, 2160)) == (2048, 1080)
assert restrict_image_resolution(get_test_example_file('target-1080p.jpg'), (426, 226)) == (426, 226)
assert restrict_image_resolution(get_test_example_file('target-1080p.jpg'), (2048, 1080)) == (2048, 1080)
assert restrict_image_resolution(get_test_example_file('target-1080p.jpg'), (4096, 2160)) == (2048, 1080)
def test_create_image_resolutions() -> None:
@@ -47,42 +49,42 @@ def test_create_image_resolutions() -> None:
def test_get_video_frame() -> None:
assert get_video_frame('.assets/examples/target-240p-25fps.mp4') is not None
assert get_video_frame(get_test_example_file('target-240p-25fps.mp4')) is not None
assert get_video_frame('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(get_test_example_file('target-240p-25fps.mp4')) == 270
assert count_video_frame_total(get_test_example_file('target-240p-30fps.mp4')) == 324
assert count_video_frame_total(get_test_example_file('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(get_test_example_file('target-240p-25fps.mp4')) == 25.0
assert detect_video_fps(get_test_example_file('target-240p-30fps.mp4')) == 30.0
assert detect_video_fps(get_test_example_file('target-240p-60fps.mp4')) == 60.0
assert detect_video_fps('invalid') is None
def test_restrict_video_fps() -> None:
assert restrict_video_fps('.assets/examples/target-1080p.mp4', 20.0) == 20.0
assert restrict_video_fps('.assets/examples/target-1080p.mp4', 25.0) == 25.0
assert restrict_video_fps('.assets/examples/target-1080p.mp4', 60.0) == 25.0
assert restrict_video_fps(get_test_example_file('target-1080p.mp4'), 20.0) == 20.0
assert restrict_video_fps(get_test_example_file('target-1080p.mp4'), 25.0) == 25.0
assert restrict_video_fps(get_test_example_file('target-1080p.mp4'), 60.0) == 25.0
def test_detect_video_resolution() -> None:
assert detect_video_resolution('.assets/examples/target-240p.mp4') == (426, 226)
assert detect_video_resolution('.assets/examples/target-240p-90deg.mp4') == (226, 426)
assert detect_video_resolution('.assets/examples/target-1080p.mp4') == (2048, 1080)
assert detect_video_resolution('.assets/examples/target-1080p-90deg.mp4') == (1080, 2048)
assert detect_video_resolution(get_test_example_file('target-240p.mp4')) == (426, 226)
assert detect_video_resolution(get_test_example_file('target-240p-90deg.mp4')) == (226, 426)
assert detect_video_resolution(get_test_example_file('target-1080p.mp4')) == (2048, 1080)
assert detect_video_resolution(get_test_example_file('target-1080p-90deg.mp4')) == (1080, 2048)
assert detect_video_resolution('invalid') is None
def test_restrict_video_resolution() -> None:
assert restrict_video_resolution('.assets/examples/target-1080p.mp4', (426, 226)) == (426, 226)
assert restrict_video_resolution('.assets/examples/target-1080p.mp4', (2048, 1080)) == (2048, 1080)
assert restrict_video_resolution('.assets/examples/target-1080p.mp4', (4096, 2160)) == (2048, 1080)
assert restrict_video_resolution(get_test_example_file('target-1080p.mp4'), (426, 226)) == (426, 226)
assert restrict_video_resolution(get_test_example_file('target-1080p.mp4'), (2048, 1080)) == (2048, 1080)
assert restrict_video_resolution(get_test_example_file('target-1080p.mp4'), (4096, 2160)) == (2048, 1080)
def test_create_video_resolutions() -> None:

View File

@@ -3,5 +3,5 @@ from facefusion import wording
def test_get() -> None:
assert wording.get('python_not_supported')
assert wording.get('help.source')
assert wording.get('help.source_paths')
assert wording.get('invalid') is None