From 019fb5346ce1020c1e086227fdf47d1a26b7bbb5 Mon Sep 17 00:00:00 2001 From: bitingsock Date: Sun, 28 Feb 2021 22:03:07 +0000 Subject: [PATCH] Document user options and add some new features (#26) * Document user options and add some new features I realized I've been adding to and adjusting this script for a while now and almost lost it in a reformat. I also included some requested feature's from the issue tracker. I'll comment inline to clarify some changes. * Update speed-transition.lua * Update README.md * Update speed-transition.lua * Update speed-transition.lua --- README.md | 6 +- speed-transition.lua | 133 ++++++++++++++++++++++++++++++++++--------- 2 files changed, 110 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index b9973f8..2574ff9 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,6 @@ The script looks for the next subtitle and if it is ahead by 5 (default) seconds ### Usage For the script to work it is necessary to have an appropriate 'text' subtitle selected and visible. -If you want to use it with local files it is necessary to either have `--cache=yes` or `--demuxer-readahead-secs=10` options enabled in your config/cli. A value of `demuxer-readahead-secs>=10` is recommended. The same applies to `--cache-secs` option if it has been set. - The script works best in `video-sync=audio` mode (the default in mpv), because it will then be able to minimize frame drops on speed transition from high->normal. Stutter-free playback is the result. Sensible defaults have been set, but if you want to change the `lookahead` value take care to not set it larger than what the buffers can provide. This applies to embedded subtitles and not external. @@ -23,6 +21,10 @@ Key Bind|Effect `alt + j`|Toggle sub visibility on/off (non-styled subs) `alt + '+'`|Increase speedup `alt + '-'`|Decrease speedup +`alt + '0'`|Increase leadin (time before the next subtitle to return to normal speed) +`alt + '9'`|Decrease leadin +`alt + '8'`|Increase Look ahead (if the next subtitle is closer than this, don't speed up) +`alt + '7'`|Decrease Look ahead ## subselect diff --git a/speed-transition.lua b/speed-transition.lua index 0dbf7ed..0b2ca1b 100644 --- a/speed-transition.lua +++ b/speed-transition.lua @@ -1,12 +1,33 @@ -lookahead = 5 -speedup = 2.5 -leadin = 1 --range 0-2 -skipmode = false -directskip = false ---------------- +lookahead = 5 --if the next subtitle appears after this threshold then speedup +speedup = 2 --the value that "speed" is set to during speedup +leadin = 1 --seconds to stop short of the next subtitle +skipmode = false --instead of speeding up playback seek to the next known subtitle +maxSkip = 5 --max seek distance (seconds) when skipmode is enabled +minSkip = leadin --this is also configurable but setting it too low can actually make your watch time longer +skipdelay = 1 --in skip mode, this setting delays each skip by x seconds (must be >=0) +directskip = false --seek to next known subtitle (must be in cache) no matter how far away +dropOnAVdesync = true +--Because mpv syncs subtitles to audio it is possible that if audio processing lags behind-- +--video processing then normal playback may not resume in sync with the video. If "avsync" > leadin-- +--then this disables the audio so that we can ensure normal playback resumes on time. +ignorePattern = false --if true, subtitles are matched against "subPattern". A successful match will be treated as if there was no subtitle +subPattern = "^[#♯♩♪♬♫🎵🎶%[%(]+.*[#♯♩♪♬♫🎵🎶%]%)]+$" +---------------User options above this line-- +readahead_secs = mp.get_property_native("demuxer-readahead-secs") normalspeed=mp.get_property_native("speed") +function shouldIgnore(subtext) + if ignorePattern and subtext and subtext~="" then + local st = subtext:match("^%s*(.-)%s*$") -- trim whitespace + if st:find(subPattern) then + return true + end + else + return false + end +end + function set_timeout() local time_out if mp.get_property_native("cache-size") ~= nil then @@ -33,6 +54,22 @@ function check_should_speedup() local mark = mp.get_property_native("time-pos") local nextsubdelay = mp.get_property_native("sub-delay") local nextsub = subdelay - nextsubdelay + if ignorePattern and nextsub > 0 then + local lookNext = true + local ignore = shouldIgnore(mp.get_property("sub-text")) + while ignore and lookNext do + local delay1 = mp.get_property_native("sub-delay") + mp.command("no-osd sub-step 1") + local delay2 = mp.get_property_native("sub-delay") + ignore = shouldIgnore(mp.get_property("sub-text")) + if delay1 == delay2 then + lookNext = false + nextsub = 0 + else + nextsub = subdelay - delay2 + end + end + end mp.set_property("sub-delay", subdelay) mp.command("no-osd set sub-visibility yes") return nextsub, nextsub >= lookahead or nextsub == 0, mark @@ -41,8 +78,7 @@ end function check_audio(_,ds) if state==0 then return - end - if ds and tonumber(ds)>leadin then + elseif ds and tonumber(ds)>leadin and mp.get_property("aid")~="no" then aid = mp.get_property("aid") mp.set_property("aid", "no") print("avsync greater than leadin, dropping audio") @@ -62,35 +98,62 @@ function check_position(_, position) end function skipval() - local skipval = mp.get_property_native("demuxer-cache-duration", 5) - skipval = clamp(skipval, 1, 5) + local skipval = mp.get_property_native("demuxer-cache-duration", 0) if nextsub > 0 then - if nextsub-skipval-leadin <= 0 or directskip then - skipval = nextsub - leadin + if directskip then + skipval = nextsub - leadin + elseif nextsub - skipval - leadin <= 0 then + skipval = clamp(nextsub - leadin, 0, maxSkip) + else + skipval = clamp(skipval, 0, maxSkip) end + elseif directskip then + skipval = clamp(skipval - leadin, 1, nil) else - skipval = clamp(skipval-leadin, 0, nil) - if skipval == 0 then - skipval = clamp(skipval-1, 1, nil) - end + skipval = clamp(skipval - leadin, 1, maxSkip) end return skipval end +firstskip = true --make the first skip in skip mode not have to wait for skipdelay +delayEnd = true function speed_transition(_, sub) + if sub~=nil and shouldIgnore(sub) then + sub = "" + end; if state == 0 then if sub == "" then last_speedup_zone_begin = speedup_zone_begin nextsub, shouldspeedup, speedup_zone_begin = check_should_speedup() mark = speedup_zone_begin - speedup_zone_end = mark+nextsub - if shouldspeedup then + speedup_zone_end = mark + nextsub + if shouldspeedup or (skipmode and not firstskip) then local temp_disable_skipmode = false if last_speedup_zone_begin and mark < last_speedup_zone_begin then temp_disable_skipmode = true end if skipmode and not temp_disable_skipmode and mp.get_property("pause") == "no" then - mp.commandv("no-osd", "seek", skipval(), "relative", "exact") + if firstskip or skipdelay == 0 then + mp.commandv("no-osd", "seek", skipval(), "relative", "exact") + firstskip = false + elseif delayEnd then + delayEnd = false + mp.add_timeout(skipdelay, function() + delayEnd = true + if mp.get_property("pause") == "no" then + nextsub, shouldskip = check_should_speedup() + if shouldskip or nextsub > leadin then + local tSkip = skipval() + currentSub = mp.get_property("sub-text") + if tSkip > minSkip and (currentSub == "" or shouldIgnore(currentSub)) then + mp.commandv("no-osd", "seek", tSkip, "relative", "exact") + else + firstskip = true + end + end + end + end) + end else normalspeed = mp.get_property("speed") if mp.get_property_native("video-sync") == "audio" then @@ -99,13 +162,17 @@ function speed_transition(_, sub) mp.set_property("speed", speedup) mp.observe_property("time-pos", "native", check_position) state = 1 - aid=mp.get_property("aid") - mp.observe_property("avsync", "native", check_audio) + if dropOnAVdesync then + aid = mp.get_property("aid") + mp.observe_property("avsync", "native", check_audio) + end end + else + firstskip = true end end elseif state == 1 then - if sub ~= "" and sub ~= nil or not mp.get_property_native("sid") then + if (sub ~= "" and sub ~= nil) or not mp.get_property_native("sid") then mp.unobserve_property(check_position) mp.unobserve_property(check_audio) restore_normalspeed() @@ -141,8 +208,10 @@ end function toggle_skipmode() skipmode = not skipmode if enable then - toggle() - toggle() + mp.unobserve_property(speed_transition) + mp.unobserve_property(check_position) + mp.observe_property("sub-text", "native", speed_transition) + state = 0 end if skipmode then mp.osd_message("skip mode") @@ -166,20 +235,28 @@ function change_speedup(v) end function change_leadin(v) - leadin = clamp(leadin + v, 0, 2) + --leadin = clamp(leadin + v, 0, 2) + leadin = clamp(leadin + v, 0, nil) mp.osd_message("leadin: "..leadin) end +function change_lookAhead(v) + lookahead = clamp(lookahead + v , 0, nil) + mp.osd_message("lookahead: "..lookahead) +end + enable = false state = 0 function toggle() if not enable then normalspeed = mp.get_property("speed") + mp.set_property("demuxer-readahead-secs",lookahead+leadin) mp.observe_property("sub-text", "native", speed_transition) mp.osd_message("speed-transition enabled") else restore_normalspeed() + mp.set_property("demuxer-readahead-secs",readahead_secs) mp.unobserve_property(speed_transition) mp.unobserve_property(check_position) mp.osd_message("speed-transition disabled") @@ -199,8 +276,10 @@ end mp.add_key_binding("ctrl+j", "toggle_speedtrans", toggle) mp.add_key_binding("alt+j", "toggle_sub_visibility", toggle_sub_visibility) mp.add_key_binding("ctrl+alt+j", "toggle_skipmode", toggle_skipmode) -mp.add_key_binding("alt++", "increase_speedup", function() change_speedup(0.1) end) -mp.add_key_binding("alt+-", "decrease_speedup", function() change_speedup(-0.1) end) +mp.add_key_binding("alt++", "increase_speedup", function() change_speedup(0.1) end, {repeatable=true}) +mp.add_key_binding("alt+-", "decrease_speedup", function() change_speedup(-0.1) end, {repeatable=true}) mp.add_key_binding("alt+0", "increase_leadin", function() change_leadin(0.25) end) mp.add_key_binding("alt+9", "decrease_leadin", function() change_leadin(-0.25) end) +mp.add_key_binding("alt+8", "increase_lookahead", function() change_lookAhead(0.25) end) +mp.add_key_binding("alt+7", "decrease_lookahead", function() change_lookAhead(-0.25) end) mp.register_event("file-loaded", reset_on_file_load)