Umamio
25th January 2016, 18:59
I'm just coming back into the world of avisynth after almost a decade away, and it appears that VapourSynth is now the most stable multi-threaded solution on Linux.
I have a need to create a basic plugin that allows for these kinds of acceleration/deceleration effects (http://easings.net/) when moving clips between points in a frame, and essentially enabling easings on any function that can be animated.
What's the best place to get started, in terms of documentation?
"Just put some maths in your scriptClip" is also an acceptable answer.
"Someone has already done this" is an even better answer.
Myrsloik
25th January 2016, 19:07
"Just put some maths into your FrameEval (http://www.vapoursynth.com/doc/functions/frameeval.html)" <- I fixed it for you
The rest should be conceptually identical to the Avisynth way. I guess. Unless you were intending to use a function like overlay with offsets, you'll have to recreate that yourself using crop+addborders.
splinter98
29th January 2016, 13:56
for transitions I would create alpha masks that provided the transitions and then use MaskedMerge rather than overlay. (Adding borders is still required on smaller clips).
For simple video fading/Transition effects below is something I wrote previously for such an effect (written as a module so it can be imported or if run directly as a test):
import vapoursynth as vs
from math import cos, pi
from sys import stderr
from functools import partial
core = vs.get_core()
#Dict of easing functions that output a number between 0-1
easings = {'linear': lambda n,t: n/t,
'cubic': lambda n,t: (n/t)**3,
'sine': lambda n,t: -0.5 * (cos(pi * n / t)-1),
'expo': lambda n,t: n if n in [0,t] else (0.5 * 2**(10*((2*n/t)-1)) if 2*n/t < 1 else 0.5*(-2**(-10*((2*n/t)-1))+2))
}
def crossfade(clipa, clipb, num_frames, fade_cb=easings['linear']):
"""Produces a Fade affect from cliba to clipb
fade_cb = what easing function to use
num_frames = number of frames to fade across"""
fade = lambda n,blk,wht: core.std.Merge(blk, wht, fade_cb(n, num_frames))#n/num_frames
return apply_transition(clipa, clipb, num_frames, fade)
def wipe(clipa, clipb, num_frames, speed=easings['linear'], direction="ltr"):
"""Produces a Wipe transition from cliba to clipb
speed = what easing function to use
num_frames = number of frames to fade across"""
if direction in ["ltr", "rtl"]:
stack = core.std.StackHorizontal
cropdir = "left"
mult = clipa.width
elif direction in ["ttb", "btt"]:
stack = core.std.StackVertical
cropdir = "top"
mult = clipa.height
else:
raise ValueError
def wiper(n, blk, wht):
whtw = int(speed(n, num_frames)*mult)
blkw = mult-whtw
if direction in ["rtl", "btt"]:
blkw, whtw = whtw,blkw
blk, wht = wht, blk
if whtw == 0:
return blk
elif blkw == 0:
return wht
return stack([core.std.CropRel(wht, **{cropdir:blkw}),
core.std.CropRel(blk, **{cropdir:whtw})])
return apply_transition(clipa, clipb, num_frames, wiper)
def apply_transition(clipa, clipb, num_frames, transition):
fmt = clipa.format
blk = core.std.BlankClip(clipa, length=1, format=vs.GRAY8)
wht = core.std.BlankClip(blk, color=[255])
alen = len(clipa)-num_frames
blen = len(clipb)-num_frames
if alen < 1:
raise ValueError("Clip A too Short {} < {}".format(len(clipa), num_frames))
if blen <1:
raise ValueError("Clip B too Short {} < {}".format(len(clipb), num_frames))
alpha = blk*alen
for n in range(num_frames):
alpha += transition(n, blk, wht)
alpha += wht*blen
clipl = clipa+clipb[num_frames:]
clipr = clipa[:-num_frames]+clipb
alpha = core.resize.Bicubic(alpha, format=clipl.format.id)
return core.std.MaskedMerge(clipl, clipr, alpha)
def test():
t = core.std.BlankClip(width=480, height=1080, length=35, color=[255,255,0])
t = core.text.FrameNum(t, 7)
b = core.std.BlankClip(t, color=[0,255,255])
b = core.text.FrameNum(b, 7)
num_frames = 30
out = core.std.StackHorizontal([
wipe(t, b, num_frames, easings['linear'], "ttb"),
wipe(t, b, num_frames, easings['sine'], "ttb"),
wipe(t, b, num_frames, easings['expo'], "ttb"),
wipe(t, b, num_frames, easings['cubic'], "ttb"),
])
out = out.resize.Bicubic(format=vs.YUV420P8, matrix_s="709")
print(out, file=stderr)
(out*10).set_output()
if __name__ == "__vapoursynth__":
test()
vBulletin® v3.8.11, Copyright ©2000-2025, vBulletin Solutions Inc.