Add Avisynth video encoding workflow
This commit is contained in:
@@ -0,0 +1,341 @@
|
||||
# media-batch-tools Avisynth+ helpers.
|
||||
#
|
||||
# This file is imported by generated hidden source scripts. Keep functions here
|
||||
# small and dependency-light unless the visible scripts explicitly document the
|
||||
# required plugins.
|
||||
|
||||
function MBT_MarkSource(clip c, int source_id, int "matrix")
|
||||
{
|
||||
# Attach source identity to each frame. Python reads these properties after
|
||||
# running the user-edited script and maps frames back to ffprobe timestamps.
|
||||
# Timestamp/duration variables are supplied by generated ConditionalReader
|
||||
# files when available.
|
||||
matrix = Default(matrix, MBT_GetMatrixCode(c))
|
||||
runtime = """
|
||||
last.propSet("mbt_source_id", """ + String(source_id) + """).\
|
||||
propSet("mbt_source_frame", current_frame).\
|
||||
propSet("mbt_drop_frame", 0).\
|
||||
propSet("_Matrix", """ + String(matrix) + """).\
|
||||
propSet("mbt_frame_time_seconds", mbt_frame_time_seconds).\
|
||||
propSet("mbt_relative_timestamp", mbt_relative_timestamp).\
|
||||
propSet("mbt_absolute_timestamp", mbt_absolute_timestamp).\
|
||||
propSet("mbt_frame_duration_seconds", mbt_frame_duration_seconds).\
|
||||
propSet("mbt_frame_duration", mbt_frame_duration)
|
||||
"""
|
||||
return c.ScriptClip(runtime)
|
||||
}
|
||||
|
||||
function MBT_AudioSource(clip video, string source_path, string audio_cache_path)
|
||||
{
|
||||
audio = FFAudioSource(source_path, cachefile=audio_cache_path)
|
||||
return AudioDub(video, audio)
|
||||
}
|
||||
|
||||
function MBT_Drop(clip c, int start, int "end")
|
||||
{
|
||||
return MBT_SetDrop(c, 1, start, end)
|
||||
}
|
||||
|
||||
function MBT_Undrop(clip c, int start, int "end")
|
||||
{
|
||||
return MBT_SetDrop(c, 0, start, end)
|
||||
}
|
||||
|
||||
function MBT_SetDrop(clip c, int value, int start, int "end")
|
||||
{
|
||||
end = Default(end, -1)
|
||||
end = (end < 0) ? start - end - 1 : end
|
||||
runtime = """
|
||||
(current_frame >= """ + String(start) + """ && current_frame <= """ + String(end) + """) ? \
|
||||
last.propSet("mbt_drop_frame", """ + String(value) + """) : last
|
||||
"""
|
||||
return c.ScriptClip(runtime)
|
||||
}
|
||||
|
||||
function MBT_DropEvery(clip c, int cycle, int "offset0", int "offset1", int "offset2", int "offset3", int "offset4", int "offset5", int "offset6", int "offset7", int "offset8", int "offset9", int "offset10", int "offset11", int "offset12", int "offset13", int "offset14", int "offset15")
|
||||
{
|
||||
return MBT_SetDropEvery(c, 1, cycle, offset0, offset1, offset2, offset3, offset4, offset5, offset6, offset7, offset8, offset9, offset10, offset11, offset12, offset13, offset14, offset15)
|
||||
}
|
||||
|
||||
function MBT_UndropEvery(clip c, int cycle, int "offset0", int "offset1", int "offset2", int "offset3", int "offset4", int "offset5", int "offset6", int "offset7", int "offset8", int "offset9", int "offset10", int "offset11", int "offset12", int "offset13", int "offset14", int "offset15")
|
||||
{
|
||||
return MBT_SetDropEvery(c, 0, cycle, offset0, offset1, offset2, offset3, offset4, offset5, offset6, offset7, offset8, offset9, offset10, offset11, offset12, offset13, offset14, offset15)
|
||||
}
|
||||
|
||||
function MBT_SetDropEvery(clip c, int value, int cycle, int "offset0", int "offset1", int "offset2", int "offset3", int "offset4", int "offset5", int "offset6", int "offset7", int "offset8", int "offset9", int "offset10", int "offset11", int "offset12", int "offset13", int "offset14", int "offset15")
|
||||
{
|
||||
expr = "false"
|
||||
expr = Defined(offset0) ? expr + " || (current_frame % " + String(cycle) + " == " + String(offset0) + ")" : expr
|
||||
expr = Defined(offset1) ? expr + " || (current_frame % " + String(cycle) + " == " + String(offset1) + ")" : expr
|
||||
expr = Defined(offset2) ? expr + " || (current_frame % " + String(cycle) + " == " + String(offset2) + ")" : expr
|
||||
expr = Defined(offset3) ? expr + " || (current_frame % " + String(cycle) + " == " + String(offset3) + ")" : expr
|
||||
expr = Defined(offset4) ? expr + " || (current_frame % " + String(cycle) + " == " + String(offset4) + ")" : expr
|
||||
expr = Defined(offset5) ? expr + " || (current_frame % " + String(cycle) + " == " + String(offset5) + ")" : expr
|
||||
expr = Defined(offset6) ? expr + " || (current_frame % " + String(cycle) + " == " + String(offset6) + ")" : expr
|
||||
expr = Defined(offset7) ? expr + " || (current_frame % " + String(cycle) + " == " + String(offset7) + ")" : expr
|
||||
expr = Defined(offset8) ? expr + " || (current_frame % " + String(cycle) + " == " + String(offset8) + ")" : expr
|
||||
expr = Defined(offset9) ? expr + " || (current_frame % " + String(cycle) + " == " + String(offset9) + ")" : expr
|
||||
expr = Defined(offset10) ? expr + " || (current_frame % " + String(cycle) + " == " + String(offset10) + ")" : expr
|
||||
expr = Defined(offset11) ? expr + " || (current_frame % " + String(cycle) + " == " + String(offset11) + ")" : expr
|
||||
expr = Defined(offset12) ? expr + " || (current_frame % " + String(cycle) + " == " + String(offset12) + ")" : expr
|
||||
expr = Defined(offset13) ? expr + " || (current_frame % " + String(cycle) + " == " + String(offset13) + ")" : expr
|
||||
expr = Defined(offset14) ? expr + " || (current_frame % " + String(cycle) + " == " + String(offset14) + ")" : expr
|
||||
expr = Defined(offset15) ? expr + " || (current_frame % " + String(cycle) + " == " + String(offset15) + ")" : expr
|
||||
runtime = """
|
||||
(""" + expr + """) ? last.propSet("mbt_drop_frame", """ + String(value) + """) : last
|
||||
"""
|
||||
return c.ScriptClip(runtime)
|
||||
}
|
||||
|
||||
function MBT_Info(clip c, int "size", int "align")
|
||||
{
|
||||
# Overlay media-batch-tools frame properties for inspection while editing.
|
||||
size = Default(size, 16)
|
||||
align = Default(align, 7)
|
||||
runtime = """
|
||||
drop_value = propGetInt("mbt_drop_frame") == 0 ? "False" : "True"
|
||||
text = "Absolute timestamp: " + propGetString("mbt_absolute_timestamp") + Chr(10) + \
|
||||
"Relative timestamp: " + propGetString("mbt_relative_timestamp") + Chr(10) + \
|
||||
Chr(10) + \
|
||||
"Source frame: " + String(propGetInt("mbt_source_frame")) + Chr(10) + \
|
||||
"Frame duration: " + propGetString("mbt_frame_duration") + Chr(10) + \
|
||||
"Drop frame: " + drop_value
|
||||
Subtitle(last, text, size=""" + String(size) + """, align=""" + String(align) + """)
|
||||
"""
|
||||
return c.ScriptClip(runtime)
|
||||
}
|
||||
|
||||
function Cropf(clip c, float l, float t, float w, float h)
|
||||
{
|
||||
return c.MBT_LinearResize(
|
||||
\ Round(c.Width * w),
|
||||
\ Round(c.Height * h),
|
||||
\ c.Width * l,
|
||||
\ c.Height * t,
|
||||
\ c.Width * w,
|
||||
\ c.Height * h
|
||||
\)
|
||||
}
|
||||
|
||||
function RotateCrop(clip c, float angle, float "dar")
|
||||
{
|
||||
dar = Default(dar, Float(c.Width) / Float(c.Height))
|
||||
radians = angle * Pi() / 180.0
|
||||
cosine = Abs(Cos(radians))
|
||||
sine = Abs(Sin(radians))
|
||||
|
||||
crop_h = Min(
|
||||
\ Float(c.Height),
|
||||
\ Float(c.Width) / dar,
|
||||
\ Float(c.Width) / (dar * cosine + sine),
|
||||
\ Float(c.Height) / (dar * sine + cosine)
|
||||
\)
|
||||
crop_w = crop_h * dar
|
||||
|
||||
xalign = (c.Is420 || c.Is422) ? 2 : 1
|
||||
yalign = c.Is420 ? 2 : 1
|
||||
left = Ceil((c.Width - crop_w) / (2.0 * xalign)) * xalign
|
||||
top = Ceil((c.Height - crop_h) / (2.0 * yalign)) * yalign
|
||||
|
||||
turned = c.Turn(angle=angle)
|
||||
return turned.Crop(left, top, c.Width - 2 * left, c.Height - 2 * top)
|
||||
}
|
||||
|
||||
function Resize(clip v, int "w", int "h", float "dar", float "xcrop", float "ycrop", int "pos", bool "linear", string "input_matrix", string "output_matrix")
|
||||
{
|
||||
# Resize with optional aspect-ratio crop.
|
||||
# w/h: target size. dar: display aspect ratio when one dimension is omitted.
|
||||
# xcrop/ycrop: percent cropped from each side before fitting. pos uses keypad
|
||||
# placement: 1 top-left, 5 center, 9 bottom-right.
|
||||
wo = v.Width
|
||||
ho = v.Height
|
||||
|
||||
xcrop = Default(xcrop, 0.0) / 100.0
|
||||
ycrop = Default(ycrop, 0.0) / 100.0
|
||||
pos = Default(pos, 5)
|
||||
pos = (pos < 1 || pos > 9) ? 5 : pos
|
||||
|
||||
dar = Default(dar, Float(wo) / Float(ho))
|
||||
w = Defined(w) ? w : (Defined(h) ? Round(h * 0.5 * dar) * 2 : wo)
|
||||
h = Defined(h) ? h : Round(w * 0.5 / dar) * 2
|
||||
dar = Float(w) / Float(h)
|
||||
|
||||
cropped_w = (1.0 - 2.0 * xcrop) * wo
|
||||
cropped_h = (1.0 - 2.0 * ycrop) * ho
|
||||
|
||||
crop_extra_w = (cropped_w / cropped_h > dar) ? (cropped_w - cropped_h * dar) : 0.0
|
||||
crop_extra_h = (cropped_w / cropped_h < dar) ? (cropped_h - cropped_w / dar) : 0.0
|
||||
|
||||
crop_extra_t = crop_extra_h * ((pos <= 3) ? 0.0 : ((pos >= 7) ? 1.0 : 0.5))
|
||||
crop_extra_b = crop_extra_h * ((pos >= 7) ? 0.0 : ((pos <= 3) ? 1.0 : 0.5))
|
||||
crop_extra_l = crop_extra_w * ((pos % 3 == 1) ? 0.0 : ((pos % 3 == 0) ? 1.0 : 0.5))
|
||||
crop_extra_r = crop_extra_w * ((pos % 3 == 0) ? 0.0 : ((pos % 3 == 1) ? 1.0 : 0.5))
|
||||
|
||||
crop_l = wo * xcrop + crop_extra_l
|
||||
crop_t = ho * ycrop + crop_extra_t
|
||||
crop_w = cropped_w - crop_extra_l - crop_extra_r
|
||||
crop_h = cropped_h - crop_extra_t - crop_extra_b
|
||||
|
||||
input_matrix = Default(input_matrix, v.IsRGB ? MBT_DefaultMatrix(wo, ho) : MBT_GetMatrixName(v))
|
||||
output_matrix = Default(output_matrix, MBT_DefaultMatrix(w, h))
|
||||
return v.MBT_LinearResize(w, h, crop_l, crop_t, crop_w, crop_h, linear=linear, input_matrix=input_matrix, output_matrix=output_matrix)
|
||||
}
|
||||
|
||||
function MBT_LinearResize(clip src, int tw, int th,
|
||||
\ float "src_left", float "src_top", float "src_width", float "src_height",
|
||||
\ string "kernel", float "b", float "c", int "taps", float "p", int "bitdepth",
|
||||
\ string "hkernel", string "vkernel", bool "linear", string "input_matrix", string "output_matrix")
|
||||
{
|
||||
uscale = "Spline36"
|
||||
dscale = "CatmullRom"
|
||||
|
||||
hkernel = Default(hkernel , Default(kernel , (tw > src.Width ? uscale : dscale)))
|
||||
vkernel = Default(vkernel , Default(kernel , (th > src.Height ? uscale : dscale)))
|
||||
sl = Default(src_left , 0)
|
||||
st = Default(src_top , 0)
|
||||
sw = Default(src_width , src.Width)
|
||||
sh = Default(src_height , src.Height)
|
||||
b = Default(b , 1.0 / 3.0)
|
||||
c = Default(c , 1.0 / 3.0)
|
||||
p = Default(p , 30.0)
|
||||
bitdepth = Default(bitdepth , src.BitsPerComponent)
|
||||
linear = Defined(linear) ? linear : (sw / Float(tw) >= 1.5 || sh / Float(th) >= 1.5)
|
||||
input_matrix = Default(input_matrix, src.IsRGB ? MBT_DefaultMatrix(src.Width, src.Height) : MBT_GetMatrixName(src))
|
||||
output_matrix = Default(output_matrix, MBT_DefaultMatrix(tw, th))
|
||||
Assert(
|
||||
\ !linear || (FunctionExists("y_gamma_to_linear") && FunctionExists("y_linear_to_gamma")),
|
||||
\ "Resize(linear=true) requires y_gamma_to_linear and y_linear_to_gamma. Load the missing dependency or call Resize(..., linear=false)."
|
||||
\)
|
||||
|
||||
clp = (src.IsRGB ? (src.HasAlpha ? src.ConvertToPlanarRGBA
|
||||
\ : src.ConvertToPlanarRGB)
|
||||
\ : src.ConvertToPlanarRGB(matrix=input_matrix))
|
||||
clp = clp.ConvertBits(32)
|
||||
clp = linear ? clp.y_gamma_to_linear : clp
|
||||
|
||||
if (hkernel != vkernel) {
|
||||
htaps = Default(taps, (hkernel == "Lanczos" ? 3 : 4))
|
||||
vtaps = Default(taps, (vkernel == "Lanczos" ? 3 : 4))
|
||||
clp = clp.MBT_LinearResize(tw, src.Height, sl, 0, sw, 0, hkernel, b, c, htaps, p, linear=false, input_matrix=input_matrix, output_matrix=input_matrix)
|
||||
clp = clp.MBT_LinearResize(tw, th, 0, st, 0, sh, vkernel, b, c, vtaps, p, linear=false, input_matrix=input_matrix, output_matrix=output_matrix)
|
||||
}
|
||||
else {
|
||||
taps = Default(taps, (hkernel == "Lanczos" ? 3 : 4))
|
||||
clp =
|
||||
\ (hkernel == "Bicubic" ) ? clp.BicubicResize(tw, th, b=b, c=c, src_left=sl, src_top=st, src_width=sw, src_height=sh)
|
||||
\ : (hkernel == "Bilinear" ) ? clp.BilinearResize(tw, th, src_left=sl, src_top=st, src_width=sw, src_height=sh)
|
||||
\ : (hkernel == "Blackman" ) ? clp.BlackmanResize(tw, th, src_left=sl, src_top=st, src_width=sw, src_height=sh, taps=taps)
|
||||
\ : (hkernel == "Gauss" ) ? clp.GaussResize(tw, th, src_left=sl, src_top=st, src_width=sw, src_height=sh, p=p)
|
||||
\ : (hkernel == "Lanczos" ) ? clp.LanczosResize(tw, th, src_left=sl, src_top=st, src_width=sw, src_height=sh, taps=taps)
|
||||
\ : (hkernel == "Lanczos4" ) ? clp.Lanczos4Resize(tw, th, src_left=sl, src_top=st, src_width=sw, src_height=sh)
|
||||
\ : (hkernel == "Point" ) ? clp.PointResize(tw, th, src_left=sl, src_top=st, src_width=sw, src_height=sh)
|
||||
\ : (hkernel == "Sinc" ) ? clp.SincResize(tw, th, src_left=sl, src_top=st, src_width=sw, src_height=sh, taps=taps)
|
||||
\ : (hkernel == "Spline16" ) ? clp.Spline16Resize(tw, th, src_left=sl, src_top=st, src_width=sw, src_height=sh)
|
||||
\ : (hkernel == "Spline36" ) ? clp.Spline36Resize(tw, th, src_left=sl, src_top=st, src_width=sw, src_height=sh)
|
||||
\ : (hkernel == "Spline64" ) ? clp.Spline64Resize(tw, th, src_left=sl, src_top=st, src_width=sw, src_height=sh)
|
||||
\ : (hkernel == "CatmullRom" ) ? clp.BicubicResize(tw, th, b=0.0, c=0.5, src_left=sl, src_top=st, src_width=sw, src_height=sh)
|
||||
\ : Assert(false, "Invalid resize kernel.")
|
||||
}
|
||||
|
||||
clp = linear ? clp.y_linear_to_gamma : clp
|
||||
clp = src.IsRGB ? (src.HasAlpha ? clp.ConvertToPlanarRGBA : clp.ConvertToPlanarRGB)
|
||||
\ : (src.Is420 ? clp.ConvertToYUV420(matrix=output_matrix).ConvertBits(bitdepth).MBT_SetMatrix(output_matrix)
|
||||
\ : (src.Is422 ? clp.ConvertToYUV422(matrix=output_matrix).ConvertBits(bitdepth).MBT_SetMatrix(output_matrix)
|
||||
\ : (src.Is444 ? clp.ConvertToYUV444(matrix=output_matrix).ConvertBits(bitdepth).MBT_SetMatrix(output_matrix) : clp.ConvertBits(bitdepth).MBT_SetMatrix(output_matrix))))
|
||||
clp = src.IsRGB ? clp.ConvertBits(bitdepth) : clp
|
||||
|
||||
return clp
|
||||
}
|
||||
|
||||
function MBT_DefaultMatrix(int w, int h)
|
||||
{
|
||||
return (w >= 3840 || h >= 2160) ? "Rec2020" : ((w >= 1280 || h >= 720) ? "Rec709" : "Rec601")
|
||||
}
|
||||
|
||||
function MBT_MatrixNameFromCode(int matrix)
|
||||
{
|
||||
return (matrix == 1) ? "Rec709"
|
||||
\ : (matrix == 9) ? "Rec2020"
|
||||
\ : (matrix == 10) ? "Rec2020"
|
||||
\ : (matrix == 5) ? "Rec601"
|
||||
\ : (matrix == 6) ? "Rec601"
|
||||
\ : ""
|
||||
}
|
||||
|
||||
function MBT_MatrixCodeForConvert(string matrix)
|
||||
{
|
||||
return (matrix == "Rec601") ? "601"
|
||||
\ : (matrix == "Rec709") ? "709"
|
||||
\ : (matrix == "Rec2020") ? "2020"
|
||||
\ : matrix
|
||||
}
|
||||
|
||||
function MBT_MatrixInt(string matrix)
|
||||
{
|
||||
return (matrix == "Rec709") ? 1
|
||||
\ : (matrix == "Rec2020") ? 9
|
||||
\ : (matrix == "Rec601") ? 6
|
||||
\ : 2
|
||||
}
|
||||
|
||||
function MBT_GetMatrixCode(clip c)
|
||||
{
|
||||
matrix = MBT_MatrixNameFromCode(c.PropGetInt("_Matrix"))
|
||||
return (matrix == "") ? MBT_MatrixInt(MBT_DefaultMatrix(c.Width, c.Height)) : c.PropGetInt("_Matrix")
|
||||
}
|
||||
|
||||
function MBT_GetMatrixName(clip c)
|
||||
{
|
||||
matrix = MBT_MatrixNameFromCode(MBT_GetMatrixCode(c))
|
||||
return (matrix == "") ? MBT_DefaultMatrix(c.Width, c.Height) : matrix
|
||||
}
|
||||
|
||||
function MBT_SetMatrix(clip c, string matrix)
|
||||
{
|
||||
return c.PropSet("_Matrix", MBT_MatrixInt(matrix))
|
||||
}
|
||||
|
||||
function MBT_CorrectMatrix(clip c, string "input_matrix", string "output_matrix")
|
||||
{
|
||||
input_matrix = Default(input_matrix, MBT_GetMatrixName(c))
|
||||
output_matrix = Default(output_matrix, MBT_DefaultMatrix(c.Width, c.Height))
|
||||
matrix = MBT_MatrixCodeForConvert(input_matrix) + ":auto=>" + MBT_MatrixCodeForConvert(output_matrix) + ":same"
|
||||
bitdepth = c.BitsPerComponent
|
||||
return c.IsRGB ? c
|
||||
\ : (c.Is420 ? c.ConvertToYUV420(matrix=matrix).ConvertBits(bitdepth).MBT_SetMatrix(output_matrix)
|
||||
\ : (c.Is422 ? c.ConvertToYUV422(matrix=matrix).ConvertBits(bitdepth).MBT_SetMatrix(output_matrix)
|
||||
\ : (c.Is444 ? c.ConvertToYUV444(matrix=matrix).ConvertBits(bitdepth).MBT_SetMatrix(output_matrix) : c.MBT_SetMatrix(output_matrix))))
|
||||
}
|
||||
|
||||
function DeShake(clip c, int "w", int "h", float "dar", float "crop", float "xcrop", float "ycrop", int "pos", bool "zoom", bool "rot", float "freq")
|
||||
{
|
||||
# Stabilize through MVTools + DePan functions. Those plugins must be loaded
|
||||
# in Avisynth before this function is called.
|
||||
crop = Default(crop, 2.5)
|
||||
xcrop = Default(xcrop, crop)
|
||||
ycrop = Default(ycrop, crop)
|
||||
zoom = Default(zoom, true)
|
||||
rot = Default(rot, true)
|
||||
freq = Default(freq, 1.0)
|
||||
|
||||
vectors = c.MSuper().MAnalyse(isb=false, dct=5)
|
||||
mdata = MDepan(c, vectors, thscd1=1000, thscd2=1000, zoom=zoom, rot=rot, error=255)
|
||||
stabilized = DePanStabilize(
|
||||
\ c,
|
||||
\ data=mdata,
|
||||
\ dxmax=c.Width * xcrop / 100.0,
|
||||
\ dymax=c.Height * ycrop / 100.0,
|
||||
\ rotmax=3.0,
|
||||
\ mirror=15,
|
||||
\ cutoff=freq
|
||||
\)
|
||||
return (Defined(w) || Defined(h) || Defined(dar)) ? Resize(stabilized, w, h, dar, xcrop, ycrop, pos) : stabilized
|
||||
}
|
||||
|
||||
function FixContrast(clip c, int "low", int "high")
|
||||
{
|
||||
# Map input luma range to limited-range video luma.
|
||||
low = Default(low, 16)
|
||||
high = Default(high, 235)
|
||||
return c.Levels(low, 1.0, high, 16, 235, coring=false)
|
||||
}
|
||||
Reference in New Issue
Block a user