Something went wrong. Try again.
🎥 Command line media player
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158-- 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
require "mp.msg"
local script_name = mp.get_script_name()local detect_label = string.format("%s-detect", script_name)local pullup_label = string.format("%s", script_name)local dominance_label = string.format("%s-dominance", script_name)local ivtc_detect_label = string.format("%s-ivtc-detect", script_name)local timerlocal progressive, interlaced_tff, interlaced_bff, interlaced = 0, 1, 2, 3
-- number of seconds to gather cropdetect datalocal detect_seconds = tonumber(mp.get_opt(string.format("%s.detect_seconds", script_name)))if not detect_seconds then detect_seconds = 4end
local function del_filter_if_present(label) -- necessary because mp.command('vf del @label:filter') raises an -- error if the filter doesn't exist local vfs = mp.get_property_native("vf")
for i,vf in pairs(vfs) do if vf["label"] == label then table.remove(vfs, i) mp.set_property_native("vf", vfs) return true end end return falseend
local function add_vf(label, filter) return mp.command(('vf add @%s:%s'):format(label, filter))end
local function stop_detect() del_filter_if_present(detect_label) del_filter_if_present(ivtc_detect_label) timer = nilend
local function judge(label) -- get the metadata local result = mp.get_property_native(string.format("vf-metadata/%s", label)) local num_tff = tonumber(result["lavfi.idet.multiple.tff"]) local num_bff = tonumber(result["lavfi.idet.multiple.bff"]) local num_progressive = tonumber(result["lavfi.idet.multiple.progressive"]) local num_undetermined = tonumber(result["lavfi.idet.multiple.undetermined"]) local num_interlaced = num_tff + num_bff local num_determined = num_interlaced + num_progressive
mp.msg.verbose(label.." progressive = "..num_progressive) mp.msg.verbose(label.." interlaced-tff = "..num_tff) mp.msg.verbose(label.." interlaced-bff = "..num_bff) mp.msg.verbose(label.." undetermined = "..num_undetermined)
if num_determined < num_undetermined then mp.msg.warn("majority undetermined frames") end if num_progressive > 20*num_interlaced then return progressive elseif num_tff > 10*num_bff then return interlaced_tff elseif num_bff > 10*num_tff then return interlaced_bff else return interlaced endend
local function select_filter() -- handle the first detection filter results local verdict = judge(detect_label) local ivtc_verdict = judge(ivtc_detect_label) local dominance = "auto" if verdict == progressive then mp.msg.info("progressive: doing nothing") stop_detect() del_filter_if_present(dominance_label) del_filter_if_present(pullup_label) return else if verdict == interlaced_tff then dominance = "tff" add_vf(dominance_label, 'setfield=mode='..dominance) elseif verdict == interlaced_bff then dominance = "bff" add_vf(dominance_label, 'setfield=mode='..dominance) else del_filter_if_present(dominance_label) end end
-- handle the ivtc detection filter results if ivtc_verdict == progressive then mp.msg.info(string.format("telecined with %s field dominance: using pullup", dominance)) stop_detect() else mp.msg.info("interlaced with " .. dominance .. " field dominance: setting deinterlace property") del_filter_if_present(pullup_label) mp.set_property("deinterlace","yes") stop_detect() endend
local function start_detect() -- exit if detection is already in progress if timer then mp.msg.warn("already detecting!") return end
mp.set_property("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')) then mp.msg.error("failed to insert detection filters") return end
-- wait to gather data timer = mp.add_timeout(detect_seconds, select_filter)end
mp.add_key_binding("ctrl+d", script_name, start_detect)