Average motion vector tutorial (0.10)
A previous post gave an average tutorial on how to glitch motion vectors by using an average of motion vectors.
A lot has changed since then, and ffglitch
(starting with
version 0.10.0
)
now has optimized code to speed up array manipulations and calculations
in JavaScript
.
You can check out the documentation (yes, there
is documentation now!) to check the full extent of the added
functionality.
Here’s the original video again:
And the optimized script mv_average_010.js
:
// global variable holding forward motion vectors from previous frames
let prev_fwd_mvs = [ ];
let total_sum;
// change this value to use a smaller or greater number of frames to
// perform the average of motion vectors
// you can also change it using the `-sp <num>` command line option
let tail_length = 10;
let tail_length_mv;
export function setup(args)
{
// select motion vector feature
args.features = [ "mv" ];
// parse tail_length param from command line if available
if ( "params" in args )
tail_length = args.params;
tail_length_mv = MV(tail_length, tail_length);
}
export function glitch_frame(frame)
{
// bail out if we have no forward motion vectors
const fwd_mvs = frame.mv?.forward;
if ( !fwd_mvs )
return;
// set motion vector overflow behaviour in ffedit to "truncate"
frame.mv.overflow = "truncate";
// update variable holding forward motion vectors from previous
// frames. note that we perform a deep copy of the clean motion
// vector values before modifying them.
const deep_copy = fwd_mvs.dup();
// push to the end of array
prev_fwd_mvs.push(deep_copy);
// initialize total_sum to a [0,0] MV2DArray.
if ( !total_sum )
total_sum = new MV2DArray(fwd_mvs.width, fwd_mvs.height);
// update total_sum by removing the motion vector values from the
// oldest frame and adding the values from the current frame.
if ( prev_fwd_mvs.length > tail_length )
{
total_sum.sub(prev_fwd_mvs[0]);
prev_fwd_mvs = prev_fwd_mvs.slice(1);
}
total_sum.add(deep_copy);
// set new values for current frame to (total_sum / tail_length)
if ( prev_fwd_mvs.length == tail_length )
{
fwd_mvs.assign(total_sum);
fwd_mvs.div(tail_length_mv);
}
}
Now run ffedit
with mv_average_010.js
to glitch the file:
$ ffedit -i trompette_eating.mpg -s mv_average_010.js -sp 10 -o trompette_eating_glitched.mpg
(note the -sp 10
script parameter, which can be used to set tail_length
inside the script from the command line.
check the ffedit
documentation for more information on command line parameters)
And this is the resulting trompette_eating_glitched.mpg
:
Prior to 0.10.0
, with the old version of the script, I used to get
around 15 fps
.
With the optimized script, I get around 300 fps
.
That’s a whopping 20x
speedup!