Cleanup Part1 (#1201)

* remove some todos, improve video manager, simplify ffmpeg commands and more

* do more

* remove thread count for filters
This commit is contained in:
Henry Ruhs
2026-07-25 11:47:36 +02:00
committed by GitHub
parent 4a8bfec297
commit 585a7d75da
10 changed files with 87 additions and 85 deletions
+3
View File
@@ -32,6 +32,7 @@ def conditional_download(download_directory_path : str, urls : List[str]) -> Non
curl_builder.set_timeout(5),
curl_builder.set_retry(5)
)
open_curl(commands)
current_size = initial_size
progress.set_postfix(download_providers = state_manager.get_item('download_providers'), file_name = download_file_name)
@@ -48,6 +49,7 @@ def get_static_download_size(url : str) -> int:
curl_builder.ping(url),
curl_builder.set_timeout(5)
)
process = open_curl(commands)
lines = reversed(process.stdout.readlines())
@@ -66,6 +68,7 @@ def ping_static_url(url : str) -> bool:
curl_builder.ping(url),
curl_builder.set_timeout(5)
)
process = open_curl(commands)
process.communicate()
return process.returncode == 0
+18 -14
View File
@@ -10,7 +10,7 @@ import facefusion.choices
from facefusion import ffmpeg_builder, ffprobe, logger, process_manager, state_manager, translator, vision
from facefusion.filesystem import get_file_format, remove_file
from facefusion.temp_helper import get_temp_file_path, get_temp_frame_pattern
from facefusion.types import AudioBuffer, AudioEncoder, Command, EncoderSet, Fps, Resolution, UpdateProgress, VideoEncoder, VideoFormat, VideoMetadata
from facefusion.types import AudioBuffer, AudioEncoder, Command, EncoderSet, Fps, Resolution, UpdateProgress, VideoEncoder, VideoFormat, VideoReaderMetadata
def run_ffmpeg_with_progress(commands : List[Command], update_progress : UpdateProgress) -> subprocess.Popen[bytes]:
@@ -69,24 +69,20 @@ def open_ffmpeg(commands : List[Command]) -> subprocess.Popen[bytes]:
return subprocess.Popen(commands, stdin = subprocess.PIPE, stdout = subprocess.PIPE)
#todo: needs review - [decoding] [critical: medium] raw pipe reader with seek based start, spawn moved from the POC video_manager into ffmpeg
#todo: question if this does too much
def create_video_reader(video_path : str, frame_position : int, video_metadata : VideoMetadata) -> subprocess.Popen[bytes]:
def create_video_reader(video_path : str, frame_position : int, video_metadata : VideoReaderMetadata) -> subprocess.Popen[bytes]:
commands = ffmpeg_builder.chain(
ffmpeg_builder.set_input_seek(frame_position / video_metadata.get('fps')),
ffmpeg_builder.seek_to(frame_position / video_metadata.get('fps')),
ffmpeg_builder.set_input(video_path),
ffmpeg_builder.set_filter_thread_count(4),
ffmpeg_builder.restrict_color_transfer(video_metadata.get('color_transfer')),
ffmpeg_builder.prevent_frame_drop(),
ffmpeg_builder.enforce_pixel_format('bgr24'),
ffmpeg_builder.set_output_format('rawvideo'),
ffmpeg_builder.cast_stream()
)
return open_ffmpeg(commands)
#todo: needs review - [encoding] [critical: high] pipe writer always converts and tags bt709, temp_pixel_format drives the pipe channels, encoder_thread_count hardcoded to 16
#todo: question if this does too much
def create_video_writer(target_path : str, temp_video_fps : Fps, temp_video_resolution : Resolution, output_video_resolution : Resolution, output_video_fps : Fps) -> subprocess.Popen[bytes]:
output_video_encoder = state_manager.get_item('output_video_encoder')
output_video_quality = state_manager.get_item('output_video_quality')
@@ -94,7 +90,6 @@ def create_video_writer(target_path : str, temp_video_fps : Fps, temp_video_reso
temp_video_path = get_temp_file_path(target_path)
temp_video_format = cast(VideoFormat, get_file_format(temp_video_path))
output_video_encoder = fix_video_encoder(temp_video_format, output_video_encoder)
encoder_thread_count = 16
commands = ffmpeg_builder.chain(
ffmpeg_builder.set_output_format('rawvideo'),
@@ -102,10 +97,9 @@ def create_video_writer(target_path : str, temp_video_fps : Fps, temp_video_reso
ffmpeg_builder.set_media_resolution(vision.pack_resolution(temp_video_resolution)),
ffmpeg_builder.set_input_fps(temp_video_fps),
ffmpeg_builder.set_input('pipe:0'),
ffmpeg_builder.set_filter_thread_count(4),
ffmpeg_builder.set_media_resolution(vision.pack_resolution(output_video_resolution)),
ffmpeg_builder.set_video_encoder(output_video_encoder),
ffmpeg_builder.set_global_thread_count(encoder_thread_count),
ffmpeg_builder.set_thread_count(16),
ffmpeg_builder.set_video_tag(output_video_encoder, temp_video_format),
ffmpeg_builder.set_video_quality(output_video_encoder, output_video_quality),
ffmpeg_builder.set_video_preset(output_video_encoder, output_video_preset),
@@ -116,6 +110,7 @@ def create_video_writer(target_path : str, temp_video_fps : Fps, temp_video_reso
ffmpeg_builder.set_pixel_format(output_video_encoder),
ffmpeg_builder.force_output(temp_video_path)
)
return open_ffmpeg(commands)
@@ -160,6 +155,7 @@ def extract_frames(target_path : str, temp_video_resolution : Resolution, temp_v
color_transfer = ffprobe.extract_static_video_metadata(target_path).get('color_transfer')
extract_frame_total = vision.predict_video_frame_total(target_path, temp_video_fps, trim_frame_start, trim_frame_end)
temp_frame_pattern = get_temp_frame_pattern(target_path, '%08d')
commands = ffmpeg_builder.chain(
ffmpeg_builder.set_input(target_path),
ffmpeg_builder.set_media_resolution(vision.pack_resolution(temp_video_resolution)),
@@ -181,24 +177,28 @@ def extract_frames(target_path : str, temp_video_resolution : Resolution, temp_v
def copy_image(target_path : str, temp_image_resolution : Resolution) -> bool:
temp_image_path = get_temp_file_path(target_path)
commands = ffmpeg_builder.chain(
ffmpeg_builder.set_input(target_path),
ffmpeg_builder.set_media_resolution(vision.pack_resolution(temp_image_resolution)),
ffmpeg_builder.set_image_quality(target_path, 100),
ffmpeg_builder.force_output(temp_image_path)
)
return run_ffmpeg(commands).returncode == 0
def finalize_image(target_path : str, output_path : str, output_image_resolution : Resolution) -> bool:
output_image_quality = state_manager.get_item('output_image_quality')
temp_image_path = get_temp_file_path(target_path)
commands = ffmpeg_builder.chain(
ffmpeg_builder.set_input(temp_image_path),
ffmpeg_builder.set_media_resolution(vision.pack_resolution(output_image_resolution)),
ffmpeg_builder.set_image_quality(target_path, output_image_quality),
ffmpeg_builder.force_output(output_path)
)
return run_ffmpeg(commands).returncode == 0
@@ -228,8 +228,8 @@ def restore_audio(target_path : str, output_path : str, trim_frame_start : int,
temp_video_format = cast(VideoFormat, get_file_format(temp_video_path))
temp_video_duration = vision.detect_video_duration(temp_video_path)
output_video_format = cast(VideoFormat, get_file_format(output_path))
output_audio_encoder = fix_audio_encoder(temp_video_format, output_audio_encoder)
commands = ffmpeg_builder.chain(
ffmpeg_builder.set_input(temp_video_path),
ffmpeg_builder.select_media_range(trim_frame_start, trim_frame_end, target_video_fps),
@@ -244,6 +244,7 @@ def restore_audio(target_path : str, output_path : str, trim_frame_start : int,
ffmpeg_builder.set_faststart(output_video_format),
ffmpeg_builder.force_output(output_path)
)
return run_ffmpeg(commands).returncode == 0
@@ -255,8 +256,8 @@ def replace_audio(target_path : str, audio_path : str, output_path : str) -> boo
temp_video_format = cast(VideoFormat, get_file_format(temp_video_path))
temp_video_duration = vision.detect_video_duration(temp_video_path)
output_video_format = cast(VideoFormat, get_file_format(output_path))
output_audio_encoder = fix_audio_encoder(temp_video_format, output_audio_encoder)
commands = ffmpeg_builder.chain(
ffmpeg_builder.set_input(temp_video_path),
ffmpeg_builder.set_input(audio_path),
@@ -268,6 +269,7 @@ def replace_audio(target_path : str, audio_path : str, output_path : str) -> boo
ffmpeg_builder.set_faststart(output_video_format),
ffmpeg_builder.force_output(output_path)
)
return run_ffmpeg(commands).returncode == 0
@@ -279,8 +281,8 @@ def merge_video(target_path : str, temp_video_fps : Fps, output_video_resolution
temp_video_path = get_temp_file_path(target_path)
temp_video_format = cast(VideoFormat, get_file_format(temp_video_path))
temp_frame_pattern = get_temp_frame_pattern(target_path, '%08d')
output_video_encoder = fix_video_encoder(temp_video_format, output_video_encoder)
commands = ffmpeg_builder.chain(
ffmpeg_builder.set_input_fps(temp_video_fps),
ffmpeg_builder.set_start_number(trim_frame_start),
@@ -316,6 +318,7 @@ def concat_video(output_path : str, temp_output_paths : List[str]) -> bool:
output_path = os.path.abspath(output_path)
output_video_format = cast(VideoFormat, get_file_format(output_path))
commands = ffmpeg_builder.chain(
ffmpeg_builder.unsafe_concat(),
ffmpeg_builder.set_input(concat_video_file.name),
@@ -324,6 +327,7 @@ def concat_video(output_path : str, temp_output_paths : List[str]) -> bool:
ffmpeg_builder.set_faststart(output_video_format),
ffmpeg_builder.force_output(output_path)
)
process = run_ffmpeg(commands)
process.communicate()
remove_file(concat_video_path)
+3 -12
View File
@@ -83,14 +83,10 @@ def unsafe_concat() -> List[Command]:
return [ '-f', 'concat', '-safe', '0' ]
#todo: needs review - [seeking] [critical: low] seek based start for the pipe reader
#todo: question to rename set_input_seek to just set_input
def set_input_seek(seek_time : float) -> List[Command]:
return [ '-ss', str(seek_time) ]
def seek_to(time : float) -> List[Command]:
return [ '-ss', str(time)]
#todo: needs review - [decoding] [critical: low] raw output format for pipe io
#todo: question if set_output_format is needed
def set_output_format(output_format : str) -> List[Command]:
return [ '-f', output_format ]
@@ -206,15 +202,10 @@ def set_audio_volume(audio_volume : int) -> List[Command]:
#todo: needs review - [encoding] [critical: low] explicit ffmpeg thread cap
def set_global_thread_count(thread_count : int) -> List[Command]:
def set_thread_count(thread_count : int) -> List[Command]:
return [ '-threads', str(thread_count) ]
#todo: needs review - [decoding] [critical: low] threads the filter graph, new against the POC
def set_filter_thread_count(thread_count : int) -> List[Command]:
return [ '-filter_threads', str(thread_count) ]
def set_video_encoder(video_encoder : str) -> List[Command]:
return [ '-c:v', video_encoder ]
+3
View File
@@ -32,6 +32,7 @@ def probe_audio_entries(audio_path : str, entries : List[str]) -> Dict[str, str]
ffprobe_builder.format_to_key_value(),
ffprobe_builder.set_input(audio_path)
)
output, _ = run_ffprobe(commands).communicate()
return parse_entries(output)
@@ -44,6 +45,7 @@ def probe_video_entries(video_path : str, entries : List[str]) -> Dict[str, str]
ffprobe_builder.format_to_key_value(),
ffprobe_builder.set_input(video_path)
)
output, _ = run_ffprobe(commands).communicate()
return parse_entries(output)
@@ -55,6 +57,7 @@ def probe_format_entries(media_path : str, entries : List[str]) -> Dict[str, str
ffprobe_builder.format_to_key_value(),
ffprobe_builder.set_input(media_path)
)
output, _ = run_ffprobe(commands).communicate()
return parse_entries(output)
+10 -6
View File
@@ -123,23 +123,27 @@ VideoMetadata = TypedDict('VideoMetadata',
'bit_rate' : BitRate,
'color_transfer' : ColorTransfer
})
#todo: needs review - [types] [critical: low] reader and writer state around ffmpeg processes, metadata embedded whole
#todo: question if the body of VideoReader and VideoWriter needs all the keys
VideoReaderMetadata : TypeAlias = VideoMetadata
VideoWriterMetadata = TypedDict('VideoWriterMetadata',
{
'fps' : Fps,
'resolution' : Resolution
})
VideoReader = TypedDict('VideoReader',
{
'id' : str,
'process' : subprocess.Popen[bytes],
'file_path' : str,
'metadata' : VideoMetadata,
'process' : subprocess.Popen[bytes],
'metadata' : VideoReaderMetadata,
'position' : int
})
VideoReaderSet : TypeAlias = Dict[str, VideoReader]
VideoWriter = TypedDict('VideoWriter',
{
'id' : str,
'process' : subprocess.Popen[bytes],
'file_path' : str,
'metadata' : VideoMetadata
'process' : subprocess.Popen[bytes],
'metadata' : VideoWriterMetadata
})
VideoWriterSet : TypeAlias = Dict[str, VideoWriter]
VideoPoolSet = TypedDict('VideoPoolSet',
+27 -25
View File
@@ -5,7 +5,7 @@ import numpy
from facefusion import ffmpeg, ffprobe, frame_store
from facefusion.common_helper import get_first, get_last
from facefusion.types import Fps, Resolution, VideoMetadata, VideoPoolSet, VideoReader, VideoWriter, VisionFrame, VisionFrameSet
from facefusion.types import Fps, Resolution, VideoPoolSet, VideoReader, VideoWriter, VisionFrame, VisionFrameSet
VIDEO_POOL_SET : VideoPoolSet =\
{
@@ -14,7 +14,6 @@ VIDEO_POOL_SET : VideoPoolSet =\
}
#todo: needs review - [lifecycle] [critical: medium] pooled reader per path is created without lock and only reaped via clear_video_pool
def get_reader(video_path : str) -> VideoReader:
if video_path not in VIDEO_POOL_SET.get('reader'):
video_metadata = ffprobe.extract_static_video_metadata(video_path)
@@ -22,8 +21,8 @@ def get_reader(video_path : str) -> VideoReader:
VIDEO_POOL_SET['reader'][video_path] =\
{
'id': uuid.uuid4().hex,
'process': ffmpeg.create_video_reader(video_path, 0, video_metadata),
'file_path': video_path,
'process': ffmpeg.create_video_reader(video_path, 0, video_metadata),
'metadata': video_metadata,
'position': 0
}
@@ -33,10 +32,10 @@ def get_reader(video_path : str) -> VideoReader:
#todo: needs review - [seeking] [critical: high] forward skip up to 128 frames by draining the pipe, everything else refreshes the process
def conditional_set_video_reader_position(video_reader : VideoReader, frame_position : int) -> None:
skip_margin = 128
skip_total = frame_position - video_reader.get('position')
skip_margin = 128
if skip_total > 0 and skip_total <= skip_margin:
if 0 < skip_total <= skip_margin:
for _ in range(skip_total):
read_video_reader_frame(video_reader)
@@ -44,10 +43,9 @@ def conditional_set_video_reader_position(video_reader : VideoReader, frame_posi
refresh_video_reader(video_reader, frame_position)
#todo: needs review - [seeking] [critical: high] kill and respawn per out of order seek, frequent refreshes stack up on random access
def refresh_video_reader(video_reader : VideoReader, frame_position : int) -> None:
video_reader.get('process').kill()
video_reader.get('process').wait()
close_video_reader(video_reader)
video_reader['process'] = ffmpeg.create_video_reader(video_reader.get('file_path'), frame_position, video_reader.get('metadata'))
video_reader['position'] = frame_position
@@ -93,42 +91,46 @@ def read_video_reader_window(video_reader : VideoReader, frame_start : int, fram
return frame_store.select_frame_set(id, frame_start, frame_end)
#todo: needs review - [lifecycle] [critical: low] pooled writer keyed by target_path, metadata forwarded by the caller
def get_writer(target_path : str, video_metadata : VideoMetadata, temp_video_fps : Fps, temp_video_resolution : Resolution, output_video_resolution : Resolution, output_video_fps : Fps) -> VideoWriter:
if target_path not in VIDEO_POOL_SET.get('writer'):
VIDEO_POOL_SET['writer'][target_path] =\
def close_video_reader(video_reader : VideoReader) -> None:
video_reader.get('process').kill()
video_reader.get('process').wait()
frame_store.clear_frames(video_reader.get('id'))
def get_writer(video_path : str, temp_video_fps : Fps, temp_video_resolution : Resolution, output_video_resolution : Resolution, output_video_fps : Fps) -> VideoWriter:
if video_path not in VIDEO_POOL_SET.get('writer'):
VIDEO_POOL_SET['writer'][video_path] =\
{
'id': uuid.uuid4().hex,
'process': ffmpeg.create_video_writer(target_path, temp_video_fps, temp_video_resolution, output_video_resolution, output_video_fps),
'file_path': target_path,
'metadata': video_metadata
'file_path': video_path,
'process': ffmpeg.create_video_writer(video_path, temp_video_fps, temp_video_resolution, output_video_resolution, output_video_fps),
'metadata':
{
'fps': output_video_fps,
'resolution': output_video_resolution,
}
}
return VIDEO_POOL_SET.get('writer').get(target_path)
return VIDEO_POOL_SET.get('writer').get(video_path)
#todo: needs review - [encoding] [critical: medium] blocking stdin write without backpressure or broken pipe handling
def write_video_writer_frame(video_writer : VideoWriter, vision_frame : VisionFrame) -> None:
def write_video_writer(video_writer : VideoWriter, vision_frame : VisionFrame) -> None:
video_writer.get('process').stdin.write(vision_frame.tobytes())
#todo: needs review - [encoding] [critical: medium] encoder failures only surface via returncode at close time
def close_video_writer(video_writer : VideoWriter) -> bool:
video_writer.get('process').stdin.close()
video_writer.get('process').wait()
return video_writer.get('process').returncode == 0
#todo: needs review - [lifecycle] [critical: high] kill over terminate, sigterm deadlocks while the pipe is full
def clear_video_pool() -> None:
for video_reader in VIDEO_POOL_SET.get('reader').values():
video_reader.get('process').kill()
video_reader.get('process').wait()
frame_store.clear_frames(video_reader.get('id'))
close_video_reader(video_reader)
for video_writer in VIDEO_POOL_SET.get('writer').values():
video_writer.get('process').kill()
video_writer.get('process').wait()
close_video_writer(video_writer)
VIDEO_POOL_SET['reader'].clear()
VIDEO_POOL_SET['writer'].clear()
+2 -3
View File
@@ -5,7 +5,7 @@ import numpy
from tqdm import tqdm
import facefusion.workflows.image_to_video as image_to_video
from facefusion import ffprobe, logger, process_manager, state_manager, translator, video_manager
from facefusion import logger, process_manager, state_manager, translator, video_manager
from facefusion.audio import create_empty_audio_frame, get_audio_frame, get_voice_frame
from facefusion.common_helper import get_first
from facefusion.filesystem import filter_audio_paths
@@ -138,8 +138,7 @@ def process_stream_frames() -> ErrorCode:
frame_range = range(trim_frame_start, trim_frame_end)
if frame_range:
video_metadata = ffprobe.extract_static_video_metadata(state_manager.get_item('target_path'))
video_writer = video_manager.get_writer(state_manager.get_item('target_path'), video_metadata, temp_video_fps, temp_video_resolution, output_video_resolution, state_manager.get_item('output_video_fps'))
video_writer = video_manager.get_writer(state_manager.get_item('target_path'), temp_video_fps, temp_video_resolution, output_video_resolution, state_manager.get_item('output_video_fps'))
frame_look_ahead = image_to_video.calculate_frame_look_ahead(temp_video_resolution)
with tqdm(total = len(frame_range), desc = translator.get('processing'), unit = 'frame', ascii = ' =', disable = state_manager.get_item('log_level') in [ 'warn', 'error' ]) as progress:
+1 -1
View File
@@ -186,7 +186,7 @@ def write_stream_frame(video_writer : VideoWriter, futures : List[Future[Tuple[i
if not future.cancelled():
_, temp_vision_frame = future.result()
video_manager.write_video_writer_frame(video_writer, temp_vision_frame)
video_manager.write_video_writer(video_writer, temp_vision_frame)
progress.update()
+7 -12
View File
@@ -1,7 +1,7 @@
from shutil import which
from facefusion import ffmpeg_builder
from facefusion.ffmpeg_builder import chain, concat, convert_color_space, keep_video_alpha, restrict_color_transfer, run, select_frame_range, set_audio_quality, set_audio_sample_size, set_faststart, set_filter_thread_count, set_global_thread_count, set_input_seek, set_output_format, set_stream_mode, set_video_encoder, set_video_fps, set_video_quality, set_video_tag
from facefusion.ffmpeg_builder import chain, concat, convert_color_space, keep_video_alpha, restrict_color_transfer, run, seek_to, select_frame_range, set_audio_quality, set_audio_sample_size, set_faststart, set_output_format, set_stream_mode, set_thread_count, set_video_encoder, set_video_fps, set_video_quality, set_video_tag
def test_run() -> None:
@@ -41,9 +41,9 @@ def test_set_stream_mode() -> None:
assert set_stream_mode('v4l2') == [ '-f', 'v4l2' ]
def test_set_input_seek() -> None:
assert set_input_seek(0.0) == [ '-ss', '0.0' ]
assert set_input_seek(1.5) == [ '-ss', '1.5' ]
def test_seek_to() -> None:
assert seek_to(0.0) == [ '-ss', '0.0' ]
assert seek_to(1.5) == [ '-ss', '1.5' ]
def test_set_output_format() -> None:
@@ -92,14 +92,9 @@ def test_set_audio_quality() -> None:
assert set_audio_quality('flac', 100) == []
def test_set_global_thread_count() -> None:
assert set_global_thread_count(8) == [ '-threads', '8' ]
assert set_global_thread_count(16) == [ '-threads', '16' ]
def test_set_filter_thread_count() -> None:
assert set_filter_thread_count(8) == [ '-filter_threads', '8' ]
assert set_filter_thread_count(16) == [ '-filter_threads', '16' ]
def test_set_thread_count() -> None:
assert set_thread_count(8) == [ '-threads', '8' ]
assert set_thread_count(16) == [ '-threads', '16' ]
def test_set_faststart() -> None:
+13 -12
View File
@@ -9,7 +9,7 @@ from facefusion.download import conditional_download
from facefusion.ffprobe import extract_video_metadata
from facefusion.frame_store import get_frame_store
from facefusion.temp_helper import create_temp_directory, get_temp_file_path
from facefusion.video_manager import clear_video_pool, close_video_writer, conditional_set_video_reader_position, get_reader, get_writer, read_video_reader_frame, read_video_reader_window, refresh_video_reader, write_video_writer_frame
from facefusion.video_manager import clear_video_pool, close_video_writer, conditional_set_video_reader_position, get_reader, get_writer, read_video_reader_frame, read_video_reader_window, refresh_video_reader, write_video_writer
from .helper import get_test_example_file, get_test_examples_directory
@@ -134,24 +134,23 @@ def test_read_video_reader_window() -> None:
#todo: run mutation testing, strip down to the minimum, test with real data
def test_get_writer() -> None:
target_path = get_test_example_file('target-240p-25fps.mp4')
video_metadata = extract_video_metadata(target_path)
create_temp_directory(target_path)
video_writer = get_writer(target_path, video_metadata, 25.0, (426, 226), (426, 226), 25.0)
video_writer = get_writer(target_path, 25.0, (426, 226), (426, 226), 25.0)
assert get_writer(target_path, video_metadata, 25.0, (426, 226), (426, 226), 25.0) is video_writer
assert get_writer(target_path, 25.0, (426, 226), (426, 226), 25.0) is video_writer
#todo: needs review - [testing] question if the assertions are good
#todo: run mutation testing, strip down to the minimum, test with real data
def test_write_video_writer_frame() -> None:
def test_write_video_writer() -> None:
target_path = get_test_example_file('target-240p-25fps.mp4')
create_temp_directory(target_path)
video_reader = get_reader(target_path)
video_writer = get_writer(target_path, video_reader.get('metadata'), 25.0, (426, 226), (426, 226), 25.0)
video_writer = get_writer(target_path, 25.0, (426, 226), (426, 226), 25.0)
for frame_number in range(25):
vision_frame = read_video_reader_frame(video_reader)
write_video_writer_frame(video_writer, vision_frame)
write_video_writer(video_writer, vision_frame)
assert close_video_writer(video_writer) is True
@@ -170,9 +169,9 @@ def test_close_video_writer() -> None:
target_path = get_test_example_file('target-240p-30fps.mp4')
create_temp_directory(target_path)
video_reader = get_reader(target_path)
video_writer = get_writer(target_path, video_reader.get('metadata'), 30.0, (426, 226), (426, 226), 30.0)
video_writer = get_writer(target_path, 30.0, (426, 226), (426, 226), 30.0)
vision_frame = read_video_reader_frame(video_reader)
write_video_writer_frame(video_writer, vision_frame)
write_video_writer(video_writer, vision_frame)
assert close_video_writer(video_writer) is True
@@ -183,13 +182,15 @@ def test_clear_video_pool() -> None:
target_path = get_test_example_file('target-240p-25fps.mp4')
create_temp_directory(target_path)
video_reader = get_reader(target_path)
video_writer = get_writer(target_path, video_reader.get('metadata'), 25.0, (426, 226), (426, 226), 25.0)
video_writer = get_writer(target_path, 25.0, (426, 226), (426, 226), 25.0)
vision_frame = read_video_reader_frame(video_reader)
write_video_writer(video_writer, vision_frame)
clear_video_pool()
if is_windows():
assert video_reader.get('process').returncode == 1
assert video_writer.get('process').returncode == 1
if is_linux() or is_macos():
assert video_reader.get('process').returncode == -9
assert video_writer.get('process').returncode == -9
assert video_writer.get('process').returncode == 0