Update convert_to_dnx.py

This commit is contained in:
2025-09-02 17:57:07 +00:00
parent d931d2a798
commit f7471032ab

View File

@@ -22,8 +22,6 @@ import pprint
# https://askubuntu.com/questions/907398/how-to-convert-a-video-with-ffmpeg-into-the-dnxhd-dnxhr-format
# https://en.wikipedia.org/wiki/List_of_Avid_DNxHD_resolutions
# Resolution,Frame Width, Frame Height,Chroma Subsampling,Bits,Frames Per Second,Megabits per second,Minutes per Gigabyte
dnx_rates = """Avid DNxHD 440x,1920,1080,p,yuv422p10,60/1,440,0.325
@@ -94,6 +92,7 @@ Avid DNxHD 45,1280,720,p,yuv422p,24000/1001,43,3.504
available_dnx_resolutions = []
dnx_reader = csv.DictReader(io.StringIO(dnx_rates),
["name","width","height","interlaced",
@@ -105,9 +104,12 @@ for res in dnx_reader:
available_dnx_resolutions = sorted(available_dnx_resolutions,
key=lambda x: float(x["mins_per_gig"]), reverse=True)
# ffmpeg -loglevel error -f lavfi -i testsrc2 -c:v dnxhd -f null -
print(f"Loaded {len(available_dnx_resolutions)} available DNxHD resolutions...")
result = subprocess.run(["/usr/local/bin/ffmpeg",
print(f"Detecting available DNxHD codecs...")
result = subprocess.run(["ffmpeg",
"-hide_banner",
"-loglevel",
"error",
@@ -121,20 +123,20 @@ result = subprocess.run(["/usr/local/bin/ffmpeg",
"null",
"-"], capture_output=True)
# result.check_returncode()
ffmpeg_dnx_resolutions = []
for line in result.stderr.splitlines():
line = line.decode("utf-8")
matches = re.match(".*Frame size: (\d+)x(\d+)([pi]).*", line)
matches = re.match(r".*Frame size: (\d+)x(\d+)([pi]).*", line)
if matches is not None:
width, height = matches[1], matches[2]
interlace = matches[3]
matches = re.match(".*format: (yuv\w+).*", line)
matches = re.match(r".*format: (yuv\w+).*", line)
assert matches
fmt = matches[1]
matches = re.match(".*bitrate: (\d+)Mbps.*", line)
matches = re.match(r".*bitrate: (\d+)Mbps.*", line)
assert matches
mbps = matches[1]
ffmpeg_dnx_resolutions += [{
@@ -145,17 +147,16 @@ for line in result.stderr.splitlines():
"interlaced": interlace
}]
print(f"Detected {len(ffmpeg_dnx_resolutions)} codec resolutions...")
def filter_pred(res):
def inner_pred(ff_res):
# print(res, ff_res)
# input("Press return...")
result = ff_res["interlaced"] == res["interlaced"] and \
ff_res["width"] == res["width"] and \
ff_res["height"] == res["height"] and \
ff_res["pix_fmt"] == res["pix_fmt"] and \
ff_res["mb"] == res["mb"]
# print("Result", result)
return result
found = filter(inner_pred,ffmpeg_dnx_resolutions)
@@ -163,10 +164,11 @@ def filter_pred(res):
available_dnx_resolutions = list(filter(filter_pred, available_dnx_resolutions))
# probe input file
print(f"{len(available_dnx_resolutions)} resolutions are available and detected...")
input_file = sys.argv[1]
result = subprocess.run(["/usr/local/bin/ffprobe","-hide_banner","-of","json",
print(f"Probing input file {input_file}")
result = subprocess.run(["ffprobe","-hide_banner","-of","json",
"-show_streams","-select_streams","v",
input_file], capture_output=True)
@@ -179,6 +181,12 @@ frame_size = (probe_output["streams"][0]["width"], probe_output["streams"][0]["h
frame_rate = probe_output["streams"][0]["r_frame_rate"]
field_order_progressive = "p" if probe_output["streams"][0]["field_order"] == "progressive" else "i"
print("Input file characteristics...")
print(f" - pix fmt = {pix_fmt}")
print(f" - frame size = {frame_size[0]}x{frame_size[1]}")
print(f" - frame rate = {frame_rate}")
print(f" - field order = {field_order_progressive}")
def filter_for_frame_rate(res):
return res["frame_rate"] == frame_rate and res["interlaced"] == field_order_progressive
@@ -186,15 +194,17 @@ def filter_for_scale(res):
return res["width"] == frame_size[0] and res["height"] == frame_size[1] and \
res["interlaced"] == field_order_progressive
# print("Available DNx resolutions:")
print("Available DNx resolutions:")
for n in filter(lambda r: filter_for_frame_rate(r) and filter_for_scale(r), available_dnx_resolutions):
print(f"-vcodec dnxhd -b:v {n['mb']}M -pix_fmt {n['pix_fmt']}")
print(f" -vcodec dnxhd -b:v {n['mb']}M -pix_fmt {n['pix_fmt']}")
# print("Available with scaling:")
print("Available with scaling:")
for n in filter(filter_for_frame_rate, available_dnx_resolutions):
# https://superuser.com/questions/991371/ffmpeg-scale-and-pad
print(f"""-vf "scale=w={n['width']}:h={n['height']}:force_original_aspect_ratio=1,"""
print(f""" -vf "scale=w={n['width']}:h={n['height']}:force_original_aspect_ratio=1,"""
f"""pad={n['width']}:{n['height']}:(ow-iw)/2:(oh-ih)/2" -vcodec dnxhd -b:v {n['mb']}M -pix_fmt {n['pix_fmt']}""")