mirror of
https://github.com/facefusion/facefusion.git
synced 2026-07-27 12:30:55 +02:00
support for rgba via stream
This commit is contained in:
@@ -45,6 +45,7 @@ def apply_args(args : Args, apply_state_item : ApplyStateItem) -> None:
|
||||
apply_state_item('trim_frame_start', args.get('trim_frame_start'))
|
||||
apply_state_item('trim_frame_end', args.get('trim_frame_end'))
|
||||
apply_state_item('temp_frame_format', args.get('temp_frame_format'))
|
||||
apply_state_item('temp_pixel_format', args.get('temp_pixel_format'))
|
||||
apply_state_item('workflow_mode', args.get('workflow_mode'))
|
||||
apply_state_item('target_frame_amount', args.get('target_frame_amount'))
|
||||
apply_state_item('output_image_quality', args.get('output_image_quality'))
|
||||
|
||||
@@ -2,7 +2,7 @@ import logging
|
||||
from typing import List, Sequence, get_args
|
||||
|
||||
from facefusion.common_helper import create_float_range, create_int_range
|
||||
from facefusion.types import Angle, AudioEncoder, AudioFormat, AudioTypeSet, BenchmarkMode, BenchmarkResolution, BenchmarkSet, DownloadProvider, DownloadProviderSet, DownloadScope, EncoderSet, ExecutionProvider, ExecutionProviderSet, FaceDetectorModel, FaceDetectorSet, FaceLandmarkerModel, FaceMaskArea, FaceMaskAreaSet, FaceMaskRegion, FaceMaskRegionSet, FaceMaskType, FaceOccluderModel, FaceParserModel, FaceSelectorGender, FaceSelectorMode, FaceSelectorOrder, FaceSelectorRace, Gender, ImageFormat, ImageTypeSet, JobStatus, LogLevel, LogLevelSet, Race, Score, TempFrameFormat, UiWorkflow, VideoEncoder, VideoFormat, VideoMemoryStrategy, VideoPreset, VideoTypeSet, VoiceExtractorModel, WorkflowMode
|
||||
from facefusion.types import Angle, AudioEncoder, AudioFormat, AudioTypeSet, BenchmarkMode, BenchmarkResolution, BenchmarkSet, DownloadProvider, DownloadProviderSet, DownloadScope, EncoderSet, ExecutionProvider, ExecutionProviderSet, FaceDetectorModel, FaceDetectorSet, FaceLandmarkerModel, FaceMaskArea, FaceMaskAreaSet, FaceMaskRegion, FaceMaskRegionSet, FaceMaskType, FaceOccluderModel, FaceParserModel, FaceSelectorGender, FaceSelectorMode, FaceSelectorOrder, FaceSelectorRace, Gender, ImageFormat, ImageTypeSet, JobStatus, LogLevel, LogLevelSet, Race, Score, TempFrameFormat, TempPixelFormat, UiWorkflow, VideoEncoder, VideoFormat, VideoMemoryStrategy, VideoPreset, VideoTypeSet, VoiceExtractorModel, WorkflowMode
|
||||
|
||||
face_detector_set : FaceDetectorSet =\
|
||||
{
|
||||
@@ -80,6 +80,8 @@ audio_formats : List[AudioFormat] = list(get_args(AudioFormat))
|
||||
image_formats : List[ImageFormat] = list(get_args(ImageFormat))
|
||||
video_formats : List[VideoFormat] = list(get_args(VideoFormat))
|
||||
temp_frame_formats : List[TempFrameFormat] = list(get_args(TempFrameFormat))
|
||||
#todo: needs review - [config] [critical: low] temp pixel format choices for the stream pipe
|
||||
temp_pixel_formats : List[TempPixelFormat] = list(get_args(TempPixelFormat))
|
||||
|
||||
output_audio_encoders : List[AudioEncoder] = list(get_args(AudioEncoder))
|
||||
#todo: needs review - [config] [critical: low] workflow mode choices for disk and stream
|
||||
|
||||
@@ -136,6 +136,7 @@ LOCALES : Locales =\
|
||||
'trim_frame_start': 'specify the starting frame of the target video',
|
||||
'trim_frame_end': 'specify the ending frame of the target video',
|
||||
'temp_frame_format': 'specify the temporary resources format',
|
||||
'temp_pixel_format': 'specify the pixel format for the stream pipe (rgba keeps the alpha channel)',
|
||||
#todo: needs review - [ui] [critical: low] workflow_mode help text replaces keep_temp
|
||||
'workflow_mode': 'specify how frames flow through processing (disk extracts and merges temp frames, stream pipes frames through ffmpeg)',
|
||||
'target_frame_amount': 'specify the amount of target frames forwarded to the processor',
|
||||
|
||||
@@ -169,9 +169,11 @@ def create_frame_extraction_program() -> ArgumentParser:
|
||||
group_frame_extraction.add_argument('--trim-frame-start', help = translator.get('help.trim_frame_start'), type = int, default = facefusion.config.get_int_value('frame_extraction', 'trim_frame_start'))
|
||||
group_frame_extraction.add_argument('--trim-frame-end', help = translator.get('help.trim_frame_end'), type = int, default = facefusion.config.get_int_value('frame_extraction', 'trim_frame_end'))
|
||||
group_frame_extraction.add_argument('--temp-frame-format', help = translator.get('help.temp_frame_format'), default = config.get_str_value('frame_extraction', 'temp_frame_format', 'png'), choices = facefusion.choices.temp_frame_formats)
|
||||
#todo: needs review - [streaming] [critical: low] new temp pixel format option, rgba enables alpha through the stream pipe
|
||||
group_frame_extraction.add_argument('--temp-pixel-format', help = translator.get('help.temp_pixel_format'), default = config.get_str_value('frame_extraction', 'temp_pixel_format', 'rgb'), choices = facefusion.choices.temp_pixel_formats)
|
||||
#todo: needs review - [workflow] [critical: medium] keep_temp cli option replaced by workflow_mode, breaks existing configs and jobs
|
||||
group_frame_extraction.add_argument('--workflow-mode', help = translator.get('help.workflow_mode'), default = config.get_str_value('frame_extraction', 'workflow_mode', 'disk'), choices = facefusion.choices.workflow_modes)
|
||||
job_store.register_step_keys([ 'trim_frame_start', 'trim_frame_end', 'temp_frame_format', 'workflow_mode' ])
|
||||
job_store.register_step_keys([ 'trim_frame_start', 'trim_frame_end', 'temp_frame_format', 'temp_pixel_format', 'workflow_mode' ])
|
||||
return program
|
||||
|
||||
|
||||
|
||||
@@ -172,6 +172,8 @@ AudioFormat = Literal['flac', 'm4a', 'mp3', 'ogg', 'opus', 'wav']
|
||||
ImageFormat = Literal['bmp', 'jpeg', 'png', 'tiff', 'webp']
|
||||
VideoFormat = Literal['avi', 'm4v', 'mkv', 'mov', 'mp4', 'mpeg', 'mxf', 'webm', 'wmv']
|
||||
TempFrameFormat = Literal['bmp', 'jpeg', 'png', 'tiff']
|
||||
#todo: needs review - [streaming] [critical: low] new temp pixel format controls the stream pipe channels
|
||||
TempPixelFormat = Literal['rgb', 'rgba']
|
||||
#todo: needs review - [workflow] [critical: medium] new workflow mode replaces keep_temp in state and jobs
|
||||
WorkflowMode = Literal['disk', 'stream']
|
||||
AudioTypeSet : TypeAlias = Dict[AudioFormat, str]
|
||||
@@ -344,6 +346,7 @@ StateKey = Literal\
|
||||
'trim_frame_start',
|
||||
'trim_frame_end',
|
||||
'temp_frame_format',
|
||||
'temp_pixel_format',
|
||||
'workflow_mode',
|
||||
'target_frame_amount',
|
||||
'output_image_quality',
|
||||
@@ -415,6 +418,7 @@ State = TypedDict('State',
|
||||
'trim_frame_start' : int,
|
||||
'trim_frame_end' : int,
|
||||
'temp_frame_format' : TempFrameFormat,
|
||||
'temp_pixel_format' : TempPixelFormat,
|
||||
'workflow_mode' : WorkflowMode,
|
||||
'target_frame_amount' : int,
|
||||
'output_image_quality' : int,
|
||||
|
||||
@@ -167,10 +167,14 @@ def create_video_writer_process(target_path : str, temp_video_fps : Fps, temp_vi
|
||||
temp_video_format = cast(VideoFormat, get_file_format(temp_video_path))
|
||||
output_video_encoder = ffmpeg_builder.fix_video_encoder(temp_video_format, output_video_encoder)
|
||||
encoder_thread_count = 16
|
||||
writer_pixel_format = 'bgr24'
|
||||
|
||||
if state_manager.get_item('temp_pixel_format') == 'rgba':
|
||||
writer_pixel_format = 'bgra'
|
||||
|
||||
commands = ffmpeg_builder.chain(
|
||||
ffmpeg_builder.set_output_format('rawvideo'),
|
||||
#todo: consider to introduce a argument to pass --output-pixel-format
|
||||
ffmpeg_builder.enforce_pixel_format('bgra'),
|
||||
ffmpeg_builder.enforce_pixel_format(writer_pixel_format),
|
||||
ffmpeg_builder.set_media_resolution(pack_video_resolution(temp_video_resolution)),
|
||||
ffmpeg_builder.set_input_fps(temp_video_fps),
|
||||
ffmpeg_builder.set_input('pipe:0'),
|
||||
|
||||
@@ -279,7 +279,7 @@ def process_disk_frames() -> ErrorCode:
|
||||
return 0
|
||||
|
||||
|
||||
#todo: needs review - [streaming] [critical: high] middle frame resized to temp resolution before processing, returns contiguous bgra matching the writer pipe
|
||||
#todo: needs review - [streaming] [critical: high] middle frame resized to temp resolution before processing, channels follow temp_pixel_format to match the writer pipe
|
||||
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_frame = get_middle(target_vision_frames)
|
||||
@@ -289,8 +289,10 @@ def process_stream_frame(frame_number : int, temp_video_resolution : Resolution)
|
||||
temp_vision_frame = cv2.resize(target_vision_frame, temp_video_resolution)
|
||||
temp_vision_frame = process_target_frame(frame_number, target_vision_frames, temp_vision_frame)
|
||||
|
||||
if temp_vision_frame.shape[2] == 3:
|
||||
if state_manager.get_item('temp_pixel_format') == 'rgba':
|
||||
temp_vision_frame = cv2.cvtColor(temp_vision_frame, cv2.COLOR_BGR2BGRA)
|
||||
if state_manager.get_item('temp_pixel_format') == 'rgb':
|
||||
temp_vision_frame = temp_vision_frame[:, :, :3]
|
||||
|
||||
return frame_number, numpy.ascontiguousarray(temp_vision_frame)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user