From 4059d1832b1d1454aa0e030f3dc15cb5ba221746 Mon Sep 17 00:00:00 2001 From: Guido Cella Date: Thu, 30 May 2024 05:21:01 +0200 Subject: [PATCH] select.lua: preselect the correct sub line with duration >= 100 minutes ffmpeg outputs timestamps like '100:00.00' in LRCs instead of adding hours, and timestamps like '100:00' are < '10:00', so since these strings are being compared, if there is no current subtitle line, there are subtitle lines at >= 100 minutes, and time-pos is between 10 minutes and 100 minutes, one of the last subtitle lines gets preselected. Fix this by converting the timestamps to numbers before comparing them. Also simplify the logic by merging the 2 loops to determine the default line, and reformat the timestamps by adding hours to not print minutes > 60 in the selector, and by removing the hundredths of seconds. This requires storing the accurate timestamps in a table to seek to them on submit. --- player/lua/select.lua | 45 +++++++++++++++---------------------------- 1 file changed, 15 insertions(+), 30 deletions(-) diff --git a/player/lua/select.lua b/player/lua/select.lua index 0327af45dd..40042e1f96 100644 --- a/player/lua/select.lua +++ b/player/lua/select.lua @@ -209,44 +209,29 @@ mp.add_forced_key_binding(nil, "select-subtitle-line", function () end local sub_lines = {} + local sub_times = {} local default_item - local sub_start = mp.get_property_native("sub-start", - mp.get_property("time-pos")) - local m = math.floor(sub_start / 60) - local s = sub_start - m * 60 - sub_start = string.format("%.2d:%05.2f", m, s) + mp.get_property_native("time-pos")) -- Strip HTML and ASS tags. for line in r.stdout:gsub("<.->", ""):gsub("{\\.-}", ""):gmatch("[^\n]+") do - sub_lines[#sub_lines + 1] = line:sub(2):gsub("]", " ", 1) + -- ffmpeg outputs LRCs with minutes > 60 instead of adding hours. + sub_times[#sub_times + 1] = line:match("%d+") * 60 + line:match(":([%d%.]*)") + sub_lines[#sub_lines + 1] = format_time(sub_times[#sub_times]) .. " " .. + line:gsub(".*]", "", 1) - if line:find("^%[" .. sub_start) then - default_item = #sub_lines + if sub_times[#sub_times] <= sub_start then + default_item = #sub_times end end - -- Preselect the previous line when there is no exact match. - if default_item == nil then - local a = 1 - local b = #sub_lines - while a < b do - local mid = math.ceil(b - a) - - if sub_lines[mid]:match("%S*") < sub_start then - default_item = mid - a = mid + 1 - else - b = mid - end - end - - -- Handle sub-start of embedded subs being slightly earlier than - -- ffmpeg's timestamps. - if mp.get_property("sub-start") and default_item and - sub_lines[default_item + 1] then - default_item = default_item + 1 - end + -- Handle sub-start of embedded subs being slightly earlier than + -- ffmpeg's timestamps. + sub_start = mp.get_property_native("sub-start") + if sub_start and default_item and sub_times[default_item] < sub_start and + sub_lines[default_item + 1] then + default_item = default_item + 1 end input.select({ @@ -254,7 +239,7 @@ mp.add_forced_key_binding(nil, "select-subtitle-line", function () items = sub_lines, default_item = default_item, submit = function (index) - mp.commandv("seek", sub_lines[index]:match("%S*"), "absolute") + mp.commandv("seek", sub_times[index], "absolute") end, }) end)