mirror of
https://github.com/Dichgrem/DCGOS.git
synced 2025-12-17 11:41:59 -05:00
314 lines
11 KiB
Lua
Vendored
314 lines
11 KiB
Lua
Vendored
-- evafast.lua
|
|
--
|
|
-- Much speed.
|
|
--
|
|
-- Jumps forwards when right arrow is pressed, speeds up when it's held.
|
|
-- Inspired by bilibili.com's player. Allows you to have both seeking and fast-forwarding on the same key.
|
|
-- Also supports toggling fastforward mode with a keypress.
|
|
-- Adjust --input-ar-delay to define when to start fastforwarding.
|
|
-- Define --hr-seek if you want accurate seeking.
|
|
-- If you just want a nicer fastforward.lua without hybrid key behavior, set seek_distance to 0.
|
|
|
|
local options = {
|
|
-- How far to jump on press, set to 0 to disable seeking and force fastforward
|
|
seek_distance = 5,
|
|
|
|
-- Playback speed modifier, applied once every speed_interval until cap is reached
|
|
speed_increase = 0.1,
|
|
speed_decrease = 0.1,
|
|
|
|
-- At what interval to apply speed modifiers
|
|
speed_interval = 0.05,
|
|
|
|
-- Playback speed cap
|
|
speed_cap = 2,
|
|
|
|
-- Playback speed cap when subtitles are displayed, 'no' for same as speed_cap
|
|
subs_speed_cap = 1.6,
|
|
|
|
-- Multiply current speed by modifier before adjustment (exponential speedup)
|
|
-- Use much lower values than default e.g. speed_increase=0.05, speed_decrease=0.025
|
|
multiply_modifier = false,
|
|
|
|
-- Show current speed on the osd (or flash speed if using uosc)
|
|
show_speed = true,
|
|
|
|
-- Show current speed on the osd when toggled (or flash speed if using uosc)
|
|
show_speed_toggled = true,
|
|
|
|
-- Show current speed on the osd when speeding up towards a target time (or flash speed if using uosc)
|
|
show_speed_target = false,
|
|
|
|
-- Show seek actions on the osd (or flash timeline if using uosc)
|
|
show_seek = true,
|
|
|
|
-- Look ahead for smoother transition when subs_speed_cap is set
|
|
lookahead = false
|
|
}
|
|
|
|
mp.options = require "mp.options"
|
|
mp.options.read_options(options, "evafast")
|
|
|
|
local uosc_available = false
|
|
local repeated = false
|
|
local speed_timer = nil
|
|
local speedup = true
|
|
local no_speedup = false
|
|
local jumps_reset_speed = true
|
|
local toggle_display = false
|
|
local toggle_state = false
|
|
local freeze = false
|
|
|
|
local forced_speed_cap = nil
|
|
local use_forced_speed_cap = false
|
|
|
|
local speedup_target = nil
|
|
|
|
local function speed_transition(test_speed, target)
|
|
local time_for_correction = 0
|
|
if not freeze then
|
|
while test_speed ~= target do
|
|
time_for_correction = time_for_correction + options.speed_interval
|
|
if test_speed <= target then
|
|
if options.multiply_modifier then
|
|
test_speed = math.min(test_speed + (test_speed * options.speed_increase), target)
|
|
else
|
|
test_speed = math.min(test_speed + options.speed_increase, target)
|
|
end
|
|
else
|
|
if options.multiply_modifier then
|
|
test_speed = math.max(test_speed - (test_speed * options.speed_decrease), 1)
|
|
else
|
|
test_speed = math.max(test_speed - options.speed_decrease, 1)
|
|
end
|
|
end
|
|
if test_speed == 1 then break end
|
|
end
|
|
end
|
|
return time_for_correction
|
|
end
|
|
|
|
local function adjust_speed()
|
|
local no_sub_speed = not options.subs_speed_cap or mp.get_property("sub-start") == nil
|
|
local effective_speed_cap = no_sub_speed and options.speed_cap or options.subs_speed_cap
|
|
local speed = mp.get_property_number("speed", 1)
|
|
local old_speed = speed
|
|
|
|
if options.lookahead and options.subs_speed_cap and no_sub_speed and not use_forced_speed_cap then
|
|
local sub_delay = mp.get_property_native("sub-delay")
|
|
local sub_visible = mp.get_property_bool("sub-visibility")
|
|
if sub_visible then
|
|
mp.set_property_bool("sub-visibility", false)
|
|
end
|
|
mp.command("no-osd sub-step 1")
|
|
local sub_next_delay = mp.get_property_native("sub-delay")
|
|
local sub_next = sub_delay - sub_next_delay
|
|
mp.set_property("sub-delay", sub_delay)
|
|
if sub_visible then
|
|
mp.set_property_bool("sub-visibility", sub_visible)
|
|
end
|
|
-- calculate how long it takes to get from current speed to target speed, and use that as threshold for sub_next
|
|
local time_for_correction = speed_transition(speed, options.subs_speed_cap)
|
|
if sub_next ~= 0 and sub_next <= (time_for_correction * speed) then
|
|
effective_speed_cap = options.subs_speed_cap
|
|
use_forced_speed_cap = true
|
|
forced_speed_cap = effective_speed_cap
|
|
end
|
|
end
|
|
|
|
if speedup_target ~= nil then
|
|
local current_time = mp.get_property_number("time-pos", 0)
|
|
if current_time >= speedup_target then
|
|
jumps_reset_speed = true
|
|
no_speedup = true
|
|
repeated = false
|
|
freeze = false
|
|
else
|
|
local time_for_correction = speed_transition(speed, math.max(math.min(options.speed_cap, options.subs_speed_cap and options.subs_speed_cap or options.speed_cap), 1.1)) -- not effective_speed_cap because it may lead to huge fluctuations in transition speed
|
|
if (time_for_correction * speed + current_time) > speedup_target then
|
|
effective_speed_cap = 1.1 -- >1 so we don't get stuck trying to catch the target
|
|
use_forced_speed_cap = true
|
|
forced_speed_cap = effective_speed_cap
|
|
else
|
|
forced_speed_cap = nil
|
|
use_forced_speed_cap = false
|
|
end
|
|
end
|
|
end
|
|
|
|
if not freeze then
|
|
if forced_speed_cap ~= nil then
|
|
if speed ~= forced_speed_cap or mp.get_property_bool("pause") then
|
|
use_forced_speed_cap = true
|
|
end
|
|
effective_speed_cap = forced_speed_cap
|
|
end
|
|
if speedup and not no_speedup and speed <= effective_speed_cap then
|
|
if options.multiply_modifier then
|
|
speed = math.min(speed + (speed * options.speed_increase), effective_speed_cap)
|
|
else
|
|
speed = math.min(speed + options.speed_increase, effective_speed_cap)
|
|
end
|
|
else
|
|
if options.multiply_modifier then
|
|
speed = math.max(speed - (speed * options.speed_decrease), 1)
|
|
else
|
|
speed = math.max(speed - options.speed_decrease, 1)
|
|
end
|
|
end
|
|
if forced_speed_cap ~= nil and not use_forced_speed_cap then
|
|
forced_speed_cap = nil
|
|
end
|
|
if speed == options.subs_speed_cap then
|
|
if use_forced_speed_cap then
|
|
use_forced_speed_cap = false
|
|
end
|
|
end
|
|
end
|
|
|
|
if speed ~= old_speed then
|
|
mp.set_property("speed", speed)
|
|
if (options.show_speed and not toggle_display) or (options.show_speed_toggled and toggle_display and speedup_target == nil) or (options.show_speed_target and speedup_target ~= nil) then
|
|
if uosc_available then
|
|
mp.command("script-binding uosc/flash-speed")
|
|
else
|
|
mp.osd_message(("▶▶ x%.1f"):format(speed))
|
|
end
|
|
end
|
|
end
|
|
|
|
if speed == 1 and effective_speed_cap ~= 1 then
|
|
if speed_timer ~= nil and not toggle_state then
|
|
speed_timer:kill()
|
|
speed_timer = nil
|
|
end
|
|
repeated = false
|
|
jumps_reset_speed = true
|
|
toggle_display = false
|
|
toggle_state = false
|
|
speedup_target = nil
|
|
elseif speed_timer == nil then
|
|
speed_timer = mp.add_periodic_timer(options.speed_interval, adjust_speed)
|
|
end
|
|
end
|
|
|
|
local function evafast(keypress)
|
|
if jumps_reset_speed and not toggle_state and (keypress["event"] == "up" or keypress["event"] == "press") then
|
|
speedup = false
|
|
speedup_target = nil
|
|
end
|
|
|
|
if options.seek_distance == 0 then
|
|
if keypress["event"] == "up" or keypress["event"] == "press" then
|
|
speedup = false
|
|
no_speedup = true
|
|
repeated = false
|
|
speedup_target = nil
|
|
end
|
|
if keypress["event"] == "down" then
|
|
keypress["event"] = "repeat"
|
|
end
|
|
end
|
|
|
|
if keypress["event"] == "up" or keypress["event"] == "press" then
|
|
toggle_display = toggle_state
|
|
if toggle_state and jumps_reset_speed then
|
|
speedup = false
|
|
speedup_target = nil
|
|
end
|
|
if speed_timer ~= nil and not toggle_state and mp.get_property_number("speed") == 1 and ((not options.subs_speed_cap or mp.get_property("sub-start") == nil) and options.speed_cap or options.subs_speed_cap) ~= 1 then
|
|
speed_timer:kill()
|
|
speed_timer = nil
|
|
jumps_reset_speed = true
|
|
toggle_display = false
|
|
toggle_state = false
|
|
speedup_target = nil
|
|
end
|
|
freeze = false
|
|
end
|
|
|
|
if keypress["event"] == "down" then
|
|
repeated = false
|
|
speedup = true
|
|
freeze = true
|
|
toggle_display = false
|
|
if options.show_seek and not repeated and not uosc_available then
|
|
mp.osd_message("▶▶")
|
|
end
|
|
elseif (keypress["event"] == "up" and (not repeated or speedup_target)) or keypress["event"] == "press" then
|
|
if options.seek_distance ~= 0 then
|
|
mp.commandv("seek", options.seek_distance)
|
|
if options.show_seek and uosc_available then
|
|
mp.command("script-binding uosc/flash-timeline")
|
|
end
|
|
end
|
|
repeated = false
|
|
if jumps_reset_speed and not toggle_state then
|
|
no_speedup = true
|
|
end
|
|
elseif keypress["event"] == "repeat" then
|
|
freeze = false
|
|
speedup = true
|
|
no_speedup = false
|
|
if not repeated then
|
|
adjust_speed()
|
|
end
|
|
repeated = true
|
|
end
|
|
end
|
|
|
|
local function evafast_speedup()
|
|
no_speedup = false
|
|
speedup = true
|
|
jumps_reset_speed = false
|
|
toggle_display = true
|
|
toggle_state = true
|
|
evafast({event = "repeat"})
|
|
end
|
|
|
|
local function evafast_slowdown()
|
|
jumps_reset_speed = true
|
|
no_speedup = true
|
|
repeated = false
|
|
freeze = false
|
|
speedup_target = nil
|
|
end
|
|
|
|
local function evafast_toggle()
|
|
if (repeated or not jumps_reset_speed) and speedup then
|
|
evafast_slowdown()
|
|
else
|
|
evafast_speedup()
|
|
end
|
|
end
|
|
|
|
mp.register_script_message("uosc-version", function(version)
|
|
uosc_available = true
|
|
end)
|
|
|
|
mp.register_script_message("speedup-target", function(time)
|
|
time = tonumber(time) or 0
|
|
if mp.get_property_number("time-pos", 0) >= time then
|
|
if speedup_target ~= nil then
|
|
use_forced_speed_cap = false
|
|
forced_speed_cap = nil
|
|
speedup_target = nil
|
|
evafast_slowdown()
|
|
end
|
|
return
|
|
end
|
|
speedup_target = time
|
|
evafast_speedup()
|
|
end)
|
|
|
|
mp.register_script_message("get-version", function(script)
|
|
mp.commandv("script-message-to", script, "evafast-version", "1.0")
|
|
end)
|
|
|
|
mp.add_key_binding("RIGHT", "evafast", evafast, {repeatable = true, complex = true})
|
|
mp.add_key_binding(nil, "speedup", evafast_speedup)
|
|
mp.add_key_binding(nil, "slowdown", evafast_slowdown)
|
|
mp.add_key_binding(nil, "toggle", evafast_toggle)
|
|
|
|
mp.commandv("script-message-to", "uosc", "get-version", mp.get_script_name())
|