Major refactoring to isolate bitrate deciding logic

This commit is contained in:
pta 2023-12-28 01:07:51 -05:00
parent a9c3b39d09
commit 4d8acedb49
1 changed files with 108 additions and 69 deletions

View File

@ -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)