Home > Blog > Tomato v2.0 - AVI breaker

Tomato v2.0 - AVI breaker



tl;dr tomato v2.0 is available here on my github page.

in 2017 I made a small python script to facilitate and automatize glitching AVI files by modifying directly the index and not the actual data. As much as it saved my life on big glitchy projects the script did have a few problems. Firstly the index of AVI files isn't always reliable, some video players will even ignore it, but most importantly deleted keyframes would often be fixed in the baking process unless used accordingly alongside an avidemux command line interface that was only available on windows. Moreover, files that were over 4Gb do not have the same type of index, which maked them completely incompatible.

Seeings as the actual frame data is referenced the same way inside the "movi" tag as is the index data in the "idx1" tag, I decided to trade a little performance for utility by acting directly on the frame data rather than the index data. Fixing all the problems mentioned above.

For full reference on the AVI file format check this, but in the meantime if you've never looked inside an AVI video file look closely below :

corresponding frame markers in the index and movie blocks

See how the data in both blocks is announced the same way ? That's just perfect.
Switching from the index tag to the movie tag opened a lot of others doors. Not only is the data now hardcoded into the glitched videos which makes them more resilient and easier to bake, but fragile codecs like zmbv and more are now glitchable too <3

example of zmbv codec glitch

So what's new ?

  • updated for Python 3
  • can glitch files > 4Gb
  • all glitches are now bake proof
  • the first frame can be ignored or included in the mix with -ff [0 or 1]
    (defaults to ignored with -ff 1)
  • [experimental] audio frames can be added in the glitch mix with -a [0 or 1]
    (defaults to off with -a 0)
  • keyframe removal is not a mode anymore it is comes as a kill parameter -k [0 to 1]
    (defaults to 0.7) which lets us delete frames with too many intra-macroblocks
    as well as keyframes if we wish.
  • no need to give file output, an automatic name based on your params is generated.

Kill Parameter - Removing Keyframes

The iframe removal was the trickiest because frame type differentiation is done in the index but not in the actual data. To implement it anyway I made this parameter I mentioned above called kill which takes a value between 0 and 1. What it does is calculate the size of the biggest frame of the video, and then ignores every frame that is smaller than the biggest frame size multiplied by the kill parameter. Here's a small pseudo code :

for x in list_of_frames:
	if x[frame_size] < (biggest_frame_size * kill) :
                # probably a predictive or sound frame !
		# keep frame
	else :
                # probably an iframe !
		# ignore frame 

This works surprisingly well because there is a very big size difference between keyframes and predictive frames. For now the parameter defaults to 0.7, and the reason I made this value tweakable is for those of you who struggle with predictive frames that contain a lot of intra-macroblocks (predictive frames that update only parts of a scene). By setting this parameter to lower values you'll ignore more frames, starting with the annoying ones I just mentioned. If you set the parameter to 1 you keep all frames.

Modes

  • Void : does nothing
  • Random : randomizes frame order
  • Reverse : reverse frame order
  • Invert : switches each consecutive frame with each other
  • Bloom : multiplies c frame n times
  • Pulse : every c frame multiples the frame n times
  • Overlap : repeat sequence of c frames every n frames

Nothing much changes here, except I broke the jiggle mode, sorry Tomasz :3. The syntax is still really simple and if you're familiar with python list comprehension you're going to have a blast at coding your own. To get an idea of how simple the modes are check this code :

if mode == "random":
	final = random.sample(clean,len(clean))

if mode == "reverse":
	final = clean[::-1]

if mode == "invert":
	final = sum(zip(clean[1::2], clean[::2]), ())

if mode == 'bloom':
	repeat = int(countframes)
	frame = int(positframes)
	lista = clean[:frame]
	listb = clean[frame:]
	final = lista + ([clean[frame]]*repeat) + listb

Examples

[src 4K libxvid] python tomato.py -i input.avi -m pulse -c 4 -n 1 -k 0.5
If you have any questions, notice any mistakes or want to hire me for research/art
feel free to send me an email me at kaspar.ravel[at]gmail[dot]com
for more visual art and less text you can follow my work on facebook or instagram
And whoever you are stranger, thank you for existing and being passionate about things.