Search code examples
ffmpegvideo-streamingvideo-processinghttp-live-streaming

ffmpeg video duration is not equal to duration after hls process


Problem

For videofile input I preprocess/encode it to libx264. Then I'm trying to cut video into 2 second chunks except last one (last one being < 2 seconds) using hls processing

ffmpeg -v error -i video.mp4 -x264-params "keyint=60:min-keyint=60:scenecut=0" 
-hls_time 2 -hls_list_size 0 -hls_segment_filename chunk%03d.ts index.m3u8

which follows this problem

then looking into index.m3u8 file reveals that sum of all chunks' durations does not add up to original video duration:

% ffprobe -loglevel quiet -print_format flat -show_entries format=duration index.m3u8     

format.duration="204.880000"

% ffprobe -loglevel quiet -print_format flat -show_entries format=duration video.mp4 

format.duration="204.892813"

Moreover duration of a chunk in index.m3u8 is not the same as in chunk file.

% ffprobe -loglevel quiet -print_format flat -show_entries format=duration chunk000.ts

format.duration="2.023222"

% cat index.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:2
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:2.000000,
chunk000.ts
#EXTINF:2.000000,
chunk001.ts
#EXTINF:2.000000,
chunk002.ts
...

Misc

Used these videos: Me at the zoo and I finally found a useful monorail.

OS: macos Monterey 12.3.1 (21E258)

ffmpeg version 5.1.2 Copyright (c) 2000-2022 the FFmpeg developers
built with Apple clang version 14.0.0 (clang-1400.0.29.102)
configuration: --prefix=/usr/local/Cellar/ffmpeg/5.1.2 --enable-shared --enable-pthreads --enable-version3 --cc=clang --host-cflags= --host-ldflags= --enable-ffplay --enable-gnutls --enable-gpl --enable-libaom --enable-libbluray --enable-libdav1d --enable-libmp3lame --enable-libopus --enable-librav1e --enable-librist --enable-librubberband --enable-libsnappy --enable-libsrt --enable-libtesseract --enable-libtheora --enable-libvidstab --enable-libvmaf --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libxvid --enable-lzma --enable-libfontconfig --enable-libfreetype --enable-frei0r --enable-libass --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libspeex --enable-libsoxr --enable-libzmq --enable-libzimg --disable-libjack --disable-indev=jack --enable-videotoolbox
libavutil      57. 28.100 / 57. 28.100
libavcodec     59. 37.100 / 59. 37.100
libavformat    59. 27.100 / 59. 27.100
libavdevice    59.  7.100 / 59.  7.100
libavfilter     8. 44.100 /  8. 44.100
libswscale      6.  7.100 /  6.  7.100
libswresample   4.  7.100 /  4.  7.100
libpostproc    56.  6.100 / 56.  6.100

What I tried

  • Preprocess/transcode video before proceeding with hls
  • Force keyframes before proceeding with hls
  • Use 1, 3, 4 seconds chunks
  • Use different GOP sizes
  • -hls_flags split_by_time

but it leads to same result or very unequal chunks

Questions

  1. Is it ok or I'm missing something?
  2. If not, what parameters/options should I use to force chunks to be precisely 2 seconds?

Solution

  • Ok, I might solve this:

    Turns out, that duration in ffprobe shows longest from streams (audio, video) and duration of sum of chunks equals to videstream duration

    Difference in duration from ffprobe and m3u8 file are marginal and considered as normal: video stackexchange source