I managed to fix my file. I found the mpdecimate
filter, which drops duplicate or near duplicate frames from a video stream. First I tried:
ffmpeg -loglevel debug -i orig.mp4 -an -vf "mpdecimate" test.mp4
I added -loglevel debug
to get more info during transcoding. The info showed what mpdecimate
was doing with the frames, which was lots and lots of this pattern:
lo:0<217 lo:0<-2147483648 lo:0<-2147483648 drop pts:44032 pts_time:3.44 drop_count:1 lo:0<217 lo:0<-2147483648 lo:0<-2147483648 drop pts:44544 pts_time:3.48 drop_count:2 lo:0<217 lo:0<-2147483648 lo:0<-2147483648 drop pts:45056 pts_time:3.52 drop_count:3 lo:0<217 lo:0<-2147483648 lo:0<-2147483648 drop pts:45568 pts_time:3.56 drop_count:4 781>=hi keep pts:46080 pts_time:3.6 drop_count:-1 lo:0<217 lo:0<-2147483648 lo:0<-2147483648 drop pts:46592 pts_time:3.64 drop_count:1 lo:0<217 lo:0<-2147483648 lo:0<-2147483648 drop pts:47104 pts_time:3.68 drop_count:2 lo:0<217 lo:0<-2147483648 lo:0<-2147483648 drop pts:47616 pts_time:3.72 drop_count:3 lo:0<217 lo:0<-2147483648 lo:0<-2147483648 drop pts:48128 pts_time:3.76 drop_count:4 821>=hi keep pts:48640 pts_time:3.8 drop_count:-1 lo:0<217 lo:0<-2147483648 lo:0<-2147483648 drop pts:49152 pts_time:3.84 drop_count:1 lo:0<217 lo:0<-2147483648 lo:0<-2147483648 drop pts:49664 pts_time:3.88 drop_count:2 lo:0<217 lo:0<-2147483648 lo:0<-2147483648 drop pts:50176 pts_time:3.92 drop_count:3 lo:0<217 lo:0<-2147483648 lo:0<-2147483648 drop pts:50688 pts_time:3.96 drop_count:4 793>=hi keep pts:51200 pts_time:4 drop_count:-1
I.e., it was consistently dropping 4 frames in a row as duplicates and keeping every 5th. This showed that the original frame rate was 1/5th of what it was now. I was lucky! Since the video's current 25 fps was a multiple of the original frame rate, there shouldn't be a problem with temporal misalignment of the kept and dropped frames. Therefore I retranscoded the original video with nothing more complex than -vf "fps=5"
, and the output seemed to be fine. Just to be sure, I piped the output through the mpdecimate
filter, and it detected all remaining frames as a "keep". So the original file was not so messed up as I thought.