Compare commits

..
Author SHA1 Message Date
henryruhs 1434c2c9bc use ideal pipesize for our task 2026-07-28 13:39:49 +02:00
11 changed files with 30 additions and 32 deletions
+1 -1
View File
@@ -43,7 +43,7 @@ jobs:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Set up FFmpeg - name: Set up FFmpeg
uses: AnimMouse/setup-ffmpeg@v1 uses: FedericoCarboni/setup-ffmpeg@v3
- name: Set up Python 3.12 - name: Set up Python 3.12
uses: actions/setup-python@v5 uses: actions/setup-python@v5
with: with:
+2 -2
View File
@@ -9,7 +9,7 @@ from facefusion.download import conditional_download_hashes, conditional_downloa
from facefusion.filesystem import resolve_relative_path from facefusion.filesystem import resolve_relative_path
from facefusion.thread_helper import conditional_thread_semaphore from facefusion.thread_helper import conditional_thread_semaphore
from facefusion.types import Detection, DownloadScope, DownloadSet, Fps, InferencePool, ModelSet, VisionFrame from facefusion.types import Detection, DownloadScope, DownloadSet, Fps, InferencePool, ModelSet, VisionFrame
from facefusion.vision import detect_video_fps, fit_contain_frame, is_vision_frame, read_image from facefusion.vision import detect_video_fps, fit_contain_frame, read_image
STREAM_COUNTER = 0 STREAM_COUNTER = 0
@@ -172,7 +172,7 @@ def analyse_video(video_path : str, trim_frame_start : int, trim_frame_end : int
vision_frame = video_manager.read_video_frame(video_reader) vision_frame = video_manager.read_video_frame(video_reader)
if frame_number % int(video_fps) == 0: if frame_number % int(video_fps) == 0:
if is_vision_frame(vision_frame): if numpy.any(vision_frame):
total += 1 total += 1
if analyse_frame(vision_frame): if analyse_frame(vision_frame):
+1 -1
View File
@@ -100,7 +100,7 @@ def pre_check() -> bool:
def common_pre_check() -> bool: def common_pre_check() -> bool:
content_analyser_content = inspect.getsource(content_analyser).encode() content_analyser_content = inspect.getsource(content_analyser).encode()
return hash_helper.create_hash(content_analyser_content) == '3c6ce25e' return hash_helper.create_hash(content_analyser_content) == '0922c180'
def processors_pre_check() -> bool: def processors_pre_check() -> bool:
+1 -2
View File
@@ -10,7 +10,6 @@ from facefusion.face_helper import apply_nms, average_points, convert_to_face_la
from facefusion.face_landmarker import detect_face_landmark, estimate_face_landmark_68_5 from facefusion.face_landmarker import detect_face_landmark, estimate_face_landmark_68_5
from facefusion.face_recognizer import calculate_face_embedding from facefusion.face_recognizer import calculate_face_embedding
from facefusion.types import BoundingBox, Face, FaceLandmark5, FaceLandmarkSet, FaceScoreSet, Score, VisionFrame from facefusion.types import BoundingBox, Face, FaceLandmark5, FaceLandmarkSet, FaceScoreSet, Score, VisionFrame
from facefusion.vision import is_vision_frame
def create_faces(vision_frame : VisionFrame, bounding_boxes : List[BoundingBox], face_scores : List[Score], face_landmarks_5 : List[FaceLandmark5]) -> List[Face]: def create_faces(vision_frame : VisionFrame, bounding_boxes : List[BoundingBox], face_scores : List[Score], face_landmarks_5 : List[FaceLandmark5]) -> List[Face]:
@@ -74,7 +73,7 @@ def get_many_faces(vision_frames : List[VisionFrame]) -> List[Face]:
many_faces : List[Face] = [] many_faces : List[Face] = []
for vision_frame in vision_frames: for vision_frame in vision_frames:
if is_vision_frame(vision_frame): if numpy.any(vision_frame):
all_bounding_boxes = [] all_bounding_boxes = []
all_face_scores = [] all_face_scores = []
all_face_landmarks_5 = [] all_face_landmarks_5 = []
+8 -7
View File
@@ -1,16 +1,17 @@
import threading import threading
from typing import List, Optional from typing import List, Optional
import numpy
from facefusion.hash_helper import create_hash from facefusion.hash_helper import create_hash
from facefusion.types import Face, FaceStore, VisionFrame from facefusion.types import Face, FaceStore, VisionFrame
from facefusion.vision import is_vision_frame
FACE_STORE : FaceStore = {} FACE_STORE : FaceStore = {}
def get_faces(vision_frame : VisionFrame) -> Optional[List[Face]]: def get_faces(vision_frame : VisionFrame) -> Optional[List[Face]]:
if is_vision_frame(vision_frame): if numpy.any(vision_frame):
vision_hash = create_hash(vision_frame.tobytes()) vision_hash = create_hash(vision_frame.data)
if FACE_STORE.get(vision_hash): if FACE_STORE.get(vision_hash):
return FACE_STORE.get(vision_hash).get('faces') return FACE_STORE.get(vision_hash).get('faces')
@@ -19,8 +20,8 @@ def get_faces(vision_frame : VisionFrame) -> Optional[List[Face]]:
def set_faces(vision_frame : VisionFrame, faces : List[Face]) -> None: def set_faces(vision_frame : VisionFrame, faces : List[Face]) -> None:
if is_vision_frame(vision_frame): if numpy.any(vision_frame):
vision_hash = create_hash(vision_frame.tobytes()) vision_hash = create_hash(vision_frame.data)
FACE_STORE.setdefault(vision_hash, FACE_STORE.setdefault(vision_hash,
{ {
'lock': threading.Lock() 'lock': threading.Lock()
@@ -28,8 +29,8 @@ def set_faces(vision_frame : VisionFrame, faces : List[Face]) -> None:
def resolve_lock(vision_frame : VisionFrame) -> threading.Lock: def resolve_lock(vision_frame : VisionFrame) -> threading.Lock:
if is_vision_frame(vision_frame): if numpy.any(vision_frame):
vision_hash = create_hash(vision_frame.tobytes()) vision_hash = create_hash(vision_frame.data)
return FACE_STORE.setdefault(vision_hash, return FACE_STORE.setdefault(vision_hash,
{ {
'lock': threading.Lock() 'lock': threading.Lock()
+1 -1
View File
@@ -66,7 +66,7 @@ def run_ffmpeg(commands : List[Command]) -> subprocess.Popen[bytes]:
def open_ffmpeg(commands : List[Command]) -> subprocess.Popen[bytes]: def open_ffmpeg(commands : List[Command]) -> subprocess.Popen[bytes]:
commands = ffmpeg_builder.run(commands) commands = ffmpeg_builder.run(commands)
return subprocess.Popen(commands, stdin = subprocess.PIPE, stderr = subprocess.DEVNULL, stdout = subprocess.PIPE) return subprocess.Popen(commands, stdin = subprocess.PIPE, stdout = subprocess.PIPE, pipesize = 1024 * 1024)
def create_video_reader(video_path : str, frame_number : int, video_metadata : VideoReaderMetadata) -> subprocess.Popen[bytes]: def create_video_reader(video_path : str, frame_number : int, video_metadata : VideoReaderMetadata) -> subprocess.Popen[bytes]:
@@ -9,4 +9,4 @@ FrameEnhancerInputs = TypedDict('FrameEnhancerInputs',
'temp_vision_mask' : Mask 'temp_vision_mask' : Mask
}) })
FrameEnhancerModel = Literal['clear_reality_x4', 'face_dat_x4', 'nomos8k_sc_x4', 'real_esrgan_x2', 'real_esrgan_x2_fp16', 'real_esrgan_x4', 'real_esrgan_x4_fp16', 'real_esrgan_x8', 'real_esrgan_x8_fp16', 'real_hatgan_x4', 'real_web_photo_x4', 'realistic_rescaler_x4', 'remacri_x4', 'siax_x4', 'span_kendata_x4', 'swin2_sr_x4', 'tghq_face_x8', 'ultra_sharp_x4', 'ultra_sharp_2_x4'] FrameEnhancerModel = Literal['clear_reality_x4', 'face_dat_x4', 'lsdir_x4', 'nomos8k_sc_x4', 'real_esrgan_x2', 'real_esrgan_x2_fp16', 'real_esrgan_x4', 'real_esrgan_x4_fp16', 'real_esrgan_x8', 'real_esrgan_x8_fp16', 'real_hatgan_x4', 'real_web_photo_x4', 'realistic_rescaler_x4', 'remacri_x4', 'siax_x4', 'span_kendata_x4', 'swin2_sr_x4', 'tghq_face_x8', 'ultra_sharp_x4', 'ultra_sharp_2_x4']
+3 -2
View File
@@ -5,6 +5,7 @@ from concurrent.futures import ThreadPoolExecutor
from typing import Deque, Iterator, List from typing import Deque, Iterator, List
import cv2 import cv2
import numpy
from tqdm import tqdm from tqdm import tqdm
from facefusion import ffmpeg_builder, logger, state_manager, translator from facefusion import ffmpeg_builder, logger, state_manager, translator
@@ -14,7 +15,7 @@ from facefusion.ffmpeg import open_ffmpeg
from facefusion.filesystem import is_directory from facefusion.filesystem import is_directory
from facefusion.processors.core import get_processors_modules from facefusion.processors.core import get_processors_modules
from facefusion.types import Fps, StreamMode, VisionFrame from facefusion.types import Fps, StreamMode, VisionFrame
from facefusion.vision import extract_vision_mask, is_vision_frame, read_static_images from facefusion.vision import extract_vision_mask, read_static_images
def multi_process_capture(camera_capture : cv2.VideoCapture, camera_fps : Fps) -> Iterator[VisionFrame]: def multi_process_capture(camera_capture : cv2.VideoCapture, camera_fps : Fps) -> Iterator[VisionFrame]:
@@ -30,7 +31,7 @@ def multi_process_capture(camera_capture : cv2.VideoCapture, camera_fps : Fps) -
if analyse_stream(capture_vision_frame, camera_fps): if analyse_stream(capture_vision_frame, camera_fps):
camera_capture.release() camera_capture.release()
if is_vision_frame(capture_vision_frame): if numpy.any(capture_vision_frame):
future = executor.submit(process_stream_frame, source_vision_frames, capture_vision_frame) future = executor.submit(process_stream_frame, source_vision_frames, capture_vision_frame)
futures.append(future) futures.append(future)
+2 -2
View File
@@ -18,7 +18,7 @@ from facefusion.types import AudioFrame, Face, Mask, VisionFrame
from facefusion.uis import choices as uis_choices from facefusion.uis import choices as uis_choices
from facefusion.uis.core import get_ui_component, get_ui_components, register_ui_component from facefusion.uis.core import get_ui_component, get_ui_components, register_ui_component
from facefusion.uis.types import ComponentOptions, PreviewMode from facefusion.uis.types import ComponentOptions, PreviewMode
from facefusion.vision import detect_frame_orientation, extract_vision_mask, fit_cover_frame, is_vision_frame, merge_vision_mask, obscure_frame, read_static_image, read_static_images, read_video_frame, restrict_frame, select_video_frames, unpack_resolution from facefusion.vision import detect_frame_orientation, extract_vision_mask, fit_cover_frame, merge_vision_mask, obscure_frame, read_static_image, read_static_images, read_video_frame, restrict_frame, select_video_frames, unpack_resolution
PREVIEW_IMAGE : Optional[gradio.Image] = None PREVIEW_IMAGE : Optional[gradio.Image] = None
@@ -277,7 +277,7 @@ def create_face_by_face(reference_vision_frame : VisionFrame, source_vision_fram
target_crop_vision_frame = extract_crop_frame(target_vision_frame, target_face) target_crop_vision_frame = extract_crop_frame(target_vision_frame, target_face)
output_crop_vision_frame = extract_crop_frame(temp_vision_frame, target_face) output_crop_vision_frame = extract_crop_frame(temp_vision_frame, target_face)
if is_vision_frame(target_crop_vision_frame) and is_vision_frame(output_crop_vision_frame): if numpy.any(target_crop_vision_frame) and numpy.any(output_crop_vision_frame):
target_crop_dimension = min(target_crop_vision_frame.shape[:2]) target_crop_dimension = min(target_crop_vision_frame.shape[:2])
target_crop_vision_frame = fit_cover_frame(target_crop_vision_frame, (target_crop_dimension, target_crop_dimension)) target_crop_vision_frame = fit_cover_frame(target_crop_vision_frame, (target_crop_dimension, target_crop_dimension))
output_crop_vision_frame = fit_cover_frame(output_crop_vision_frame, (target_crop_dimension, target_crop_dimension)) output_crop_vision_frame = fit_cover_frame(output_crop_vision_frame, (target_crop_dimension, target_crop_dimension))
+4 -3
View File
@@ -1,4 +1,5 @@
from concurrent.futures import ThreadPoolExecutor, as_completed from concurrent.futures import ThreadPoolExecutor, as_completed
from typing import Tuple
import cv2 import cv2
import numpy import numpy
@@ -83,7 +84,7 @@ def process_disk_frames() -> ErrorCode:
return 0 return 0
def process_stream_frame(frame_number : int, temp_video_resolution : Resolution) -> VisionFrame: def process_stream_frame(frame_number : int, temp_video_resolution : Resolution) -> Tuple[int, VisionFrame]:
target_vision_frames = select_video_frames(state_manager.get_item('target_path'), frame_number, state_manager.get_item('target_frame_amount')) target_vision_frames = select_video_frames(state_manager.get_item('target_path'), frame_number, state_manager.get_item('target_frame_amount'))
target_vision_frame = get_middle(target_vision_frames) target_vision_frame = get_middle(target_vision_frames)
temp_vision_frame = target_vision_frame.copy() temp_vision_frame = target_vision_frame.copy()
@@ -99,7 +100,7 @@ def process_stream_frame(frame_number : int, temp_video_resolution : Resolution)
if state_manager.get_item('temp_pixel_format') == 'bgr24': if state_manager.get_item('temp_pixel_format') == 'bgr24':
temp_vision_frame = temp_vision_frame[:, :, :3] temp_vision_frame = temp_vision_frame[:, :, :3]
return numpy.ascontiguousarray(temp_vision_frame) return frame_number, numpy.ascontiguousarray(temp_vision_frame)
def process_stream_frames() -> ErrorCode: def process_stream_frames() -> ErrorCode:
@@ -130,7 +131,7 @@ def process_stream_frames() -> ErrorCode:
pending_future.cancel() pending_future.cancel()
if not future.cancelled(): if not future.cancelled():
temp_vision_frame = future.result() _, temp_vision_frame = future.result()
video_manager.write_video_frame(video_writer, temp_vision_frame) video_manager.write_video_frame(video_writer, temp_vision_frame)
progress.update() progress.update()
+6 -10
View File
@@ -50,35 +50,34 @@ def test_get_reader() -> None:
assert video_metadata.get('resolution') == (426, 226) assert video_metadata.get('resolution') == (426, 226)
assert video_metadata.get('fps') == 25.0 assert video_metadata.get('fps') == 25.0
assert video_metadata.get('frame_total') == 270 assert video_metadata.get('frame_total') == 270
assert get_reader(get_test_example_file('target-240p-25fps.mp4'), 'read_video_frame') is video_reader assert get_reader(get_test_example_file('target-240p-25fps.mp4'), 'read_video_frame') is video_reader
assert not get_reader(get_test_example_file('target-240p-25fps.mp4'), 'select_video_frames').get('id') == video_reader.get('id') assert not get_reader(get_test_example_file('target-240p-25fps.mp4'), 'select_video_frames').get('id') == video_reader.get('id')
def test_conditional_seek_video_reader() -> None: def test_conditional_seek_video_reader() -> None:
video_reader = get_reader(get_test_example_file('target-240p-25fps.mp4'), 'read_video_frame') video_reader = get_reader(get_test_example_file('target-240p-25fps.mp4'), 'read_video_frame')
video_frames = {} sequential_frames = {}
for frame_number in range(30): for frame_number in range(30):
video_frames[frame_number] = read_video_frame(video_reader) sequential_frames[frame_number] = read_video_frame(video_reader)
for frame_number in [ 5, 17, 29 ]: for frame_number in [ 5, 17, 29 ]:
conditional_seek_video_reader(video_reader, frame_number) conditional_seek_video_reader(video_reader, frame_number)
assert numpy.array_equal(read_video_frame(video_reader), video_frames.get(frame_number)) is True assert numpy.array_equal(read_video_frame(video_reader), sequential_frames.get(frame_number)) is True
def test_seek_video_reader() -> None: def test_seek_video_reader() -> None:
video_reader = get_reader(get_test_example_file('target-240p-25fps.mp4'), 'read_video_frame') video_reader = get_reader(get_test_example_file('target-240p-25fps.mp4'), 'read_video_frame')
video_frames = {} sequential_frames = {}
for frame_number in range(30): for frame_number in range(30):
video_frames[frame_number] = read_video_frame(video_reader) sequential_frames[frame_number] = read_video_frame(video_reader)
for frame_number in [ 5, 17, 29 ]: for frame_number in [ 5, 17, 29 ]:
seek_video_reader(video_reader, frame_number) seek_video_reader(video_reader, frame_number)
assert numpy.array_equal(read_video_frame(video_reader), video_frames.get(frame_number)) is True assert numpy.array_equal(read_video_frame(video_reader), sequential_frames.get(frame_number)) is True
def test_drain_video_reader() -> None: def test_drain_video_reader() -> None:
@@ -134,7 +133,6 @@ def test_collect_video_frames() -> None:
def test_close_video_reader() -> None: def test_close_video_reader() -> None:
video_reader = get_reader(get_test_example_file('target-240p-25fps.mp4'), 'select_video_frames') video_reader = get_reader(get_test_example_file('target-240p-25fps.mp4'), 'select_video_frames')
read_video_frames(video_reader, 0, 4) read_video_frames(video_reader, 0, 4)
close_video_reader(video_reader) close_video_reader(video_reader)
@@ -178,7 +176,6 @@ def test_close_video_writer() -> None:
create_temp_directory(target_path) create_temp_directory(target_path)
video_reader = get_reader(target_path, 'read_video_frame') video_reader = get_reader(target_path, 'read_video_frame')
video_writer = get_writer(target_path, 30.0, (426, 226), (426, 226), 30.0) video_writer = get_writer(target_path, 30.0, (426, 226), (426, 226), 30.0)
write_video_frame(video_writer, read_video_frame(video_reader)) write_video_frame(video_writer, read_video_frame(video_reader))
assert close_video_writer(video_writer) is True assert close_video_writer(video_writer) is True
@@ -189,7 +186,6 @@ def test_clear_video_pool() -> None:
create_temp_directory(target_path) create_temp_directory(target_path)
video_reader = get_reader(target_path, 'select_video_frames') video_reader = get_reader(target_path, 'select_video_frames')
video_writer = get_writer(target_path, 25.0, (426, 226), (426, 226), 25.0) video_writer = get_writer(target_path, 25.0, (426, 226), (426, 226), 25.0)
read_video_frames(video_reader, 0, 4) read_video_frames(video_reader, 0, 4)
write_video_frame(video_writer, read_video_frame(video_reader)) write_video_frame(video_writer, read_video_frame(video_reader))
clear_video_pool() clear_video_pool()