FFglitch:
the multimedia
bitstream editor
FOSDEM 2025
Ramiro Polla
FFmpeg + glitch art
=
FFglitch
Common glitch art examples in the wild:
- SD card corruption
- Scratched DVDs
- DVB-T reception issues
- Streaming connectivity issues
- Mostly data corruption
in some way or another... - ... that create visual artifacts
JPEG
SD card (file system) corruption
JPEG 2000
ePirat, 2018

Sample file
WMV3
Broken experimental encoder
FFglitch early history:
- Glitch Artists Collective Facebook group
- It should be possible...
- So I set out to create a bitstream editor
"Is it possible to edit the motion vectors in a video file?"
Proof of concept:
- Reuse FFmpeg codebase
- Pass 1:
- decode file normally
- export motion vectors to JSON file
- ... modify JSON file ...
- Pass 2:
- decode file again
- while decoding, replicate bitstream
- while replicating, modify motion vectors
GetBitContext:
- Structure used to read bits
from a bitstream - Functions such as:
- get_bits1()
- get_bits(n)
- get_vlc2() [variable length codes]

MPEG-4 P frame
with motion vectors
MPEG-4 inter macroblock
Bytes:
52 C1 D2 [...]
Bitstream:
01000100 10000100 11000001
01000100 10000100 11000001
get_bits1():
0 not_coded
01000100 10000100 11000001
get_vlc2():
1 cbpc
01000100 10000100 11000001
get_vlc2():
00010 cbpy
01000100 10000100 11000001
get_vlc2():
get_bits1():
get_bits(5):
01
0 MV delta x (3)
00010
\}
01000100 10000100 11000001
get_vlc2():
get_bits1():
get_bits(5):
01
1 MV delta y (-1)
00000
\}
01000100 10000100 11000001
PutBitContext:
- Structure used to write bits
to a bitstream - Functions such as:
- put_bits()
Bitstream replication:
Input:
01000100 10000100 11000001
01000100 10000100 11000001
get_bits1():
0 put_bits(0)
0
Output:
01000100 10000100 11000001
get_vlc2():
1 put_bits(1)
01
01000100 10000100 11000001
get_vlc2():
00010 put_bits(00010)
0100010
01000100 10000100 11000001
get_vlc2():
get_bits1():
get_bits(5):
01
0 put_bits(01000010)
00010
\}
01000100 1000010
01000100 10000100 11000001
get_vlc2():
get_bits1():
get_bits(5):
01
1 put_bits(01100000)
00000
\}
01000100 10000100 11000001
01000100 10000100 1100000
0put_bits(01000010)
00010 put_bits(1)
Bitstream transplication:
Input:
01000100 10000100 11000001
01000100 10000100 11000001
get_bits1():
0 put_bits(0)
0
Output:
01000100 10000100 11000001
get_vlc2():
1 put_bits(1)
01
01000100 10000100 11000001
get_vlc2():
00010 put_bits(00010)
0100010
0100010
01000100 10000100 11000001
get_vlc2():
get_bits1():
get_bits(5):
01
0
00010
\|
01000101
01000100 10000100 11000001
get_vlc2():
get_bits1():
get_bits(5):
01
1 put_bits(01100000)
00000
\}
01000100 10000100 11000001
01000101 01100000
0 put_bits(1)
export function glitch_frame(frame)
{
// get the forward motion vectors
const fwd_mvs = frame.mv?.forward;
if ( !fwd_mvs )
return;
// clear horizontal element of all motion vectors
for ( let i = 0; i < fwd_mvs.length; i++ )
{
// loop through all rows
const row = fwd_mvs[i];
for ( let j = 0; j < row.length; j++ )
{
// loop through all macroblocks
const mv = row[j];
mv[0] = 0; // this sets the horizontal motion vector to zero
}
}
}
mv_sink_and_rise.js
Glitched file
MPEG-2 glitch
PNG
change filter type from "up" to "avg"


JPEG
from pixels to bitstream

Supported codecs:
- JPEG
(DCT coefficients, Quantization Table) - MPEG-2
(DCT coefficients, Motion Vectors, qscale) - MPEG-4
(Motion Vectors, Global Motion Compensation) - PNG
(Headers, Image Data (IDAT))
Supported formats:
- rawvideo
- AVI
- MOV
Extra features:
- Scripting support through QuickJS and Python3
- HID support with SDL2
- MIDI controllers support with RtMidi
- Network support using ZeroMQ
FFglitch is 3 programs:
- ffedit (new tool)
- the main tool for FFglitch
- it's a multimedia bitstream editor
- fflive (it's the 'ffplay' binary)
- integrated with bitstream editor
- create live glitch in real-time
- ffgac (it's the 'ffmpeg' binary)
- but with some extra features for glitch artists
Upstreaming to FFmpeg?
- Most of it is way outside the scope of FFmpeg
- Capture support (v4l2)
- Bug fixes
- Tests
- Optimizations
Orange Pi 5 Ultra

What's next for FFglitch?
- More video codecs (H.264, AV1, ...)
- More image codecs (GIF, JPEG 2000)
- Audio codecs! (MP3, AAC)
- Integration with live mixing/streaming:
- Syphon
- Spout
- Steganography (?)
- Codec security (?) (kind of like h26forge)
- Your contributions!!!!!!
Gallery
Kaspar Ravel and Thomas Collet
Thomas Collet
Sébastien Brias
fflive demo
Thank you!
- https://ffglitch.org
- https://github.com/ramiropolla
- https://instagram.com/ffglitch.art
- ramiro.polla@gmail.com
Let's go for a 🍺 later today and talk about glitch art!
FFglitch FOSDEM 2025
By Ramiro Polla
FFglitch FOSDEM 2025
- 74