Spaces:
Sleeping
Sleeping
Update dvd_converter.py
Browse files- dvd_converter.py +63 -41
dvd_converter.py
CHANGED
|
@@ -1250,26 +1250,23 @@ def build_pre_scale_chain(info: dict, cfg: argparse.Namespace) -> str:
|
|
| 1250 |
else:
|
| 1251 |
log.info(" βοΈ denoise skipped (--no-denoise)")
|
| 1252 |
|
| 1253 |
-
# 4.
|
| 1254 |
-
|
| 1255 |
-
|
| 1256 |
|
| 1257 |
return ",".join(filters) if filters else "null"
|
| 1258 |
|
| 1259 |
|
| 1260 |
def build_filter_complex(pre_scale: str, cfg: argparse.Namespace) -> str:
|
| 1261 |
-
"""Build the full filter_complex string with
|
| 1262 |
-
|
| 1263 |
-
|
| 1264 |
-
|
| 1265 |
-
|
| 1266 |
-
|
| 1267 |
-
|
| 1268 |
-
|
| 1269 |
-
|
| 1270 |
-
β’ The frame always touches at least two edges; the player scales the
|
| 1271 |
-
whole frame to fill its screen, so the video fills the horizontal
|
| 1272 |
-
extent and the player shrinks it to keep the height in bounds.
|
| 1273 |
"""
|
| 1274 |
|
| 1275 |
deflicker_part = (
|
|
@@ -1297,35 +1294,60 @@ def build_filter_complex(pre_scale: str, cfg: argparse.Namespace) -> str:
|
|
| 1297 |
|
| 1298 |
post_filter = (f"{cfg.post_output_filter}," if cfg.post_output_filter else "")
|
| 1299 |
|
| 1300 |
-
#
|
| 1301 |
-
|
| 1302 |
-
# force_original_aspect_ratio=decrease ensures the result fits
|
| 1303 |
-
# inside WΓH without cropping.
|
| 1304 |
-
# Step 2: pad to exact target dimensions, centring the scaled picture,
|
| 1305 |
-
# filling the remainder with black.
|
| 1306 |
-
letterbox = (
|
| 1307 |
-
f"scale={cfg.width}:{cfg.height}"
|
| 1308 |
-
f":force_original_aspect_ratio=decrease"
|
| 1309 |
-
f":flags={cfg.scale_flags},"
|
| 1310 |
-
f"pad={cfg.width}:{cfg.height}"
|
| 1311 |
-
f":(ow-iw)/2:(oh-ih)/2"
|
| 1312 |
-
f":black"
|
| 1313 |
-
)
|
| 1314 |
|
| 1315 |
-
|
| 1316 |
-
|
| 1317 |
-
|
| 1318 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1319 |
|
| 1320 |
return (
|
| 1321 |
-
|
| 1322 |
-
|
| 1323 |
-
|
| 1324 |
-
|
| 1325 |
-
f"{
|
| 1326 |
-
|
| 1327 |
-
|
| 1328 |
-
"null[out]"
|
| 1329 |
).replace(",null[out]", "[out]").replace("null[out]", "[out]")
|
| 1330 |
|
| 1331 |
|
|
|
|
| 1250 |
else:
|
| 1251 |
log.info(" βοΈ denoise skipped (--no-denoise)")
|
| 1252 |
|
| 1253 |
+
# 4. Final scale/fill is handled in build_filter_complex (letterbox or blur mode)
|
| 1254 |
+
fill_mode = getattr(cfg, "bg_fill_mode", "letterbox")
|
| 1255 |
+
log.info(" β
fill mode: %s β final scale/pad applied in filter_complex", fill_mode)
|
| 1256 |
|
| 1257 |
return ",".join(filters) if filters else "null"
|
| 1258 |
|
| 1259 |
|
| 1260 |
def build_filter_complex(pre_scale: str, cfg: argparse.Namespace) -> str:
|
| 1261 |
+
"""Build the full filter_complex string with selectable fill mode + deflicker + eq.
|
| 1262 |
+
|
| 1263 |
+
bg_fill_mode (cfg attribute, default "letterbox"):
|
| 1264 |
+
"letterbox" β scale to fit inside WΓH preserving aspect ratio, pad remainder
|
| 1265 |
+
with solid black bars. No cropping, no blur, no stretching.
|
| 1266 |
+
This is standard Letterboxing / Pillarboxing behaviour.
|
| 1267 |
+
"blur" β scale to fill WΓH, then composite the sharp foreground (scaled
|
| 1268 |
+
to fit) over a blurred, darkened copy of the same frame.
|
| 1269 |
+
Produces an aesthetically filled background instead of bars.
|
|
|
|
|
|
|
|
|
|
| 1270 |
"""
|
| 1271 |
|
| 1272 |
deflicker_part = (
|
|
|
|
| 1294 |
|
| 1295 |
post_filter = (f"{cfg.post_output_filter}," if cfg.post_output_filter else "")
|
| 1296 |
|
| 1297 |
+
# Resolve bg_fill_mode β attribute may be missing on hand-built cfg objects
|
| 1298 |
+
fill_mode = getattr(cfg, "bg_fill_mode", "letterbox")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1299 |
|
| 1300 |
+
# ββ MODE: letterbox (black bars) βββββββββββββββββββββββββββββββββββββββββ
|
| 1301 |
+
# scale down to fit entirely inside WΓH (never upscale beyond target),
|
| 1302 |
+
# then pad to exact dimensions centring the picture with black.
|
| 1303 |
+
if fill_mode != "blur":
|
| 1304 |
+
log.info(
|
| 1305 |
+
" β
fill=letterbox: scaleβ%dΓ%d (fit) + pad black [%s]",
|
| 1306 |
+
cfg.width, cfg.height, cfg.scale_flags,
|
| 1307 |
+
)
|
| 1308 |
+
fill_chain = (
|
| 1309 |
+
f"[0:v]{pre_scale}[prescaled];"
|
| 1310 |
+
f"[prescaled]"
|
| 1311 |
+
f"scale={cfg.width}:{cfg.height}"
|
| 1312 |
+
f":force_original_aspect_ratio=decrease"
|
| 1313 |
+
f":flags={cfg.scale_flags},"
|
| 1314 |
+
f"pad={cfg.width}:{cfg.height}"
|
| 1315 |
+
f":(ow-iw)/2:(oh-ih)/2"
|
| 1316 |
+
f":black"
|
| 1317 |
+
f"[filled];"
|
| 1318 |
+
)
|
| 1319 |
+
|
| 1320 |
+
# ββ MODE: blur background ββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 1321 |
+
# Split the pre-scaled stream into foreground (fit-scaled) and background
|
| 1322 |
+
# (fill-scaled β blurred β darkened), then overlay the foreground centred.
|
| 1323 |
+
else:
|
| 1324 |
+
ov_x = cfg.overlay_x if hasattr(cfg, "overlay_x") else cfg.overlay_x_expr
|
| 1325 |
+
ov_y = cfg.overlay_y if hasattr(cfg, "overlay_y") else cfg.overlay_y_expr
|
| 1326 |
+
log.info(
|
| 1327 |
+
" β
fill=blur: avgblur r=%d bg_bright=%.2f bg_sat=%.2f [%s]",
|
| 1328 |
+
cfg.blur_radius, cfg.bg_brightness, cfg.bg_saturation, cfg.bg_scale_flags,
|
| 1329 |
+
)
|
| 1330 |
+
fill_chain = (
|
| 1331 |
+
f"[0:v]{pre_scale}[prescaled];"
|
| 1332 |
+
"[prescaled]split=2[fg][bg_src];"
|
| 1333 |
+
f"[fg]scale={cfg.width}:-2:flags={cfg.scale_flags}[fg_scaled];"
|
| 1334 |
+
f"[bg_src]scale={cfg.width}:{cfg.height}:flags={cfg.bg_scale_flags},"
|
| 1335 |
+
f"avgblur={cfg.blur_radius},"
|
| 1336 |
+
f"eq=brightness={cfg.bg_brightness}"
|
| 1337 |
+
f":saturation={cfg.bg_saturation}"
|
| 1338 |
+
f":contrast={cfg.bg_contrast}"
|
| 1339 |
+
f":gamma={cfg.bg_gamma}[bg];"
|
| 1340 |
+
f"[bg][fg_scaled]overlay={ov_x}:{ov_y}[filled];"
|
| 1341 |
+
)
|
| 1342 |
|
| 1343 |
return (
|
| 1344 |
+
fill_chain
|
| 1345 |
+
+ "[filled]"
|
| 1346 |
+
+ deflicker_part
|
| 1347 |
+
+ sharpen_eq_part
|
| 1348 |
+
+ f"setsar={cfg.sar},"
|
| 1349 |
+
+ post_filter
|
| 1350 |
+
+ "null[out]"
|
|
|
|
| 1351 |
).replace(",null[out]", "[out]").replace("null[out]", "[out]")
|
| 1352 |
|
| 1353 |
|