1

I have many cine films that have been digitally converted. They have been converted as a 25 fps with 2 frames in every 23 duplicated. I need to remove the duplicated frames using a bitstream filter so there is no decoding/encoding.

After removing the frames I will change to the original cine frame rate of 18 fps. I will then change the frame rate to 25 fps using duplicated frames. I don't want to interpolate as I want to preserve the jerky format of the cine. Finally I will video editing software that will do the final encoding.

All the additional steps will cause several stages of decoding/encoding, that I need to avoid.

First I used a combination of the answers to FFmpeg remove video frames at specific intervals and FFmpeg remove every 6th frame starting from the 3rd frame, on an mp4 file to check it works. I modified it to remove every 4th and 17th frame in 25.

ffmpeg -loglevel warning -i cine.mp4 -an -vf "select='if((mod(n-4,25)),(mod(n-17,25)))',setpts='N/FRAME_RATE/TB'" cine-23.mp4

This works fine, but I end up with a file a quarter the size.

I now used Gyan's answer in Using ffmpeg to change framerate to extract the raw bitstream.

ffmpeg -loglevel warning -i cine.mp4 -c copy -f h264 cine.h264

This created the h264 file as expected, surprisingly it was 16 kB smaller than the original (67 GB file size).

I then modified the code to use the .h264 file.

ffmpeg -loglevel warning -i cine.h264 -vf "select='if((mod(n-4,25)),(mod(n-17,25)))',setpts='N/FRAME_RATE/TB'" cine-23.h264

This gave the following error, but created the cine-23.h264 file although it was the same size as cine-23.mp4 in the test above

[h264 @ 00000245ec0bfb80] non-existing SPS 0 referenced in buffering period
    Last message repeated 1 times

I then checked the ffmpeg bitstream filter documentation and found the bitstream filter setts. I changed my code to the following.

ffmpeg -loglevel warning -i cine.h264 -bsf:v "select='if((mod(n-4,25)),(mod(n-17,25)))',setts=pts='N/FRAME_RATE/TB'" cine-23.h264

Which resulted in the following error.

[vost#0:0/libx264 @ 000002916cf173c0] Error parsing bitstream filter sequence 'select='if((mod(n-4,25)),(mod(n-17,25)))',setts=pts='N/FRAME_RATE/TB'': Bitstream filter not found
Error opening output file cine-23.h264.
Error opening output files: Bitstream filter not found

I'm assuming the error is because setts does not support select. Is there another way to achieve what I am looking for?

I could use mpdecimate but as that has to compare each frame it is much slower than defining it only needs to delete frames 4 and 17 in every second.

This is the output of ffprobe on my original file. (updated)

ffprobe version 2023-11-28-git-47e214245b-full_build-www.gyan.dev Copyright (c) 2007-2023 the FFmpeg developers
  built with gcc 12.2.0 (Rev10, Built by MSYS2 project)
  configuration: --enable-gpl --enable-version3 --enable-static --pkg-config=pkgconf --disable-w32threads --disable-autodetect --enable-fontconfig --enable-iconv --enable-gnutls --enable-libxml2 --enable-gmp --enable-bzlib --enable-lzma --enable-libsnappy --enable-zlib --enable-librist --enable-libsrt --enable-libssh --enable-libzmq --enable-avisynth --enable-libbluray --enable-libcaca --enable-sdl2 --enable-libaribb24 --enable-libaribcaption --enable-libdav1d --enable-libdavs2 --enable-libuavs3d --enable-libzvbi --enable-librav1e --enable-libsvtav1 --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs2 --enable-libxvid --enable-libaom --enable-libjxl --enable-libopenjpeg --enable-libvpx --enable-mediafoundation --enable-libass --enable-frei0r --enable-libfreetype --enable-libfribidi --enable-libharfbuzz --enable-liblensfun --enable-libvidstab --enable-libvmaf --enable-libzimg --enable-amf --enable-cuda-llvm --enable-cuvid --enable-ffnvcodec --enable-nvdec --enable-nvenc --enable-dxva2 --enable-d3d11va --enable-libvpl --enable-libshaderc --enable-vulkan --enable-libplacebo --enable-opencl --enable-libcdio --enable-libgme --enable-libmodplug --enable-libopenmpt --enable-libopencore-amrwb --enable-libmp3lame --enable-libshine --enable-libtheora --enable-libtwolame --enable-libvo-amrwbenc --enable-libcodec2 --enable-libilbc --enable-libgsm --enable-libopencore-amrnb --enable-libopus --enable-libspeex --enable-libvorbis --enable-ladspa --enable-libbs2b --enable-libflite --enable-libmysofa --enable-librubberband --enable-libsoxr --enable-chromaprint
  libavutil      58. 32.100 / 58. 32.100
  libavcodec     60. 35.100 / 60. 35.100
  libavformat    60. 18.100 / 60. 18.100
  libavdevice    60.  4.100 / 60.  4.100
  libavfilter     9. 14.100 /  9. 14.100
  libswscale      7.  6.100 /  7.  6.100
  libswresample   4. 13.100 /  4. 13.100
  libpostproc    57.  4.100 / 57.  4.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '1) 1961-62.mp4':
  Metadata:
    major_brand     : mp42
    minor_version   : 0
    compatible_brands: mp42mp41
    creation_time   : 2023-11-10T18:48:15.000000Z
  Duration: 00:01:53.80, start: 0.000000, bitrate: 10024 kb/s
  Stream #0:0[0x1](eng): Video: h264 (Main) (avc1 / 0x31637661), yuv420p(tv, bt470bg, progressive), 720x576 [SAR 128:117 DAR 160:117], 10021 kb/s, SAR 787:720 DAR 787:576, 25 fps, 25 tbr, 25k tbn (default)
    Metadata:
      creation_time   : 2023-11-10T18:48:15.000000Z
      handler_name    : ?Mainconcept Video Media Handler
      vendor_id       : [0][0][0][0]
      encoder         : AVC Coding
7
  • Updated the ffprobe output as it was from a different file.
    – DaveB44
    Commented Jun 15 at 16:39
  • Consider that H.264 elementary stream doesn't have PTS timestamps (the PTS are part of the container). I think there is a way to mark a frame for not to be displayed by the player (without reencoding). As far as I know, it is not possible using FFmpeg.
    – Rotem
    Commented Jun 15 at 18:20
  • select is not a bsf.
    – Tom Yan
    Commented Jun 15 at 18:47
  • Thanks for the confirmation@TomYan.
    – DaveB44
    Commented Jun 16 at 20:00
  • Thanks for the clarification @Rotem.
    – DaveB44
    Commented Jun 16 at 20:00

0

You must log in to answer this question.

Browse other questions tagged .