0

I want to cut a video into many segments and then stitch them back together. To account for videos that have a framerate of 29.97 I cut them into 100-second videos via ffmpeg -ss 0 -t 100 which works well for the most part and outputs videos that have a duration of 100 seconds and 2997 frames.

I've noticed that for some video sources with a (constant) frame-rate of 29.97 it'll output a video with a duration of 100.034 and 2998 frames instead of the expected 100 and 2997. For subsequent segments (e.g. ffmpeg -ss 100 -t 100) it will output a video with a duration of 100.67 and 2999 frames.

The issue is that this results with segments that have overlapping frames and when I stitch the segments back together I have a video that is longer than its source and will be out of sync with the audio.

I noticed that for those problematic videos if I use ffmpeg -ss 0 -t 99.999 and ffmpeg -ss 99.999 -t 99.999 etc. it'll output videos of precisely 100 seconds and 2997 frames which solves the problem.

My question is why am I seeing these inconsistencies and how can I approach this in a reliable way that will work for all videos.

Full command:

ffmpeg -ss 0 -t 100 -i "./input.mov" -map V:0 -c:v libx264 -vf scale=-2:240 out.mp4

Logs:

ffmpeg version 2021-01-12-git-ca21cb1e36-full_build-www.gyan.dev Copyright (c) 2000-2021 the FFmpeg developers
  built with gcc 10.2.0 (Rev6, Built by MSYS2 project)
  configuration: --enable-gpl --enable-version3 --enable-static --disable-w32threads --disable-autodetect --enable-fontconfig --enable-iconv --enable-gnutls --enable-libxml2 --enable-gmp --enable-lzma --enable-libsnappy --enable-zlib --enable-libsrt --enable-libssh --enable-libzmq --enable-avisynth --enable-libbluray --enable-libcaca --enable-sdl2 --enable-libdav1d --enable-libzvbi --enable-librav1e --enable-libsvtav1 --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxvid --enable-libaom --enable-libopenjpeg --enable-libvpx --enable-libass --enable-frei0r --enable-libfreetype --enable-libfribidi --enable-libvidstab --enable-libvmaf --enable-libzimg --enable-amf --enable-cuda-llvm --enable-cuvid --enable-ffnvcodec --enable-nvdec --enable-nvenc --enable-d3d11va --enable-dxva2 --enable-libmfx --enable-libglslang --enable-vulkan --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-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      56. 63.100 / 56. 63.100
  libavcodec     58.116.100 / 58.116.100
  libavformat    58. 65.101 / 58. 65.101
  libavdevice    58. 11.103 / 58. 11.103
  libavfilter     7. 95.100 /  7. 95.100
  libswscale      5.  8.100 /  5.  8.100
  libswresample   3.  8.100 /  3.  8.100
  libpostproc    55.  8.100 / 55.  8.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from './input.mov':
  Metadata:
    major_brand     : qt  
    minor_version   : 512
    compatible_brands: qt  
    encoder         : Lavf58.35.100
  Duration: 00:07:09.83, start: 0.000000, bitrate: 37022 kb/s
    Stream #0:0: Audio: pcm_s16le (sowt / 0x74776F73), 44100 Hz, stereo, s16, 1411 kb/s (default)
    Metadata:
      handler_name    : SoundHandler
      vendor_id       : [0][0][0][0]
    Stream #0:1: Audio: pcm_s16le (sowt / 0x74776F73), 48000 Hz, stereo, s16, 1536 kb/s
    Metadata:
      handler_name    : SoundHandler
      vendor_id       : [0][0][0][0]
    Stream #0:2: Audio: pcm_s16le (sowt / 0x74776F73), 48000 Hz, stereo, s16, 1536 kb/s
    Metadata:
      handler_name    : SoundHandler
      vendor_id       : [0][0][0][0]
    Stream #0:3: Video: prores (HQ) (apch / 0x68637061), yuv422p10le(tv, bt709, progressive), 1920x1080, 32531 kb/s, SAR 1:1 DAR 16:9, 29.97 fps, 29.97 tbr, 30k tbn, 30k tbc (default)
    Metadata:
      handler_name    : VideoHandler
      vendor_id       : FFMP
      encoder         : Lavc58.64.101 prores_ks
Stream mapping:
  Stream #0:3 -> #0:0 (prores (native) -> h264 (libx264))
Press [q] to stop, [?] for help
[libx264 @ 000001a481da7080] using SAR=640/639
[libx264 @ 000001a481da7080] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 BMI2 AVX2
[libx264 @ 000001a481da7080] profile High 4:2:2, level 2.1, 4:2:2, 10-bit
[libx264 @ 000001a481da7080] 264 - core 161 r3033 0d754ec - H.264/MPEG-4 AVC codec - Copyleft 2003-2020 - http://www.videolan.org/x264.html - options: cabac=1 ref=3 deblock=1:0:0 analyse=0x3:0x113 me=hex subme=7 psy=1 psy_rd=1.00:0.00 mixed_ref=1 me_range=16 chroma_me=1 trellis=1 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=-2 threads=7 lookahead_threads=1 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=1 b_bias=0 direct=1 weightb=1 open_gop=0 weightp=2 keyint=250 keyint_min=25 scenecut=40 intra_refresh=0 rc_lookahead=40 rc=crf mbtree=1 crf=23.0 qcomp=0.60 qpmin=0 qpmax=81 qpstep=4 ip_ratio=1.40 aq=1:1.00
Output #0, mp4, to 'out.mp4':
  Metadata:
    major_brand     : qt  
    minor_version   : 512
    compatible_brands: qt  
    encoder         : Lavf58.65.101
    Stream #0:0: Video: h264 (avc1 / 0x31637661), yuv422p10le(tv, bt709, progressive), 426x240 [SAR 640:639 DAR 16:9], q=2-31, 29.97 fps, 30k tbn (default)
    Metadata:
      handler_name    : VideoHandler
      vendor_id       : FFMP
      encoder         : Lavc58.116.100 libx264
    Side data:
      cpb: bitrate max/min/avg: 0/0/0 buffer size: 0 vbv_delay: N/A
frame=    1 fps=0.0 q=0.0 size=       0kB time=00:00:00.00 bitrate=N/A speed=   0x    
frame=  140 fps=0.0 q=41.0 size=       0kB time=00:00:02.86 bitrate=   0.1kbits/s speed=5.72x    
frame=  273 fps=272 q=41.0 size=       0kB time=00:00:07.30 bitrate=   0.1kbits/s speed=7.28x    
frame=  423 fps=281 q=41.0 size=     256kB time=00:00:12.31 bitrate= 170.4kbits/s speed=8.17x    
frame=  571 fps=284 q=41.0 size=     512kB time=00:00:17.25 bitrate= 243.2kbits/s speed=8.58x    
frame=  715 fps=284 q=41.0 size=     768kB time=00:00:22.05 bitrate= 285.3kbits/s speed=8.77x    
frame=  853 fps=283 q=41.0 size=     768kB time=00:00:26.66 bitrate= 236.0kbits/s speed=8.84x    
frame=  986 fps=280 q=41.0 size=    1024kB time=00:00:31.09 bitrate= 269.8kbits/s speed=8.84x    
frame= 1117 fps=278 q=41.0 size=    1280kB time=00:00:35.46 bitrate= 295.6kbits/s speed=8.82x    
frame= 1263 fps=279 q=41.0 size=    1536kB time=00:00:40.34 bitrate= 311.9kbits/s speed=8.93x    
frame= 1435 fps=286 q=41.0 size=    1536kB time=00:00:46.07 bitrate= 273.1kbits/s speed=9.18x    
frame= 1584 fps=287 q=41.0 size=    1536kB time=00:00:51.05 bitrate= 246.5kbits/s speed=9.25x    
frame= 1734 fps=288 q=41.0 size=    1536kB time=00:00:56.05 bitrate= 224.5kbits/s speed= 9.3x    
frame= 1880 fps=288 q=41.0 size=    1792kB time=00:01:00.92 bitrate= 240.9kbits/s speed=9.34x    
frame= 2013 fps=286 q=41.0 size=    1792kB time=00:01:05.36 bitrate= 224.6kbits/s speed= 9.3x    
frame= 2178 fps=289 q=41.0 size=    1792kB time=00:01:10.87 bitrate= 207.1kbits/s speed=9.41x    
frame= 2338 fps=291 q=41.0 size=    2048kB time=00:01:16.20 bitrate= 220.2kbits/s speed=9.49x    
frame= 2484 fps=291 q=41.0 size=    2048kB time=00:01:21.08 bitrate= 206.9kbits/s speed= 9.5x    
frame= 2646 fps=293 q=41.0 size=    2048kB time=00:01:26.48 bitrate= 194.0kbits/s speed=9.57x    
frame= 2814 fps=295 q=38.0 size=    2304kB time=00:01:32.09 bitrate= 205.0kbits/s speed=9.65x    
frame= 2981 fps=297 q=41.0 size=    2304kB time=00:01:37.66 bitrate= 193.3kbits/s speed=9.72x    
frame= 2998 fps=296 q=-1.0 Lsize=    2533kB time=00:01:39.93 bitrate= 207.7kbits/s speed=9.86x    
video:2498kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 1.416280%
[libx264 @ 000001a481da7080] frame I:17    Avg QP:28.16  size:  6543
[libx264 @ 000001a481da7080] frame P:849   Avg QP:35.09  size:  2215
[libx264 @ 000001a481da7080] frame B:2132  Avg QP:37.45  size:   265
[libx264 @ 000001a481da7080] consecutive B-frames:  3.6%  3.8%  2.5% 90.1%
[libx264 @ 000001a481da7080] mb I  I16..4: 34.4% 48.6% 17.1%
[libx264 @ 000001a481da7080] mb P  I16..4:  1.5%  4.4%  0.9%  P16..4: 32.5% 14.7%  9.3%  0.0%  0.0%    skip:36.8%
[libx264 @ 000001a481da7080] mb B  I16..4:  0.1%  0.1%  0.0%  B16..8: 18.5%  2.0%  0.4%  direct: 1.3%  skip:77.6%  L0:46.9% L1:42.6% BI:10.5%
[libx264 @ 000001a481da7080] 8x8 transform intra:60.5% inter:61.4%
[libx264 @ 000001a481da7080] coded y,uvDC,uvAC intra: 40.1% 47.4% 14.3% inter: 11.4% 6.1% 0.6%
[libx264 @ 000001a481da7080] i16 v,h,dc,p: 52% 15%  8% 24%
[libx264 @ 000001a481da7080] i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 19% 16% 36%  3%  5%  5%  6%  5%  4%
[libx264 @ 000001a481da7080] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 28% 21% 14%  4%  7%  7%  9%  5%  5%
[libx264 @ 000001a481da7080] i8c dc,h,v,p: 66% 11% 15%  8%
[libx264 @ 000001a481da7080] Weighted P-Frames: Y:25.8% UV:12.1%
[libx264 @ 000001a481da7080] ref P L0: 59.9% 23.7% 14.8%  1.5%
[libx264 @ 000001a481da7080] ref B L0: 69.1% 19.4% 11.5%
[libx264 @ 000001a481da7080] ref B L1: 94.4%  5.6%
[libx264 @ 000001a481da7080] kb/s:204.50

6
  • Full command and logs missing. – Gyan Jan 18 at 4:37
  • @Gyan I've added the command and logs. Hope that's helpful. Thanks! – Sal More Jan 18 at 12:31
  • Use the segment muxer instead. At 29.97 fps, 100 seconds doesn't contain a whole number of frames. – Gyan Jan 18 at 17:22
  • @Gyan Thanks. Are you saying that at 29.97 fps 100 seconds does not contain whole frames because 30000/1001 = 2.9997003? if so what's the logic? does ffmpeg round it to the next frame? and if so can I rely on 99.999 to be consistent with producing 2997 frames for 100 seconds of 29.97 fps? – Sal More Jan 18 at 19:38
  • I was not familiar with segment muxer but giving it a glance seems like it will over-complicate my process as my process entails distributing the processing of each segment to another machine or machine process which enables reduced transcoding time via running them in parallel and since the segment muxer doesn't seem to support outputing a single segment and will need to process them all, this would mean that I first need to split the source file into smaller files via stream copying and then transcode each segment individually. I prefer to avoid the management of this extra complexity. – Sal More Jan 18 at 19:42
0

It seems that there are at least 2 ways to achieve this:

  1. As Gyan mentioned in the comments, by using the segment muxer which is designed for segmenting videos. For my use case his method was not practical.

  2. Using cuts that are multiplications of 100 seconds (100, 200, 1000, etc.) which will ensure that each cut ends at precisely the end of a frame (2997 * n) and hence at precisely the desired time (100 * n).

For method 2, I'm not sure why but in some scenarios even when the source video appeared to have a constant frame rate of 29.97 fps the cuts would not be accurate (off by 1-2 frames). To fix this I had to ensure the source was transcoded with -r 29.97 -vsync cfr which then resulted in accurate cuts.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.