Next (#318)
* renaming and restructuring (#282) * Renaming and restructuring * Renaming and restructuring * Renaming and restructuring * Fix gender detection * Implement distance to face debugger * Implement distance to face debugger part2 * Implement distance to face debugger part3 * Mark as next * Fix reference when face_debugger comes first * Use official onnxruntime nightly * CUDA on steroids * CUDA on steroids * Add some testing * Set inswapper_128_fp16 as default * Feat/block until post check (#292) * Block until download is done * Introduce post_check() * Fix webcam * Update dependencies * Add --force-reinstall to installer * Introduce config ini (#298) * Introduce config ini * Fix output video encoder * Revert help listings back to commas, Move SSL hack to download.py * Introduce output-video-preset which defaults to veryfast * Mapping for nvenc encoders * Rework on events and non-blocking UI * Add fast bmp to temp_frame_formats * Add fast bmp to temp_frame_formats * Show total processing time on success * Show total processing time on success * Show total processing time on success * Move are_images, is_image and is_video back to filesystem * Fix some spacings * Pissing everyone of by renaming stuff * Fix seconds output * feat/video output fps (#312) * added output fps slider, removed 'keep fps' option (#311) * added output fps slider, removed 'keep fps' option * now uses passed fps instead of global fps for ffmpeg * fps values are now floats instead of ints * fix previous commit * removed default value from fps slider this is so we can implement a dynamic default value later * Fix seconds output * Some cleanup --------- Co-authored-by: Ran Shaashua <47498956+ranshaa05@users.noreply.github.com> * Allow 0.01 steps for fps * Make fps unregulated * Make fps unregulated * Remove distance from face debugger again (does not work) * Fix gender age * Fix gender age * Hotfix benchmark suite * Warp face normalize (#313) * use normalized kp templates * Update face_helper.py * My 50 cents to warp_face() --------- Co-authored-by: Harisreedhar <46858047+harisreedhar@users.noreply.github.com> * face-swapper-weight (#315) * Move prepare_crop_frame and normalize_crop_frame out of apply_swap * Fix UI bug with different range * feat/output video resolution (#316) * Introduce detect_video_resolution, Rename detect_fps to detect_video_fps * Add calc_video_resolution_range * Make output resolution work, does not auto-select yet * Make output resolution work, does not auto-select yet * Try to keep the origin resolution * Split code into more fragments * Add pack/unpack resolution * Move video_template_sizes to choices * Improve create_video_resolutions * Reword benchmark suite * Optimal speed for benchmark * Introduce different video memory strategies, rename max_memory to max… (#317) * Introduce different video memory strategies, rename max_memory to max_system_memory * Update readme * Fix limit_system_memory call * Apply video_memory_strategy to face debugger * Limit face swapper weight to 3.0 * Remove face swapper weight due bad render outputs * Show/dide logic for output video preset * fix uint8 conversion * Fix whitespace * Finalize layout and update preview * Fix multi renders on face debugger * Restore less restrictive rendering of preview and stream * Fix block mode for model downloads * Add testing * Cosmetic changes * Enforce valid fps and resolution via CLI * Empty config * Cosmetics on args processing * Memory workover (#319) * Cosmetics on args processing * Fix for MacOS * Rename all max_ to _limit * More fixes * Update preview * Fix whitespace --------- Co-authored-by: Ran Shaashua <47498956+ranshaa05@users.noreply.github.com> Co-authored-by: Harisreedhar <46858047+harisreedhar@users.noreply.github.com>
This commit is contained in:
@@ -2,6 +2,6 @@ from typing import List
|
||||
|
||||
from facefusion.uis.typing import WebcamMode
|
||||
|
||||
common_options : List[str] = [ 'keep-fps', 'keep-temp', 'skip-audio', 'skip-download' ]
|
||||
common_options : List[str] = [ 'keep-temp', 'skip-audio', 'skip-download' ]
|
||||
webcam_modes : List[WebcamMode] = [ 'inline', 'udp', 'v4l2' ]
|
||||
webcam_resolutions : List[str] = [ '320x240', '640x480', '800x600', '1024x768', '1280x720', '1280x960', '1920x1080', '2560x1440', '3840x2160' ]
|
||||
|
||||
@@ -6,11 +6,11 @@ import gradio
|
||||
|
||||
import facefusion.globals
|
||||
from facefusion import wording
|
||||
from facefusion.face_analyser import get_face_analyser
|
||||
from facefusion.face_store import clear_static_faces
|
||||
from facefusion.processors.frame.core import get_frame_processors_modules
|
||||
from facefusion.vision import count_video_frame_total
|
||||
from facefusion.core import limit_resources, conditional_process
|
||||
from facefusion.vision import count_video_frame_total, detect_video_resolution, detect_video_fps, pack_resolution
|
||||
from facefusion.core import conditional_process
|
||||
from facefusion.memory import limit_system_memory
|
||||
from facefusion.normalizer import normalize_output_path
|
||||
from facefusion.filesystem import clear_temp
|
||||
from facefusion.uis.core import get_ui_component
|
||||
@@ -77,6 +77,8 @@ def listen() -> None:
|
||||
|
||||
def start(benchmark_runs : List[str], benchmark_cycles : int) -> Generator[List[Any], None, None]:
|
||||
facefusion.globals.source_paths = [ '.assets/examples/source.jpg' ]
|
||||
facefusion.globals.temp_frame_format = 'bmp'
|
||||
facefusion.globals.output_video_preset = 'ultrafast'
|
||||
target_paths = [ BENCHMARKS[benchmark_run] for benchmark_run in benchmark_runs if benchmark_run in BENCHMARKS ]
|
||||
benchmark_results = []
|
||||
if target_paths:
|
||||
@@ -88,8 +90,8 @@ def start(benchmark_runs : List[str], benchmark_cycles : int) -> Generator[List[
|
||||
|
||||
|
||||
def pre_process() -> None:
|
||||
limit_resources()
|
||||
get_face_analyser()
|
||||
if facefusion.globals.system_memory_limit > 0:
|
||||
limit_system_memory(facefusion.globals.system_memory_limit)
|
||||
for frame_processor_module in get_frame_processors_modules(facefusion.globals.frame_processors):
|
||||
frame_processor_module.get_frame_processor()
|
||||
|
||||
@@ -101,9 +103,12 @@ def post_process() -> None:
|
||||
def benchmark(target_path : str, benchmark_cycles : int) -> List[Any]:
|
||||
process_times = []
|
||||
total_fps = 0.0
|
||||
for i in range(benchmark_cycles):
|
||||
for index in range(benchmark_cycles):
|
||||
facefusion.globals.target_path = target_path
|
||||
facefusion.globals.output_path = normalize_output_path(facefusion.globals.source_paths, facefusion.globals.target_path, tempfile.gettempdir())
|
||||
target_video_resolution = detect_video_resolution(facefusion.globals.target_path)
|
||||
facefusion.globals.output_video_resolution = pack_resolution(target_video_resolution)
|
||||
facefusion.globals.output_video_fps = detect_video_fps(facefusion.globals.target_path)
|
||||
video_frame_total = count_video_frame_total(facefusion.globals.target_path)
|
||||
start_time = time.perf_counter()
|
||||
conditional_process()
|
||||
|
||||
@@ -20,7 +20,7 @@ def render() -> None:
|
||||
)
|
||||
BENCHMARK_CYCLES_SLIDER = gradio.Slider(
|
||||
label = wording.get('benchmark_cycles_slider_label'),
|
||||
value = 3,
|
||||
value = 5,
|
||||
step = 1,
|
||||
minimum = 1,
|
||||
maximum = 10
|
||||
|
||||
@@ -12,8 +12,6 @@ def render() -> None:
|
||||
global COMMON_OPTIONS_CHECKBOX_GROUP
|
||||
|
||||
value = []
|
||||
if facefusion.globals.keep_fps:
|
||||
value.append('keep-fps')
|
||||
if facefusion.globals.keep_temp:
|
||||
value.append('keep-temp')
|
||||
if facefusion.globals.skip_audio:
|
||||
@@ -32,7 +30,6 @@ def listen() -> None:
|
||||
|
||||
|
||||
def update(common_options : List[str]) -> None:
|
||||
facefusion.globals.keep_fps = 'keep-fps' in common_options
|
||||
facefusion.globals.keep_temp = 'keep-temp' in common_options
|
||||
facefusion.globals.skip_audio = 'skip-audio' in common_options
|
||||
facefusion.globals.skip_download = 'skip-download' in common_options
|
||||
|
||||
@@ -66,11 +66,11 @@ def render() -> None:
|
||||
|
||||
|
||||
def listen() -> None:
|
||||
FACE_ANALYSER_ORDER_DROPDOWN.select(update_face_analyser_order, inputs = FACE_ANALYSER_ORDER_DROPDOWN)
|
||||
FACE_ANALYSER_AGE_DROPDOWN.select(update_face_analyser_age, inputs = FACE_ANALYSER_AGE_DROPDOWN)
|
||||
FACE_ANALYSER_GENDER_DROPDOWN.select(update_face_analyser_gender, inputs = FACE_ANALYSER_GENDER_DROPDOWN)
|
||||
FACE_ANALYSER_ORDER_DROPDOWN.change(update_face_analyser_order, inputs = FACE_ANALYSER_ORDER_DROPDOWN)
|
||||
FACE_ANALYSER_AGE_DROPDOWN.change(update_face_analyser_age, inputs = FACE_ANALYSER_AGE_DROPDOWN)
|
||||
FACE_ANALYSER_GENDER_DROPDOWN.change(update_face_analyser_gender, inputs = FACE_ANALYSER_GENDER_DROPDOWN)
|
||||
FACE_DETECTOR_MODEL_DROPDOWN.change(update_face_detector_model, inputs = FACE_DETECTOR_MODEL_DROPDOWN)
|
||||
FACE_DETECTOR_SIZE_DROPDOWN.select(update_face_detector_size, inputs = FACE_DETECTOR_SIZE_DROPDOWN)
|
||||
FACE_DETECTOR_SIZE_DROPDOWN.change(update_face_detector_size, inputs = FACE_DETECTOR_SIZE_DROPDOWN)
|
||||
FACE_DETECTOR_SCORE_SLIDER.change(update_face_detector_score, inputs = FACE_DETECTOR_SCORE_SLIDER)
|
||||
|
||||
|
||||
|
||||
@@ -7,9 +7,9 @@ import facefusion.choices
|
||||
from facefusion import wording
|
||||
from facefusion.face_store import clear_static_faces, clear_reference_faces
|
||||
from facefusion.vision import get_video_frame, read_static_image, normalize_frame_color
|
||||
from facefusion.filesystem import is_image, is_video
|
||||
from facefusion.face_analyser import get_many_faces
|
||||
from facefusion.typing import Frame, FaceSelectorMode
|
||||
from facefusion.filesystem import is_image, is_video
|
||||
from facefusion.uis.core import get_ui_component, register_ui_component
|
||||
from facefusion.uis.typing import ComponentName
|
||||
|
||||
@@ -57,7 +57,7 @@ def render() -> None:
|
||||
|
||||
|
||||
def listen() -> None:
|
||||
FACE_SELECTOR_MODE_DROPDOWN.select(update_face_selector_mode, inputs = FACE_SELECTOR_MODE_DROPDOWN, outputs = [ REFERENCE_FACE_POSITION_GALLERY, REFERENCE_FACE_DISTANCE_SLIDER ])
|
||||
FACE_SELECTOR_MODE_DROPDOWN.change(update_face_selector_mode, inputs = FACE_SELECTOR_MODE_DROPDOWN, outputs = [ REFERENCE_FACE_POSITION_GALLERY, REFERENCE_FACE_DISTANCE_SLIDER ])
|
||||
REFERENCE_FACE_POSITION_GALLERY.select(clear_and_update_reference_face_position)
|
||||
REFERENCE_FACE_DISTANCE_SLIDER.change(update_reference_face_distance, inputs = REFERENCE_FACE_DISTANCE_SLIDER)
|
||||
multi_component_names : List[ComponentName] =\
|
||||
|
||||
@@ -4,7 +4,7 @@ import gradio
|
||||
import facefusion.globals
|
||||
from facefusion import wording
|
||||
from facefusion.processors.frame.core import load_frame_processor_module, clear_frame_processors_modules
|
||||
from facefusion.filesystem import list_module_names
|
||||
from facefusion.filesystem import list_directory
|
||||
from facefusion.uis.core import register_ui_component
|
||||
|
||||
FRAME_PROCESSORS_CHECKBOX_GROUP : Optional[gradio.CheckboxGroup] = None
|
||||
@@ -36,5 +36,5 @@ def update_frame_processors(frame_processors : List[str]) -> gradio.CheckboxGrou
|
||||
|
||||
|
||||
def sort_frame_processors(frame_processors : List[str]) -> list[str]:
|
||||
available_frame_processors = list_module_names('facefusion/processors/frame/modules')
|
||||
available_frame_processors = list_directory('facefusion/processors/frame/modules')
|
||||
return sorted(available_frame_processors, key = lambda frame_processor : frame_processors.index(frame_processor) if frame_processor in frame_processors else len(frame_processors))
|
||||
|
||||
@@ -56,7 +56,7 @@ def render() -> None:
|
||||
step = frame_processors_choices.frame_enhancer_blend_range[1] - frame_processors_choices.frame_enhancer_blend_range[0],
|
||||
minimum = frame_processors_choices.frame_enhancer_blend_range[0],
|
||||
maximum = frame_processors_choices.frame_enhancer_blend_range[-1],
|
||||
visible = 'face_enhancer' in facefusion.globals.frame_processors
|
||||
visible = 'frame_enhancer' in facefusion.globals.frame_processors
|
||||
)
|
||||
FACE_DEBUGGER_ITEMS_CHECKBOX_GROUP = gradio.CheckboxGroup(
|
||||
label = wording.get('face_debugger_items_checkbox_group_label'),
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
from typing import Optional
|
||||
import gradio
|
||||
|
||||
import facefusion.globals
|
||||
import facefusion.choices
|
||||
from facefusion import wording
|
||||
|
||||
MAX_MEMORY_SLIDER : Optional[gradio.Slider] = None
|
||||
|
||||
|
||||
def render() -> None:
|
||||
global MAX_MEMORY_SLIDER
|
||||
|
||||
MAX_MEMORY_SLIDER = gradio.Slider(
|
||||
label = wording.get('max_memory_slider_label'),
|
||||
step = facefusion.choices.max_memory_range[1] - facefusion.choices.max_memory_range[0],
|
||||
minimum = facefusion.choices.max_memory_range[0],
|
||||
maximum = facefusion.choices.max_memory_range[-1]
|
||||
)
|
||||
|
||||
|
||||
def listen() -> None:
|
||||
MAX_MEMORY_SLIDER.change(update_max_memory, inputs = MAX_MEMORY_SLIDER)
|
||||
|
||||
|
||||
def update_max_memory(max_memory : int) -> None:
|
||||
facefusion.globals.max_memory = max_memory if max_memory > 0 else None
|
||||
41
facefusion/uis/components/memory.py
Normal file
41
facefusion/uis/components/memory.py
Normal file
@@ -0,0 +1,41 @@
|
||||
from typing import Optional
|
||||
import gradio
|
||||
|
||||
import facefusion.globals
|
||||
import facefusion.choices
|
||||
from facefusion.typing import VideoMemoryStrategy
|
||||
from facefusion import wording
|
||||
|
||||
VIDEO_MEMORY_STRATEGY : Optional[gradio.Dropdown] = None
|
||||
SYSTEM_MEMORY_LIMIT_SLIDER : Optional[gradio.Slider] = None
|
||||
|
||||
|
||||
def render() -> None:
|
||||
global VIDEO_MEMORY_STRATEGY
|
||||
global SYSTEM_MEMORY_LIMIT_SLIDER
|
||||
|
||||
VIDEO_MEMORY_STRATEGY = gradio.Dropdown(
|
||||
label = wording.get('video_memory_strategy_dropdown_label'),
|
||||
choices = facefusion.choices.video_memory_strategies,
|
||||
value = facefusion.globals.video_memory_strategy
|
||||
)
|
||||
SYSTEM_MEMORY_LIMIT_SLIDER = gradio.Slider(
|
||||
label = wording.get('system_memory_limit_slider_label'),
|
||||
step =facefusion.choices.system_memory_limit_range[1] - facefusion.choices.system_memory_limit_range[0],
|
||||
minimum = facefusion.choices.system_memory_limit_range[0],
|
||||
maximum = facefusion.choices.system_memory_limit_range[-1],
|
||||
value = facefusion.globals.system_memory_limit
|
||||
)
|
||||
|
||||
|
||||
def listen() -> None:
|
||||
VIDEO_MEMORY_STRATEGY.change(update_video_memory_strategy, inputs = VIDEO_MEMORY_STRATEGY)
|
||||
SYSTEM_MEMORY_LIMIT_SLIDER.change(update_system_memory_limit, inputs = SYSTEM_MEMORY_LIMIT_SLIDER)
|
||||
|
||||
|
||||
def update_video_memory_strategy(video_memory_strategy : VideoMemoryStrategy) -> None:
|
||||
facefusion.globals.video_memory_strategy = video_memory_strategy
|
||||
|
||||
|
||||
def update_system_memory_limit(system_memory_limit : int) -> None:
|
||||
facefusion.globals.system_memory_limit = system_memory_limit
|
||||
@@ -3,10 +3,11 @@ import gradio
|
||||
|
||||
import facefusion.globals
|
||||
from facefusion import wording
|
||||
from facefusion.core import limit_resources, conditional_process
|
||||
from facefusion.core import conditional_process
|
||||
from facefusion.memory import limit_system_memory
|
||||
from facefusion.uis.core import get_ui_component
|
||||
from facefusion.normalizer import normalize_output_path
|
||||
from facefusion.filesystem import is_image, is_video, clear_temp
|
||||
from facefusion.filesystem import clear_temp, is_image, is_video
|
||||
|
||||
OUTPUT_IMAGE : Optional[gradio.Image] = None
|
||||
OUTPUT_VIDEO : Optional[gradio.Video] = None
|
||||
@@ -47,7 +48,8 @@ def listen() -> None:
|
||||
|
||||
def start(output_path : str) -> Tuple[gradio.Image, gradio.Video]:
|
||||
facefusion.globals.output_path = normalize_output_path(facefusion.globals.source_paths, facefusion.globals.target_path, output_path)
|
||||
limit_resources()
|
||||
if facefusion.globals.system_memory_limit > 0:
|
||||
limit_system_memory(facefusion.globals.system_memory_limit)
|
||||
conditional_process()
|
||||
if is_image(facefusion.globals.output_path):
|
||||
return gradio.Image(value = facefusion.globals.output_path, visible = True), gradio.Video(value = None, visible = False)
|
||||
|
||||
@@ -5,22 +5,29 @@ import gradio
|
||||
import facefusion.globals
|
||||
import facefusion.choices
|
||||
from facefusion import wording
|
||||
from facefusion.typing import OutputVideoEncoder
|
||||
from facefusion.typing import OutputVideoEncoder, OutputVideoPreset, Fps
|
||||
from facefusion.filesystem import is_image, is_video
|
||||
from facefusion.uis.typing import ComponentName
|
||||
from facefusion.uis.core import get_ui_component, register_ui_component
|
||||
from facefusion.vision import detect_video_fps, create_video_resolutions, detect_video_resolution, pack_resolution
|
||||
|
||||
OUTPUT_PATH_TEXTBOX : Optional[gradio.Textbox] = None
|
||||
OUTPUT_IMAGE_QUALITY_SLIDER : Optional[gradio.Slider] = None
|
||||
OUTPUT_VIDEO_ENCODER_DROPDOWN : Optional[gradio.Dropdown] = None
|
||||
OUTPUT_VIDEO_PRESET_DROPDOWN : Optional[gradio.Dropdown] = None
|
||||
OUTPUT_VIDEO_RESOLUTION_DROPDOWN : Optional[gradio.Dropdown] = None
|
||||
OUTPUT_VIDEO_QUALITY_SLIDER : Optional[gradio.Slider] = None
|
||||
OUTPUT_VIDEO_FPS_SLIDER : Optional[gradio.Slider] = None
|
||||
|
||||
|
||||
def render() -> None:
|
||||
global OUTPUT_PATH_TEXTBOX
|
||||
global OUTPUT_IMAGE_QUALITY_SLIDER
|
||||
global OUTPUT_VIDEO_ENCODER_DROPDOWN
|
||||
global OUTPUT_VIDEO_PRESET_DROPDOWN
|
||||
global OUTPUT_VIDEO_RESOLUTION_DROPDOWN
|
||||
global OUTPUT_VIDEO_QUALITY_SLIDER
|
||||
global OUTPUT_VIDEO_FPS_SLIDER
|
||||
|
||||
OUTPUT_PATH_TEXTBOX = gradio.Textbox(
|
||||
label = wording.get('output_path_textbox_label'),
|
||||
@@ -41,6 +48,12 @@ def render() -> None:
|
||||
value = facefusion.globals.output_video_encoder,
|
||||
visible = is_video(facefusion.globals.target_path)
|
||||
)
|
||||
OUTPUT_VIDEO_PRESET_DROPDOWN = gradio.Dropdown(
|
||||
label = wording.get('output_video_preset_dropdown_label'),
|
||||
choices = facefusion.choices.output_video_presets,
|
||||
value = facefusion.globals.output_video_preset,
|
||||
visible = is_video(facefusion.globals.target_path)
|
||||
)
|
||||
OUTPUT_VIDEO_QUALITY_SLIDER = gradio.Slider(
|
||||
label = wording.get('output_video_quality_slider_label'),
|
||||
value = facefusion.globals.output_video_quality,
|
||||
@@ -49,14 +62,31 @@ def render() -> None:
|
||||
maximum = facefusion.choices.output_video_quality_range[-1],
|
||||
visible = is_video(facefusion.globals.target_path)
|
||||
)
|
||||
OUTPUT_VIDEO_RESOLUTION_DROPDOWN = gradio.Dropdown(
|
||||
label = wording.get('output_video_resolution_dropdown_label'),
|
||||
choices = create_video_resolutions(facefusion.globals.target_path),
|
||||
value = facefusion.globals.output_video_resolution,
|
||||
visible = is_video(facefusion.globals.target_path)
|
||||
)
|
||||
OUTPUT_VIDEO_FPS_SLIDER = gradio.Slider(
|
||||
label = wording.get('output_video_fps_slider_label'),
|
||||
value = facefusion.globals.output_video_fps,
|
||||
step = 0.01,
|
||||
minimum = 1,
|
||||
maximum = 60,
|
||||
visible = is_video(facefusion.globals.target_path)
|
||||
)
|
||||
register_ui_component('output_path_textbox', OUTPUT_PATH_TEXTBOX)
|
||||
|
||||
|
||||
def listen() -> None:
|
||||
OUTPUT_PATH_TEXTBOX.change(update_output_path, inputs = OUTPUT_PATH_TEXTBOX)
|
||||
OUTPUT_IMAGE_QUALITY_SLIDER.change(update_output_image_quality, inputs = OUTPUT_IMAGE_QUALITY_SLIDER)
|
||||
OUTPUT_VIDEO_ENCODER_DROPDOWN.select(update_output_video_encoder, inputs = OUTPUT_VIDEO_ENCODER_DROPDOWN)
|
||||
OUTPUT_VIDEO_ENCODER_DROPDOWN.change(update_output_video_encoder, inputs = OUTPUT_VIDEO_ENCODER_DROPDOWN)
|
||||
OUTPUT_VIDEO_PRESET_DROPDOWN.change(update_output_video_preset, inputs = OUTPUT_VIDEO_PRESET_DROPDOWN)
|
||||
OUTPUT_VIDEO_QUALITY_SLIDER.change(update_output_video_quality, inputs = OUTPUT_VIDEO_QUALITY_SLIDER)
|
||||
OUTPUT_VIDEO_RESOLUTION_DROPDOWN.change(update_output_video_resolution, inputs = OUTPUT_VIDEO_RESOLUTION_DROPDOWN)
|
||||
OUTPUT_VIDEO_FPS_SLIDER.change(update_output_video_fps, inputs = OUTPUT_VIDEO_FPS_SLIDER)
|
||||
multi_component_names : List[ComponentName] =\
|
||||
[
|
||||
'source_image',
|
||||
@@ -67,15 +97,19 @@ def listen() -> None:
|
||||
component = get_ui_component(component_name)
|
||||
if component:
|
||||
for method in [ 'upload', 'change', 'clear' ]:
|
||||
getattr(component, method)(remote_update, outputs = [ OUTPUT_IMAGE_QUALITY_SLIDER, OUTPUT_VIDEO_ENCODER_DROPDOWN, OUTPUT_VIDEO_QUALITY_SLIDER ])
|
||||
getattr(component, method)(remote_update, outputs = [ OUTPUT_IMAGE_QUALITY_SLIDER, OUTPUT_VIDEO_ENCODER_DROPDOWN, OUTPUT_VIDEO_PRESET_DROPDOWN, OUTPUT_VIDEO_QUALITY_SLIDER, OUTPUT_VIDEO_RESOLUTION_DROPDOWN, OUTPUT_VIDEO_FPS_SLIDER ])
|
||||
|
||||
|
||||
def remote_update() -> Tuple[gradio.Slider, gradio.Dropdown, gradio.Slider]:
|
||||
def remote_update() -> Tuple[gradio.Slider, gradio.Dropdown, gradio.Dropdown, gradio.Slider, gradio.Dropdown, gradio.Slider]:
|
||||
if is_image(facefusion.globals.target_path):
|
||||
return gradio.Slider(visible = True), gradio.Dropdown(visible = False), gradio.Slider(visible = False)
|
||||
return gradio.Slider(visible = True), gradio.Dropdown(visible = False), gradio.Dropdown(visible = False), gradio.Slider(visible = False), gradio.Dropdown(visible = False, value = None, choices = None), gradio.Slider(visible = False, value = None)
|
||||
if is_video(facefusion.globals.target_path):
|
||||
return gradio.Slider(visible = False), gradio.Dropdown(visible = True), gradio.Slider(visible = True)
|
||||
return gradio.Slider(visible = False), gradio.Dropdown(visible = False), gradio.Slider(visible = False)
|
||||
target_video_resolution = detect_video_resolution(facefusion.globals.target_path)
|
||||
output_video_resolution = pack_resolution(target_video_resolution)
|
||||
output_video_resolutions = create_video_resolutions(facefusion.globals.target_path)
|
||||
output_video_fps = detect_video_fps(facefusion.globals.target_path)
|
||||
return gradio.Slider(visible = False), gradio.Dropdown(visible = True), gradio.Dropdown(visible = True), gradio.Slider(visible = True), gradio.Dropdown(visible = True, value = output_video_resolution, choices = output_video_resolutions), gradio.Slider(visible = True, value = output_video_fps)
|
||||
return gradio.Slider(visible = False), gradio.Dropdown(visible = False), gradio.Dropdown(visible = False), gradio.Slider(visible = False), gradio.Dropdown(visible = False, value = None, choices = None), gradio.Slider(visible = False, value = None)
|
||||
|
||||
|
||||
def update_output_path(output_path : str) -> None:
|
||||
@@ -90,5 +124,17 @@ def update_output_video_encoder(output_video_encoder: OutputVideoEncoder) -> Non
|
||||
facefusion.globals.output_video_encoder = output_video_encoder
|
||||
|
||||
|
||||
def update_output_video_preset(output_video_preset : OutputVideoPreset) -> None:
|
||||
facefusion.globals.output_video_preset = output_video_preset
|
||||
|
||||
|
||||
def update_output_video_quality(output_video_quality : int) -> None:
|
||||
facefusion.globals.output_video_quality = output_video_quality
|
||||
|
||||
|
||||
def update_output_video_resolution(output_video_resolution : str) -> None:
|
||||
facefusion.globals.output_video_resolution = output_video_resolution
|
||||
|
||||
|
||||
def update_output_video_fps(output_video_fps : Fps) -> None:
|
||||
facefusion.globals.output_video_fps = output_video_fps
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
from typing import Any, Dict, List, Optional
|
||||
from time import sleep
|
||||
import cv2
|
||||
import gradio
|
||||
|
||||
import facefusion.globals
|
||||
from facefusion import wording
|
||||
from facefusion import wording, logger
|
||||
from facefusion.core import conditional_append_reference_faces
|
||||
from facefusion.face_store import clear_static_faces, get_reference_faces, clear_reference_faces
|
||||
from facefusion.typing import Frame, Face, FaceSet
|
||||
from facefusion.vision import get_video_frame, count_video_frame_total, normalize_frame_color, resize_frame_dimension, read_static_image, read_static_images
|
||||
from facefusion.vision import get_video_frame, count_video_frame_total, normalize_frame_color, resize_frame_resolution, read_static_image, read_static_images
|
||||
from facefusion.filesystem import is_image, is_video
|
||||
from facefusion.face_analyser import get_average_face, clear_face_analyser
|
||||
from facefusion.content_analyser import analyse_frame
|
||||
from facefusion.processors.frame.core import load_frame_processor_module
|
||||
from facefusion.filesystem import is_image, is_video
|
||||
from facefusion.uis.typing import ComponentName
|
||||
from facefusion.uis.core import get_ui_component, register_ui_component
|
||||
|
||||
@@ -94,9 +95,7 @@ def listen() -> None:
|
||||
change_one_component_names : List[ComponentName] =\
|
||||
[
|
||||
'face_debugger_items_checkbox_group',
|
||||
'face_enhancer_model_dropdown',
|
||||
'face_enhancer_blend_slider',
|
||||
'frame_enhancer_model_dropdown',
|
||||
'frame_enhancer_blend_slider',
|
||||
'face_selector_mode_dropdown',
|
||||
'reference_face_distance_slider',
|
||||
@@ -115,7 +114,9 @@ def listen() -> None:
|
||||
change_two_component_names : List[ComponentName] =\
|
||||
[
|
||||
'frame_processors_checkbox_group',
|
||||
'face_enhancer_model_dropdown',
|
||||
'face_swapper_model_dropdown',
|
||||
'frame_enhancer_model_dropdown',
|
||||
'face_detector_model_dropdown',
|
||||
'face_detector_size_dropdown',
|
||||
'face_detector_score_slider'
|
||||
@@ -130,22 +131,29 @@ def clear_and_update_preview_image(frame_number : int = 0) -> gradio.Image:
|
||||
clear_face_analyser()
|
||||
clear_reference_faces()
|
||||
clear_static_faces()
|
||||
sleep(0.5)
|
||||
return update_preview_image(frame_number)
|
||||
|
||||
|
||||
def update_preview_image(frame_number : int = 0) -> gradio.Image:
|
||||
for frame_processor in facefusion.globals.frame_processors:
|
||||
frame_processor_module = load_frame_processor_module(frame_processor)
|
||||
while not frame_processor_module.post_check():
|
||||
logger.disable()
|
||||
sleep(0.5)
|
||||
logger.enable()
|
||||
conditional_append_reference_faces()
|
||||
source_frames = read_static_images(facefusion.globals.source_paths)
|
||||
source_face = get_average_face(source_frames)
|
||||
reference_face = get_reference_faces() if 'reference' in facefusion.globals.face_selector_mode else None
|
||||
reference_faces = get_reference_faces() if 'reference' in facefusion.globals.face_selector_mode else None
|
||||
if is_image(facefusion.globals.target_path):
|
||||
target_frame = read_static_image(facefusion.globals.target_path)
|
||||
preview_frame = process_preview_frame(source_face, reference_face, target_frame)
|
||||
preview_frame = process_preview_frame(source_face, reference_faces, target_frame)
|
||||
preview_frame = normalize_frame_color(preview_frame)
|
||||
return gradio.Image(value = preview_frame)
|
||||
if is_video(facefusion.globals.target_path):
|
||||
temp_frame = get_video_frame(facefusion.globals.target_path, frame_number)
|
||||
preview_frame = process_preview_frame(source_face, reference_face, temp_frame)
|
||||
preview_frame = process_preview_frame(source_face, reference_faces, temp_frame)
|
||||
preview_frame = normalize_frame_color(preview_frame)
|
||||
return gradio.Image(value = preview_frame)
|
||||
return gradio.Image(value = None)
|
||||
@@ -159,12 +167,14 @@ def update_preview_frame_slider() -> gradio.Slider:
|
||||
|
||||
|
||||
def process_preview_frame(source_face : Face, reference_faces : FaceSet, temp_frame : Frame) -> Frame:
|
||||
temp_frame = resize_frame_dimension(temp_frame, 640, 640)
|
||||
temp_frame = resize_frame_resolution(temp_frame, 640, 640)
|
||||
if analyse_frame(temp_frame):
|
||||
return cv2.GaussianBlur(temp_frame, (99, 99), 0)
|
||||
for frame_processor in facefusion.globals.frame_processors:
|
||||
frame_processor_module = load_frame_processor_module(frame_processor)
|
||||
logger.disable()
|
||||
if frame_processor_module.pre_process('preview'):
|
||||
logger.enable()
|
||||
temp_frame = frame_processor_module.process_frame(
|
||||
source_face,
|
||||
reference_faces,
|
||||
|
||||
@@ -33,7 +33,7 @@ def render() -> None:
|
||||
|
||||
|
||||
def listen() -> None:
|
||||
TEMP_FRAME_FORMAT_DROPDOWN.select(update_temp_frame_format, inputs = TEMP_FRAME_FORMAT_DROPDOWN)
|
||||
TEMP_FRAME_FORMAT_DROPDOWN.change(update_temp_frame_format, inputs = TEMP_FRAME_FORMAT_DROPDOWN)
|
||||
TEMP_FRAME_QUALITY_SLIDER.change(update_temp_frame_quality, inputs = TEMP_FRAME_QUALITY_SLIDER)
|
||||
target_video = get_ui_component('target_video')
|
||||
if target_video:
|
||||
|
||||
@@ -1,22 +1,23 @@
|
||||
from typing import Optional, Generator, Deque
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from collections import deque
|
||||
from typing import Optional, Generator, Deque, List
|
||||
import os
|
||||
import platform
|
||||
import subprocess
|
||||
import cv2
|
||||
import gradio
|
||||
from time import sleep
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from collections import deque
|
||||
from tqdm import tqdm
|
||||
|
||||
import facefusion.globals
|
||||
from facefusion import logger, wording
|
||||
from facefusion.content_analyser import analyse_stream
|
||||
from facefusion.typing import Frame, Face
|
||||
from facefusion.typing import Frame, Face, Fps
|
||||
from facefusion.face_analyser import get_average_face
|
||||
from facefusion.processors.frame.core import get_frame_processors_modules
|
||||
from facefusion.processors.frame.core import get_frame_processors_modules, load_frame_processor_module
|
||||
from facefusion.ffmpeg import open_ffmpeg
|
||||
from facefusion.vision import normalize_frame_color, read_static_images
|
||||
from facefusion.uis.typing import StreamMode, WebcamMode
|
||||
from facefusion.vision import normalize_frame_color, read_static_images, unpack_resolution
|
||||
from facefusion.uis.typing import StreamMode, WebcamMode, ComponentName
|
||||
from facefusion.uis.core import get_ui_component
|
||||
|
||||
WEBCAM_CAPTURE : Optional[cv2.VideoCapture] = None
|
||||
@@ -73,28 +74,36 @@ def listen() -> None:
|
||||
if webcam_mode_radio and webcam_resolution_dropdown and webcam_fps_slider:
|
||||
start_event = WEBCAM_START_BUTTON.click(start, inputs = [ webcam_mode_radio, webcam_resolution_dropdown, webcam_fps_slider ], outputs = WEBCAM_IMAGE)
|
||||
WEBCAM_STOP_BUTTON.click(stop, cancels = start_event)
|
||||
source_image = get_ui_component('source_image')
|
||||
if source_image:
|
||||
for method in [ 'upload', 'change', 'clear' ]:
|
||||
getattr(source_image, method)(stop, cancels = start_event)
|
||||
change_two_component_names : List[ComponentName] =\
|
||||
[
|
||||
'frame_processors_checkbox_group',
|
||||
'face_swapper_model_dropdown',
|
||||
'face_enhancer_model_dropdown',
|
||||
'frame_enhancer_model_dropdown',
|
||||
'source_image'
|
||||
]
|
||||
for component_name in change_two_component_names:
|
||||
component = get_ui_component(component_name)
|
||||
if component:
|
||||
component.change(update, cancels = start_event)
|
||||
|
||||
|
||||
def start(webcam_mode : WebcamMode, resolution : str, fps : float) -> Generator[Frame, None, None]:
|
||||
def start(webcam_mode : WebcamMode, webcam_resolution : str, webcam_fps : Fps) -> Generator[Frame, None, None]:
|
||||
facefusion.globals.face_selector_mode = 'one'
|
||||
facefusion.globals.face_analyser_order = 'large-small'
|
||||
source_frames = read_static_images(facefusion.globals.source_paths)
|
||||
source_face = get_average_face(source_frames)
|
||||
stream = None
|
||||
if webcam_mode in [ 'udp', 'v4l2' ]:
|
||||
stream = open_stream(webcam_mode, resolution, fps) # type: ignore[arg-type]
|
||||
webcam_width, webcam_height = map(int, resolution.split('x'))
|
||||
stream = open_stream(webcam_mode, webcam_resolution, webcam_fps) # type: ignore[arg-type]
|
||||
webcam_width, webcam_height = unpack_resolution(webcam_resolution)
|
||||
webcam_capture = get_webcam_capture()
|
||||
if webcam_capture and webcam_capture.isOpened():
|
||||
webcam_capture.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc(*'MJPG')) # type: ignore[attr-defined]
|
||||
webcam_capture.set(cv2.CAP_PROP_FRAME_WIDTH, webcam_width)
|
||||
webcam_capture.set(cv2.CAP_PROP_FRAME_HEIGHT, webcam_height)
|
||||
webcam_capture.set(cv2.CAP_PROP_FPS, fps)
|
||||
for capture_frame in multi_process_capture(source_face, webcam_capture, fps):
|
||||
webcam_capture.set(cv2.CAP_PROP_FPS, webcam_fps)
|
||||
for capture_frame in multi_process_capture(source_face, webcam_capture, webcam_fps):
|
||||
if webcam_mode == 'inline':
|
||||
yield normalize_frame_color(capture_frame)
|
||||
else:
|
||||
@@ -105,14 +114,14 @@ def start(webcam_mode : WebcamMode, resolution : str, fps : float) -> Generator[
|
||||
yield None
|
||||
|
||||
|
||||
def multi_process_capture(source_face : Face, webcam_capture : cv2.VideoCapture, fps : float) -> Generator[Frame, None, None]:
|
||||
def multi_process_capture(source_face : Face, webcam_capture : cv2.VideoCapture, webcam_fps : Fps) -> Generator[Frame, None, None]:
|
||||
with tqdm(desc = wording.get('processing'), unit = 'frame', ascii = ' =', disable = facefusion.globals.log_level in [ 'warn', 'error' ]) as progress:
|
||||
with ThreadPoolExecutor(max_workers = facefusion.globals.execution_thread_count) as executor:
|
||||
futures = []
|
||||
deque_capture_frames : Deque[Frame] = deque()
|
||||
while webcam_capture and webcam_capture.isOpened():
|
||||
_, capture_frame = webcam_capture.read()
|
||||
if analyse_stream(capture_frame, fps):
|
||||
if analyse_stream(capture_frame, webcam_fps):
|
||||
return
|
||||
future = executor.submit(process_stream_frame, source_face, capture_frame)
|
||||
futures.append(future)
|
||||
@@ -125,6 +134,15 @@ def multi_process_capture(source_face : Face, webcam_capture : cv2.VideoCapture,
|
||||
yield deque_capture_frames.popleft()
|
||||
|
||||
|
||||
def update() -> None:
|
||||
for frame_processor in facefusion.globals.frame_processors:
|
||||
frame_processor_module = load_frame_processor_module(frame_processor)
|
||||
while not frame_processor_module.post_check():
|
||||
logger.disable()
|
||||
sleep(0.5)
|
||||
logger.enable()
|
||||
|
||||
|
||||
def stop() -> gradio.Image:
|
||||
clear_webcam_capture()
|
||||
return gradio.Image(value = None)
|
||||
@@ -132,7 +150,9 @@ def stop() -> gradio.Image:
|
||||
|
||||
def process_stream_frame(source_face : Face, temp_frame : Frame) -> Frame:
|
||||
for frame_processor_module in get_frame_processors_modules(facefusion.globals.frame_processors):
|
||||
logger.disable()
|
||||
if frame_processor_module.pre_process('stream'):
|
||||
logger.enable()
|
||||
temp_frame = frame_processor_module.process_frame(
|
||||
source_face,
|
||||
None,
|
||||
@@ -141,8 +161,8 @@ def process_stream_frame(source_face : Face, temp_frame : Frame) -> Frame:
|
||||
return temp_frame
|
||||
|
||||
|
||||
def open_stream(stream_mode : StreamMode, resolution : str, fps : float) -> subprocess.Popen[bytes]:
|
||||
commands = [ '-f', 'rawvideo', '-pix_fmt', 'bgr24', '-s', resolution, '-r', str(fps), '-i', '-' ]
|
||||
def open_stream(stream_mode : StreamMode, stream_resolution : str, stream_fps : Fps) -> subprocess.Popen[bytes]:
|
||||
commands = [ '-f', 'rawvideo', '-pix_fmt', 'bgr24', '-s', stream_resolution, '-r', str(stream_fps), '-i', '-']
|
||||
if stream_mode == 'udp':
|
||||
commands.extend([ '-b:v', '2000k', '-f', 'mpegts', 'udp://localhost:27000?pkt_size=1316' ])
|
||||
if stream_mode == 'v4l2':
|
||||
|
||||
@@ -28,10 +28,12 @@ def load_ui_layout_module(ui_layout : str) -> Any:
|
||||
if not hasattr(ui_layout_module, method_name):
|
||||
raise NotImplementedError
|
||||
except ModuleNotFoundError as exception:
|
||||
logger.error(wording.get('ui_layout_not_loaded').format(ui_layout=ui_layout), __name__.upper())
|
||||
logger.debug(exception.msg, __name__.upper())
|
||||
sys.exit(wording.get('ui_layout_not_loaded').format(ui_layout = ui_layout))
|
||||
sys.exit(1)
|
||||
except NotImplementedError:
|
||||
sys.exit(wording.get('ui_layout_not_implemented').format(ui_layout = ui_layout))
|
||||
logger.error(wording.get('ui_layout_not_implemented').format(ui_layout = ui_layout), __name__.upper())
|
||||
sys.exit(1)
|
||||
return ui_layout_module
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import gradio
|
||||
|
||||
import facefusion.globals
|
||||
from facefusion.download import conditional_download
|
||||
from facefusion.uis.components import about, frame_processors, frame_processors_options, execution, execution_thread_count, execution_queue_count, limit_resources, benchmark_options, benchmark
|
||||
from facefusion.uis.components import about, frame_processors, frame_processors_options, execution, execution_thread_count, execution_queue_count, memory, benchmark_options, benchmark
|
||||
|
||||
|
||||
def pre_check() -> bool:
|
||||
@@ -40,7 +40,7 @@ def render() -> gradio.Blocks:
|
||||
execution_thread_count.render()
|
||||
execution_queue_count.render()
|
||||
with gradio.Blocks():
|
||||
limit_resources.render()
|
||||
memory.render()
|
||||
with gradio.Blocks():
|
||||
benchmark_options.render()
|
||||
with gradio.Column(scale = 5):
|
||||
@@ -55,7 +55,7 @@ def listen() -> None:
|
||||
execution.listen()
|
||||
execution_thread_count.listen()
|
||||
execution_queue_count.listen()
|
||||
limit_resources.listen()
|
||||
memory.listen()
|
||||
benchmark.listen()
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import gradio
|
||||
|
||||
from facefusion.uis.components import about, frame_processors, frame_processors_options, execution, execution_thread_count, execution_queue_count, limit_resources, temp_frame, output_options, common_options, source, target, output, preview, trim_frame, face_analyser, face_selector, face_masker
|
||||
from facefusion.uis.components import about, frame_processors, frame_processors_options, execution, execution_thread_count, execution_queue_count, memory, temp_frame, output_options, common_options, source, target, output, preview, trim_frame, face_analyser, face_selector, face_masker
|
||||
|
||||
|
||||
def pre_check() -> bool:
|
||||
@@ -25,13 +25,11 @@ def render() -> gradio.Blocks:
|
||||
execution_thread_count.render()
|
||||
execution_queue_count.render()
|
||||
with gradio.Blocks():
|
||||
limit_resources.render()
|
||||
memory.render()
|
||||
with gradio.Blocks():
|
||||
temp_frame.render()
|
||||
with gradio.Blocks():
|
||||
output_options.render()
|
||||
with gradio.Blocks():
|
||||
common_options.render()
|
||||
with gradio.Column(scale = 2):
|
||||
with gradio.Blocks():
|
||||
source.render()
|
||||
@@ -50,6 +48,8 @@ def render() -> gradio.Blocks:
|
||||
face_masker.render()
|
||||
with gradio.Blocks():
|
||||
face_analyser.render()
|
||||
with gradio.Blocks():
|
||||
common_options.render()
|
||||
return layout
|
||||
|
||||
|
||||
@@ -59,10 +59,9 @@ def listen() -> None:
|
||||
execution.listen()
|
||||
execution_thread_count.listen()
|
||||
execution_queue_count.listen()
|
||||
limit_resources.listen()
|
||||
memory.listen()
|
||||
temp_frame.listen()
|
||||
output_options.listen()
|
||||
common_options.listen()
|
||||
source.listen()
|
||||
target.listen()
|
||||
output.listen()
|
||||
@@ -71,6 +70,7 @@ def listen() -> None:
|
||||
face_selector.listen()
|
||||
face_masker.listen()
|
||||
face_analyser.listen()
|
||||
common_options.listen()
|
||||
|
||||
|
||||
def run(ui : gradio.Blocks) -> None:
|
||||
|
||||
@@ -39,5 +39,6 @@ ComponentName = Literal\
|
||||
'webcam_resolution_dropdown',
|
||||
'webcam_fps_slider'
|
||||
]
|
||||
|
||||
WebcamMode = Literal['inline', 'udp', 'v4l2']
|
||||
StreamMode = Literal['udp', 'v4l2']
|
||||
|
||||
Reference in New Issue
Block a user