Ghosts S01e11 Libvpx !new! 〈Proven〉
Welcome to Ghosts S01E11: Libvpx . Let’s exorcise it. It started with a routine archival job. We were transcoding a film scan (ProRes 4444 → WebM) for a client’s interactive museum installation. The command was standard:
Ghosts in the Machine: Debugging FFmpeg’s Libvpx Encoder (Season 1, Episode 11)
Drop your Libvpx war stories in the comments below. ghosts s01e11 libvpx
The ghosting bug in Libvpx v1.11.0–v1.12.0 is largely fixed in v1.13.0+. The patch (Change-Id: I8a3f7b2e9c4d1a5f6e7b8c9d0e1f2a3b4c5d6e7f) corrects the reference frame buffer reset logic after scene detection.
ffmpeg -i master.mov -c:v libvpx-vp9 -pix_fmt yuv420p10le -crf 18 -b:v 0 output.webm The first pass looked incredible. Grain was preserved. Banding was minimal. But during playback on a high-refresh-rate display, we noticed it: . Welcome to Ghosts S01E11: Libvpx
Pause the video. Look at frame 1042. Fine. Advance one frame. A faint, semi-transparent outline of frame 1042 remains superimposed over frame 1043. Another frame forward? The ghost fades. But it shouldn't be there at all.
ffmpeg -i input.mov -c:v libvpx-vp9 -b:v 0 -crf 18 -pass 1 -f null /dev/null ffmpeg -i input.mov -c:v libvpx-vp9 -b:v 0 -crf 18 -pass 2 output.webm Libvpx is a phenomenal encoder—it often beats x265 at half the bitrate for animated or grainy content. But it is also a complex state machine. Ghosting artifacts are a reminder that "lossy" doesn't just mean losing detail; sometimes, it means gaining things that were never there. We were transcoding a film scan (ProRes 4444
ffmpeg -i input.mov -c:v libvpx-vp9 \ -tile-columns 2 -row-mt 1 \ -lag-in-frames 16 \ # Reduce from default 25 -auto-alt-ref 1 \ # Keep on, but be careful -arnr-maxframes 3 \ # Reduce temporal filtering -cpu-used 2 \ output.webm Two-pass encoding often masks the bug because the first pass forces the encoder to re-evaluate scene boundaries more strictly.