Skip to content

Instantly share code, notes, and snippets.

@iluvcapra
Created December 16, 2020 19:00
Show Gist options
  • Save iluvcapra/943f4956be7e14168125154bc60df4e7 to your computer and use it in GitHub Desktop.
Save iluvcapra/943f4956be7e14168125154bc60df4e7 to your computer and use it in GitHub Desktop.
--[[
Detect Cuts.lua
Jamie Hardt 16 Dec 2020
]]
ScriptExtKey = "COM_SQUAD51ENTERPRISES_DETECTCUTS"
FFmpegPathKey = "FFMPEG_PATH"
LastThresholdKey = "LAST_THRESHOLD"
function Get_FFMpeg_Path ()
local function test_ffmpeg (test_path)
return os.execute(test_path .. " -t 1.0 -f lavfi -i 'color=black' -filter:v 'scdet=t=3.0' -f null /dev/null") -- on my system os.execute returns a boolean
end
local path = nil
if reaper.HasExtState(ScriptExtKey, FFmpegPathKey) then
path = reaper.GetExtState(ScriptExtKey, FFmpegPathKey)
else
local retval = reaper.MB("FFMpeg is required for this action, find the path to your FFmpeg executable now or click Cancel.","Detect Cuts",1)
if retval == 1 then
retval, path = reaper.GetUserFileNameForRead("/usr/local/bin/", "Find FFMpeg executable", "")
if retval then
reaper.SetExtState(ScriptExtKey,FFmpegPathKey,path, true)
return Get_FFMpeg_Path() -- tail call
end
else
return nil
end
end
if test_ffmpeg (path) then
return path
else
reaper.MB("Working FFMpeg could not be found at " .. path .. ".", "Detect Cuts Error",0)
reaper.DeleteExtState(ScriptExtKey, FFmpegPathKey, true)
return Get_FFMpeg_Path() -- tail call
end
end
local ffmpeg_path = Get_FFMpeg_Path()
if ffmpeg_path == nil then return else ffmpeg_path = ffmpeg_path .. " -hide_banner" end
function Iterate_cuts ( file_path, detection_threshold, start_offset, length )
local args = " "
if start_offset ~= nil then
args = args .. "-ss " .. string.format("%f", start_offset) .. " "
end
if length ~= nil then
args = args .. "-t " .. string.format("%f", length) .. " "
end
args = args .. "-i \"" .. file_path .. "\" -filter:v 'scdet=t=" ..
string.format("%f",detection_threshold) .. ":s=1,metadata=print:file=-' -f null - 2>/dev/null"
local ffmpeg_read = io.popen(ffmpeg_path .. args, "r")
local line = nil
return function ()
while true do
line = ffmpeg_read:read("*l")
if line == nil then break end
local pts_time = line:match("pts_time:(%d+)%.")
if pts_time ~= nil then
local time = tonumber(pts_time)
local time_parts = line:match("pts_time:%d+%.(%d+)")
if time_parts ~= nil then
time = tonumber(pts_time .. "." .. time_parts)
end
return time, line
end
end
end
end
local count = reaper.CountSelectedMediaItems(0)
if count > 1 then
reaper.MB("Please select one object. Cut detection only works on single media files.", "Cut Detection",0)
return
elseif count == 0 then
reaper.MB("Please select a video media object.", "Cut Detection",0)
return
end
local selected = reaper.GetSelectedMediaItem(0,0)
local selected_take = reaper.GetTake(selected, 0)
local source = reaper.GetMediaItemTake_Source(selected_take)
local filename = reaper.GetMediaSourceFileName(source, "")
local source_type = reaper.GetMediaSourceType(source, "")
if source_type ~= "VIDEO" then
reaper.MB("Please select a video media object.", "Cut Detection",0)
return
end
local default_threshold = 5.0
if reaper.HasExtState(ScriptExtKey, LastThresholdKey) then
default_threshold = tonumber(reaper.GetExtState(ScriptExtKey, LastThresholdKey))
end
local result, rvals = reaper.GetUserInputs("Cut Detection with ffmpeg",1,"Detection Threshold",tostring(default_threshold))
if result then
local position = reaper.GetMediaItemInfo_Value(selected, "D_POSITION")
local length = reaper.GetMediaItemInfo_Value(selected, "D_LENGTH")
local start_offset = reaper.GetMediaItemTakeInfo_Value(selected_take, "D_STARTOFFS")
local this_threshold = tonumber(rvals)
reaper.SetExtState(ScriptExtKey, LastThresholdKey, tostring(this_threshold), true)
local n = 1
for time, line in Iterate_cuts(filename, this_threshold, start_offset, length) do
-- reaper.SetEditCurPos(time+position, false, false)
-- reaper.Main_OnCommandEx(40012,0,0)
-- SPLIT: 40012
reaper.AddProjectMarker(0, false, time + position, 0., "Cut: " .. line, n)
n = n + 1
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment