diff --git a/proxima/queuer/resolve.py b/proxima/queuer/resolve.py index a2b16f8..80dab38 100644 --- a/proxima/queuer/resolve.py +++ b/proxima/queuer/resolve.py @@ -286,6 +286,7 @@ def get_resolve_proxy_jobs(media_pool_items): "file_name": cp["File Name"], "file_path": cp["File Path"], "duration": cp["Duration"], + "data_level": cp["Data Level"], "resolution": str(cp["Resolution"]).split("x"), "frames": int(cp["Frames"]), "fps": float(cp["FPS"]), diff --git a/proxima/worker/ffmpeg/utils.py b/proxima/worker/ffmpeg/utils.py index 30df8f2..cf33fef 100644 --- a/proxima/worker/ffmpeg/utils.py +++ b/proxima/worker/ffmpeg/utils.py @@ -52,7 +52,7 @@ def frac_to_dec(fraction: str): return float(f) -def get_media_info(file): +def ffprobe(file): """Get media info from file using ffprobe""" cmd = f'ffprobe -v quiet -print_format json -show_format -show_streams "{file}"' diff --git a/proxima/worker/launch_workers.py b/proxima/worker/launch_workers.py index 4c44611..7f4f3f4 100644 --- a/proxima/worker/launch_workers.py +++ b/proxima/worker/launch_workers.py @@ -206,7 +206,7 @@ def main(workers: int = 0): launch_workers(prompt_worker_amount(cpu_cores), queue_name) print(f"[green]Done![/]") - core.app_exit(0, 5) + core.app_exit(0, 2) if __name__ == "__main__": diff --git a/proxima/worker/tasks/encode/tasks.py b/proxima/worker/tasks/encode/tasks.py index 2549873..ff77645 100644 --- a/proxima/worker/tasks/encode/tasks.py +++ b/proxima/worker/tasks/encode/tasks.py @@ -62,27 +62,46 @@ def encode_proxy(self, job): ps = job["proxy_settings"] ffmpeg_command = [ + # INPUT "ffmpeg", "-y", # Never prompt! - *ps["misc_args"], # User global settings + *ps["misc_args"], "-i", job["file_path"], + # VIDEO "-c:v", ps["codec"], "-profile:v", ps["profile"], "-vsync", "-1", # Necessary to match VFR + # TODO: Format this better + # It's hard to format this. Every arg behind the -vf flag + # should be separated by a literal comma and NO SPACES to string them together as per ffmpeg syntax. + # Any optional args must provide their own literal commas so as not to leave them stray + # if disabled... Inline functions here are also confusing and "magical". + # But we don't want to run them queuer side, only on final queueables. + # labels: enhancement + # VIDEO FILTERS "-vf", f"scale=-2:{int(job['proxy_settings']['vertical_res'])}," + f"scale={utils.get_input_level(job)}:out_range=limited, " f"{utils.get_flip(job)}" - f"format={ps['pix_fmt']}", + f"format={ps['pix_fmt']}" + if ps["pix_fmt"] + else "", + # AUDIO "-c:a", ps["audio_codec"], "-ar", ps["audio_samplerate"], + # TIMECODE "-timecode", job["start_tc"], + # FLAGS + "-movflags", + "+write_colr", + # OUTPUT output_path, ] diff --git a/proxima/worker/utils.py b/proxima/worker/utils.py index eae7323..b952c79 100644 --- a/proxima/worker/utils.py +++ b/proxima/worker/utils.py @@ -6,6 +6,7 @@ from ..app.utils import core from ..settings.manager import SettingsManager +from ..worker.ffmpeg.utils import ffprobe core.install_rich_tracebacks() @@ -68,6 +69,39 @@ def get_queue(): return file.read() +def get_input_level(job): + """ + Match Resolve's set data levels ("Auto", "Full" or "Video") + + Uses ffprobe to probe file for levels if Resolve data levels are set to Auto. + """ + + def probe_for_input_range(job): + """ + Probe file with ffprobe for colour range + and map to ffmpeg 'in_range' value ("full" or "limited") + """ + + input = job["file_path"] + info = ffprobe(file=input)["streams"][0] + color_data = {k: v for k, v in info.items() if "color" in k} + logger.debug(f"[magenta]Probed color data:\n{color_data}") + + switch = { + "pc": "in_range=full", + "tv": "in_range=limited", + } + return switch[info["color_range"]] + + switch = { + "Auto": probe_for_input_range(job), + "Full": "in_range=full", + "Video": "in_range=limited", + } + + return switch[job["data_level"]] + + def get_flip(job): flip = str() diff --git a/version_constraint_key b/version_constraint_key index a3dfe28..9ae02c3 100644 --- a/version_constraint_key +++ b/version_constraint_key @@ -1 +1 @@ -constantly-cool-corgi \ No newline at end of file +annually-awaited-akita \ No newline at end of file