Skip to content

Instantly share code, notes, and snippets.

@DonRichie
Last active June 17, 2023 19:02
Show Gist options
  • Save DonRichie/23d8442e91ef8dc4917f9e6a9d6fe5c0 to your computer and use it in GitHub Desktop.
Save DonRichie/23d8442e91ef8dc4917f9e6a9d6fe5c0 to your computer and use it in GitHub Desktop.
local utils = require 'mp.utils'
local enabled = false
local silence_threshold = -20
local edge_delta = 0.06
local file = nil
local silenceData = {}
local currentIndex = 1
local result = ""
local block_refresh = false
local next_skip_start = -1
local next_skip_end = -1
local next_duration = -1
local silence_list = {}
function refresh_ffmpeg_silent_parts()
if not block_refresh then
block_refresh = true
-- Find silent parts with ffmpeg
file = mp.get_property("path")
print("file: " .. file)
local command = { "ffmpeg", "-i", file, "-af", string.format("silencedetect=noise=%ddB:d=0.5", silence_threshold), "-f", "null", "-" }
result = utils.subprocess({ args = command, cancellable = false, capture_stdout = true, capture_stderr = true })
if result.error then
print("Error running ffmpeg command")
return
end
print(result.stderr)
-- Parse detected silent parts into a list
silence_list = {}
for start, endtime, duration in result.stderr:gmatch("silence_start: (%S+)\n.-silence_end: (%S+) | silence_duration: (%S+)") do
table.insert(silence_list, { tonumber(start), tonumber(endtime), tonumber(duration) })
end
print("Silence List:")
for i, data in ipairs(silence_list) do
print(i, "Start:", data[1], "End:", data[2], "Dur:", data[3])
end
print("done finding silence")
mp.osd_message("done finding silence")
block_refresh = false
else
print("refresh already running")
end
end
function recalc_next_skip()
--print("recalc now")
local current_time = mp.get_property_number("time-pos", 0)
--print("current_time: " .. current_time)
next_skip_start = mp.get_property_number("duration")
for _, silence in ipairs(silence_list) do
local start_time, end_time, duration = silence[1], silence[2], silence[3]
if current_time <= (start_time+edge_delta) and start_time < next_skip_start then
next_skip_start = start_time
next_skip_end = end_time
next_duration = duration
end
end
--print(" next skip: " .. next_skip_start .. " for " .. next_duration .. " in " .. (next_skip_start-current_time))
end
function toggle_skip_silent()
enabled = not enabled
if enabled then
print("Skip Silence enabled, finding silence...")
mp.osd_message("Silence skipping enabled, finding silence...")
refresh_ffmpeg_silent_parts()
function skip_silent_parts()
if enabled then
local current_time = mp.get_property_number("time-pos", 0)
if current_time >= (next_skip_start + edge_delta) and current_time <= (next_skip_end - edge_delta) then
print("skipping to " .. next_skip_end-edge_delta)
mp.commandv("seek", next_skip_end-edge_delta, "absolute+exact")
end
--todo: this recalc should only be calculated when it is necessary
-- but it is currently still no performance bottleneck
recalc_next_skip()
end
end
mp.observe_property("time-pos", "native", skip_silent_parts)
else
mp.osd_message("Skip Silence disabled")
mp.osd_message("Skip Silence disabled")
end
end
mp.add_key_binding("F2", "toggle_skip_silent", toggle_skip_silent)
function change_threshold(delta)
silence_threshold = silence_threshold + delta
mp.osd_message("silence_threshold: "..silence_threshold.."dB , finding silence...")
refresh_ffmpeg_silent_parts()
end
mp.add_key_binding("F3", "threshold-down", function() change_threshold(-1) end, "repeatable")
mp.add_key_binding("F4", "threshold-up", function() change_threshold(1) end, "repeatable")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment