Уменьшите частоту кадров видео без потери полезных кадров

2399
Boann

У меня есть видео с камеры безопасности, которое было изначально записано с низкой частотой кадров, возможно, 15 кадров в секунду, возможно, 10 кадров в секунду, может быть, даже меньше. С тех пор он был преобразован кем-то еще в 25 кадров в секунду (без изменения длительности). Я предполагаю, что были добавлены дополнительные дублирующие кадры, и, возможно, это также немного исказило точное время, в которое отображаются исходные кадры.

Я хочу перекодировать видео с помощью ffmpeg в исходную частоту кадров, не отбрасывая ни одного полезного кадра реального движения. Если я просто использую fpsфильтр, он не будет избирательно выбирать, какие кадры он хранит, и я предполагаю, что из-за ошибок округления он может в конечном итоге сохранить некоторые дубликаты кадров и навсегда потерять полезные кадры, что ухудшит ситуацию. В любом случае, я не знаю, какое число сказать фильтру, потому что я не знаю точно, какова была первоначальная частота кадров!

Как я могу приступить к восстановлению этого видео с помощью ffmpeg?

ffmpeg -i "orig.mp4" -an -vcodec h264 -vf "fps=???" "fixed.mp4" 
3
Кажется маловероятным, что это можно сделать, особенно если вы не знаете точный «алгоритм» используемого конвертера. Звучит вроде как выпадающий между прочим. Tom Yan 8 лет назад 0

2 ответа на вопрос

4
Boann

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.

2
Gyan

If the extra frames are duplicates and not interpolations, then the following may work:

ffmpeg -i orig.mp4 -an -vf "select='gt(scene\,0.001)',setpts=N/(10*TB)" -r 10 fixed.mp4 

The idea is to select all frames not a duplicate of the preceding frame. Then PTSes are regenerated as per the output rate specified. You may have to tweak the scene value up or down to get the detection filter right. If the video appears faster or slower than real-time then lower or raise the rate (and setpts denominator value) respectively.

Я думаю, что это может сработать, но мне было трудно настроить его правильно. В конце я нашел фильтр «mpdecimate» и использовал его, который, как казалось, дает более определенный результат «дуплекс или не дуплекс» для каждого кадра. Boann 8 лет назад 0

Похожие вопросы