Major refactoring to isolate bitrate deciding logic
This commit is contained in:
parent
a9c3b39d09
commit
4d8acedb49
177
scripts/dump.lua
177
scripts/dump.lua
|
@ -85,59 +85,102 @@ local function set_clipboard(text)
|
|||
end
|
||||
end
|
||||
|
||||
-- 33390 creates files that are just barely over the 4M limit
|
||||
local fourchsizelimit = 33388 -- 4chan's 4M filesize limit in kilobits
|
||||
-- 32000 is 4M exactly
|
||||
-- 33388 was the previous working number
|
||||
-- 33000 creates files that are just barely over the 4M limit
|
||||
-- Conclusion: just use 33388, and when you get a rare file that breaks the 4M limit, just
|
||||
-- manually lower the bitrate on the command line by a few kilobits
|
||||
local fourchsizelimit = 33388 --48000 for /wsg/'s 6M limit -- /jp/'s 4M filesize limit in kilobits
|
||||
|
||||
local function copyff(x)
|
||||
-- vft will be a non-empty lua table if a crop was set with crop.lua
|
||||
local vft = mp.get_property_native("vf")
|
||||
local crop_was_set = (#vft > 0)
|
||||
vaapi = " -vaapi_device /dev/dri/renderD128 "
|
||||
|
||||
function makescalefilter()
|
||||
local cmd = 'echo | dmenu -p scale:'
|
||||
local scale = string.gsub(io.popen(cmd):read('*a'), '\n$', '')
|
||||
if #scale == 0 then
|
||||
return ""
|
||||
else
|
||||
return "scale="..scale
|
||||
end
|
||||
end
|
||||
|
||||
function getTargetBitrate(sourcebitrate,clipduration,w,h,crop_was_set,vft)
|
||||
if crop_was_set then
|
||||
crop_area = vft[1].params.w * vft[1].params.h
|
||||
print(w)
|
||||
print(h)
|
||||
print("lmao")
|
||||
og_area = w * h
|
||||
mp.osd_message(crop_area/og_area)
|
||||
if crop_area < og_area / 4 then
|
||||
workingbitrate = sourcebitrate * 0.9
|
||||
else
|
||||
workingbitrate = sourcebitrate
|
||||
end
|
||||
else
|
||||
workingbitrate = sourcebitrate
|
||||
end
|
||||
|
||||
local is4chsized = (clipduration * workingbitrate) < (fourchsizelimit * 0.75)
|
||||
|
||||
if is4chsized then
|
||||
return workingbitrate
|
||||
else
|
||||
return fourchsizelimit / clipduration -- kilobits/s
|
||||
end
|
||||
end
|
||||
|
||||
function makecropfilter(w,h,vft)
|
||||
-- vft will be a non-empty lua table if a crop was set with crop.lua
|
||||
-- added following crop condition check because when manually cropping, placing the
|
||||
-- mouse at the very bottom or right of the fullscreened video doesn't select the last
|
||||
-- row or column of pixels. So this automatically updates the crop to include the
|
||||
-- unselected pixels when within 2 pixels of the bottom or right edge
|
||||
if crop_was_set then
|
||||
local w = mp.get_property_native("width")
|
||||
print(w.." - (".. vft[1].params.y.." + "..vft[1].params.w..")")
|
||||
local wdiff = w - (vft[1].params.x + vft[1].params.w)
|
||||
print("wdiff: "..wdiff)
|
||||
if wdiff < 3 then
|
||||
vft[1].params.w = vft[1].params.w + wdiff
|
||||
end
|
||||
|
||||
local h = mp.get_property_native("height")
|
||||
print(h.." - (".. vft[1].params.x.." + "..vft[1].params.h..")")
|
||||
local hdiff = h - (vft[1].params.y + vft[1].params.h)
|
||||
print("hdiff: "..hdiff)
|
||||
if hdiff < 3 then
|
||||
vft[1].params.h = vft[1].params.h + hdiff
|
||||
end
|
||||
print(w.." - (".. vft[1].params.y.." + "..vft[1].params.w..")")
|
||||
local wdiff = w - (vft[1].params.x + vft[1].params.w)
|
||||
print("wdiff: "..wdiff)
|
||||
if wdiff < 3 then
|
||||
vft[1].params.w = vft[1].params.w + wdiff
|
||||
end
|
||||
|
||||
|
||||
print(h.." - (".. vft[1].params.x.." + "..vft[1].params.h..")")
|
||||
local hdiff = h - (vft[1].params.y + vft[1].params.h)
|
||||
print("hdiff: "..hdiff)
|
||||
if hdiff < 3 then
|
||||
vft[1].params.h = vft[1].params.h + hdiff
|
||||
end
|
||||
|
||||
-- assemble the crop settings string
|
||||
-- crop.lua supports recursive cropping by building a chain of crop filters. This
|
||||
-- script does not support chains longer than 1.
|
||||
local c = crop_was_set
|
||||
and ("crop="..vft[1].params.w..":"..vft[1].params.h..":"..
|
||||
-- script does not support chains longer than 1.
|
||||
return ("crop="..vft[1].params.w..":"..vft[1].params.h..":"..
|
||||
vft[1].params.x..":"..vft[1].params.y)
|
||||
or ""
|
||||
|
||||
-- set a vf parameter when ticker overlay isn't requested
|
||||
if x ~= "ticker" and crop_was_set then
|
||||
vf = " -vf "..c
|
||||
else
|
||||
vf = ""
|
||||
end
|
||||
end
|
||||
|
||||
-- fc for filter_complex: this adds the #e9ebe8 ticker overlay
|
||||
if x == "ticker" then
|
||||
local a = crop_was_set and "[v4];[v4]"..c or ""
|
||||
fc = " -f lavfi -i color=#e9ebe8:s=1698x101 -f lavfi -i color=#e9ebe8:s=139x62 -filter_complex '[0:v][1:v]overlay=33:962[v2];[v2][2:v]overlay=1752:1003"..a.."' "
|
||||
function makefilterchain(maybe_ticker,crop_was_set,w,h,vft)
|
||||
local c = crop_was_set and makecropfilter(w,h,vft) or ""
|
||||
local s = makescalefilter()
|
||||
local ce = #c > 0
|
||||
local filterchain = ce and c..","..s or s
|
||||
local chainexists = #filterchain > 0
|
||||
if maybe_ticker == "ticker" then
|
||||
local a = chainexists and "[v4];[v4]"..filterchain or ""
|
||||
return " -f lavfi -i color=#e9ebe8:s=1698x101 -f lavfi -i color=#e9ebe8:s=139x62 -filter_complex '[0:v][1:v]overlay=33:962[v2];[v2][2:v]overlay=1752:1003"..a.."' "
|
||||
elseif chainexists then
|
||||
return " -vf "..filterchain
|
||||
else
|
||||
fc = ""
|
||||
return ""
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
local function copyff(x)
|
||||
local vft = mp.get_property_native("vf")
|
||||
local crop_was_set = (#vft > 0)
|
||||
local w = mp.get_property_native("width")
|
||||
local h = mp.get_property_native("height")
|
||||
print(w)
|
||||
print(h)
|
||||
-- local lmao = print(vft) and 1
|
||||
-- Get loop start and end points. Set defaults if unset
|
||||
local clip_start = mp.get_property_native("ab-loop-a")
|
||||
local clip_start = type(clip_start) == "number" and clip_start or 0
|
||||
|
@ -145,51 +188,43 @@ local function copyff(x)
|
|||
local sourceduration = mp.get_property_native("duration") -- clip source file duration in seconds
|
||||
local clip_end = type(clip_end) == "number" and clip_end or sourceduration
|
||||
local start_end = " -ss "..clip_start.." -to "..clip_end
|
||||
local f = mp.get_property("path")
|
||||
local file = mp.get_property("path")
|
||||
-- don't include audio in webm if mpv is muted
|
||||
local mute = mp.get_property_native("mute") and " -an " or ""
|
||||
-- unix niceness: see manpage for "nice". Transcoding is intensive and can slow down
|
||||
-- other programs on weak systems. Make this an empty string if you don't need it.
|
||||
local nice = " nice "
|
||||
local filterchain = makefilterchain(x,crop_was_set,w,h,vft)
|
||||
print(filterchain)
|
||||
|
||||
-- assemble the ffmpeg command
|
||||
if x == "singlepass" then
|
||||
cmd = nice.."ffmpeg "..mute.." -i ".."'file:"..f.."'"..vf..fc..start_end.." /tmp/a.webm"
|
||||
cmd = nice.."ffmpeg "..mute.." -i ".."'file:"..file.."'"..filterchain..start_end.." /tmp/a.webm"
|
||||
elseif x == "copy" then
|
||||
cmd = "ffmpeg "..mute.." -i ".."'file:"..f.."' -c copy"..start_end.." /tmp/a.webm"
|
||||
elseif x == "twopass" or x == "ticker" then
|
||||
cmd = "ffmpeg "..mute.." -i ".."'file:"..file.."' -c copy"..start_end.." /tmp/a.webm"
|
||||
elseif x == "twopass" or x == "ticker" or x == "crf" then
|
||||
-- Reference: https://trac.ffmpeg.org/wiki/Encode/VP9
|
||||
local filesize = mp.get_property_native("file-size") or mp.get_property("file-size")
|
||||
local clipduration = clip_end - clip_start
|
||||
local sourcebits = (mp.get_property_native("file-size")) * 8
|
||||
local sourcebits = filesize * 8
|
||||
-- multiply denominator by 1000 here rather than divide sourcebits by 1000 above to
|
||||
-- minimize divisions, which is lossy in floating-point operations
|
||||
local sourcebitrate = sourcebits / (sourceduration * 1000) -- result is kilobits/s
|
||||
|
||||
if sourcebitrate * clipduration <= fourchsizelimit then
|
||||
if crop_was_set then
|
||||
crop_area = vft[1].params.w * vft[1].params.h
|
||||
og_area = mp.get_property_native("width") * mp.get_property_native("height")
|
||||
end
|
||||
|
||||
if crop_was_set and crop_area < og_area / 4 then
|
||||
targetbitratestring = " -b:v 0 -crf 18 "
|
||||
print("crop_area: "..crop_area..
|
||||
"\nog_area: "..og_area..
|
||||
"\nUsing constant quality 2-pass")
|
||||
else targetbitratestring = " -b:v "..sourcebitrate.."k "
|
||||
print("Using source's average bitrate 2-pass")
|
||||
end
|
||||
else
|
||||
local targetbitrate = fourchsizelimit / clipduration -- kilobits/s
|
||||
targetbitratestring = " -b:v "..targetbitrate.."k "
|
||||
print("Using calculated target bitrate")
|
||||
end
|
||||
local targetbitrate = getTargetBitrate(sourcebitrate, clipduration, w, h, crop_was_set, vft)
|
||||
|
||||
cmd = nice.."ffmpeg -i 'file:"..f.."'" ..
|
||||
vf..fc.." -c:v libvpx-vp9"..targetbitratestring.."-pass 1"..start_end..
|
||||
" -an -f null /dev/null && "..nice.." ffmpeg "..mute.." -hide_banner -y -i 'file:"..f.."'" ..
|
||||
vf..fc.." -c:v libvpx-vp9"..targetbitratestring.."-pass 2"..start_end..
|
||||
-- targetbitratestring = " -crf 0 -b:v "..targetbitrate.."k ".." -maxrate "..targetbitrate.."k "
|
||||
-- on small crops, 13 at most is visually lossless, from my experience, 0 for big crops
|
||||
targetbitratestring = " -crf 0 -b:v "..targetbitrate.."k "
|
||||
|
||||
cmd = nice.."ffmpeg -hide_banner -i 'file:"..file.."'" ..
|
||||
filterchain.." -c:v libvpx-vp9"..targetbitratestring.."-pass 1"..start_end..
|
||||
" -an -f null /dev/null && "..nice.." ffmpeg "..mute.." -hide_banner -y -i 'file:"..file.."'" ..
|
||||
filterchain.." -c:v libvpx-vp9"..targetbitratestring.."-pass 2"..start_end..
|
||||
" -c:a libopus /tmp/a.webm; rm -f ffmpeg2pass-0.log"
|
||||
elseif x == "lossless" then
|
||||
cmd = "ffmpeg "..mute.." -hide_banner -y -i 'file:"..file.."'" ..
|
||||
filterchain.." -c:v libvpx-vp9 -lossless 1 "..start_end..
|
||||
" -c:a libopus /tmp/a.webm"
|
||||
end
|
||||
|
||||
if set_clipboard(cmd) then
|
||||
|
@ -202,9 +237,13 @@ end
|
|||
function copyffcopy() copyff("copy") end
|
||||
function copyffsinglepass() copyff("singlepass") end
|
||||
function copyfftwopass() copyff("twopass") end
|
||||
function copyffcrf() copyff("crf") end
|
||||
function copyffticker() copyff("ticker") end
|
||||
function copyfflossless() copyff("lossless") end
|
||||
|
||||
mp.add_key_binding("ctrl+c", "copyffcopy", copyffcopy) -- just cut and copy the video stream
|
||||
mp.add_key_binding("ctrl+s", "copyffsinglepass", copyffsinglepass) -- single pass default encode
|
||||
mp.add_key_binding("ctrl+d", "copyfftwopass", copyfftwopass) -- dual pass encode
|
||||
mp.add_key_binding("ctrl+t", "copyffticker", copyffticker) -- "t" for ticker; includes overlay for ticker
|
||||
mp.add_key_binding("ctrl+r", "copyffcrf", copyffcrf) -- "t" for ticker; includes overlay for ticker
|
||||
mp.add_key_binding("ctrl+l", "copyfflossless", copyfflossless)
|
||||
|
|
Loading…
Reference in New Issue