mirror of
https://github.com/mpv-player/mpv
synced 2025-04-23 15:47:54 +00:00
- lint - better error message through check_error when mpv api(s) return with an error - add function hook_add - add function hook_continue - add event handler for MPV_EVENT_HOOK
152 lines
5.0 KiB
Python
152 lines
5.0 KiB
Python
# This script uses the lavfi idet filter to automatically insert the
|
|
# appropriate deinterlacing filter based on a short section of the
|
|
# currently playing video.
|
|
#
|
|
# It registers the key-binding ctrl+d, which when pressed, inserts the filters
|
|
# ``vf=idet,lavfi-pullup,idet``. After 4 seconds, it removes these
|
|
# filters and decides whether the content is progressive, interlaced, or
|
|
# telecined and the interlacing field dominance.
|
|
#
|
|
# Based on this information, it may set mpv's ``deinterlace`` property (which
|
|
# usually inserts the bwdif filter), or insert the ``pullup`` filter if the
|
|
# content is telecined. It also sets field dominance with lavfi setfield.
|
|
#
|
|
# OPTIONS:
|
|
# The default detection time may be overridden by adding
|
|
#
|
|
# --script-opts=autodeint.detect_seconds=<number of seconds>
|
|
#
|
|
# to mpv's arguments. This may be desirable to allow idet more
|
|
# time to collect data.
|
|
#
|
|
# To see counts of the various types of frames for each detection phase,
|
|
# the verbosity can be increased with
|
|
#
|
|
# --msg-level=autodeint=v
|
|
|
|
from mpvclient import mpv # type: ignore
|
|
|
|
script_name = mpv.name
|
|
detect_label = f"{script_name}-detect"
|
|
pullup_label = script_name
|
|
dominance_label = f"{script_name}-dominance"
|
|
ivtc_detect_label = f"{script_name}-ivtc-detect"
|
|
|
|
progressive, interlaced_tff, interlaced_bff, interlaced = 0, 1, 2, 3
|
|
|
|
# number of seconds to gather cropdetect data
|
|
try:
|
|
detect_seconds = float(mpv.get_opt(f"{script_name}.detect_seconds", 4))
|
|
except ValueError:
|
|
detect_seconds = 4
|
|
|
|
|
|
def del_filter_if_present(label):
|
|
# necessary because mp.command('vf del @label:filter') raises an
|
|
# error if the filter doesn't exist
|
|
vfs = mpv.get_property_node("vf")
|
|
|
|
for i, vf in enumerate(vfs):
|
|
if vf["label"] == label:
|
|
vfs.pop(i)
|
|
mpv.set_property_node("vf", vfs)
|
|
return True
|
|
return False
|
|
|
|
|
|
def add_vf(label, filter): # noqa: A002
|
|
return mpv.command_string(f"vf add @{label}:{filter}")
|
|
|
|
|
|
def stop_detect():
|
|
del_filter_if_present(detect_label)
|
|
del_filter_if_present(ivtc_detect_label)
|
|
|
|
|
|
def judge(label):
|
|
# get the metadata
|
|
result = mpv.get_property_node(f"vf-metadata/{label}")
|
|
num_tff = float(result["lavfi.idet.multiple.tff"])
|
|
num_bff = float(result["lavfi.idet.multiple.bff"])
|
|
num_progressive = float(result["lavfi.idet.multiple.progressive"])
|
|
num_undetermined = float(result["lavfi.idet.multiple.undetermined"])
|
|
num_interlaced = num_tff + num_bff
|
|
num_determined = num_interlaced + num_progressive
|
|
|
|
mpv.info(label + " progressive = " + str(num_progressive))
|
|
mpv.info(label + " interlaced-tff = " + str(num_tff))
|
|
mpv.info(label + " interlaced-bff = " + str(num_bff))
|
|
mpv.info(label + " undetermined = " + str(num_undetermined))
|
|
|
|
if num_determined < num_undetermined:
|
|
mpv.warn("majority undetermined frames")
|
|
|
|
if num_progressive > 20*num_interlaced:
|
|
return progressive
|
|
elif num_tff > 10*num_bff:
|
|
return interlaced_tff
|
|
elif num_bff > 10*num_tff:
|
|
return interlaced_bff
|
|
else:
|
|
return interlaced
|
|
|
|
|
|
def select_filter():
|
|
# handle the first detection filter results
|
|
verdict = judge(detect_label)
|
|
ivtc_verdict = judge(ivtc_detect_label)
|
|
dominance = "auto"
|
|
if verdict == progressive:
|
|
mpv.info("progressive: doing nothing")
|
|
stop_detect()
|
|
del_filter_if_present(dominance_label)
|
|
del_filter_if_present(pullup_label)
|
|
return
|
|
else:
|
|
if verdict == interlaced_tff:
|
|
dominance = "tff"
|
|
add_vf(dominance_label, "setfield=mode=" + dominance)
|
|
elif verdict == interlaced_bff:
|
|
dominance = "bff"
|
|
add_vf(dominance_label, "setfield=mode=" + dominance)
|
|
else:
|
|
del_filter_if_present(dominance_label)
|
|
|
|
# handle the ivtc detection filter results
|
|
if ivtc_verdict == progressive:
|
|
mpv.info(f"telecined with {dominance} field dominance: using pullup")
|
|
stop_detect()
|
|
else:
|
|
mpv.info("interlaced with " + dominance +
|
|
" field dominance: setting deinterlace property")
|
|
del_filter_if_present(pullup_label)
|
|
mpv.set_property_string("deinterlace","yes")
|
|
stop_detect()
|
|
|
|
|
|
@mpv.add_binding("ctrl+d")
|
|
def start_detect():
|
|
# exit if detection is already in progress
|
|
if "select_filter" in mpv.timers:
|
|
mpv.warn("already detecting!")
|
|
return
|
|
|
|
mpv.set_property_string("deinterlace", "no")
|
|
del_filter_if_present(pullup_label)
|
|
del_filter_if_present(dominance_label)
|
|
|
|
# insert the detection filters
|
|
if not (add_vf(detect_label, "idet") and
|
|
add_vf(dominance_label, "setfield=mode=auto") and
|
|
add_vf(pullup_label, "lavfi-pullup") and
|
|
add_vf(ivtc_detect_label, "idet")):
|
|
mpv.error("failed to insert detection filters")
|
|
return
|
|
|
|
def wrap_select_filter():
|
|
select_filter()
|
|
mpv.clear_timer("select_filter")
|
|
|
|
# wait to gather data
|
|
mpv.add_timeout(detect_seconds, wrap_select_filter, name="select_filter")
|