Opened 2 years ago

Closed 19 months ago

#9028 closed defect (fixed)

mp4 durations include edit list delay

Reported by: j0sh Owned by:
Priority: normal Component: avformat
Version: git-master Keywords: mov edts
Cc: Blocked By:
Blocking: Reproduced by developer: no
Analyzed by developer: no

Description

When clipping and transmuxing to mp4 (eg, -ss <seek> -i <in> ), the duration of the resulting clip includes the edit list delay (start time offset from the beginning of the clip). This does not match the actual track duration.

Generated the source (also attached):

ffmpeg -f lavfi -i testsrc=duration=20:rate=30 -an -c:v libx264 -g 60 test-timecode.mp4

Now try to trim it. This should attempt to cut in the middle of the second GOP, with one extra second of "delay".

ffmpeg -ss 3 -i test-timecode.mp4 -t 5 -c copy out.mp4

Note that the reported time is mostly correct: time=00:00:04.96

`
ffmpeg -ss 3 -i test-timecode.mp4 -t 5 -c copy out.mp4
ffmpeg version 4.3.1 Copyright (c) 2000-2020 the FFmpeg developers

built with clang version 7.1.0 (tags/RELEASE_710/final)
configuration: --disable-static --prefix=/nix/store/dwplnqraah2ygx9kwl1yklddvwj5x5rw-ffmpeg-full-4.3.1 --target_os=darwin --arch=x86_64 --enable-gpl --enable-version3 --disable-nonfree --enable-shared --enable-pic --cc=clang --disable-small --enable-runtime-cpudetect --disable-lto --enable-gray --enable-swscale-alpha --enable-hardcoded-tables --enable-safe-bitstream-reader --enable-pthreads --disable-w32threads --disable-os2threads --enable-network --enable-pixelutils --enable-ffmpeg --enable-ffplay --enable-ffprobe --enable-avcodec --enable-avdevice --enable-avfilter --enable-avformat --enable-avresample --enable-avutil --enable-postproc --enable-swresample --enable-swscale --enable-doc --disable-htmlpages --enable-manpages --disable-podpages --disable-txtpages --enable-bzlib --enable-libcelt --enable-libdav1d --disable-libfdk-aac --disable-libflite --enable-fontconfig --enable-libfreetype --disable-frei0r --enable-libfribidi --disable-libgme --enable-gnutls --enable-libgsm --enable-ladspa --enable-libmp3lame --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --disable-libdc1394 --enable-iconv --disable-libjack --disable-libmfx --disable-libmodplug --enable-libmysofa --enable-libopus --enable-librsvg --enable-libsrt --enable-libssh --enable-libtheora --disable-libv4l2 --disable-vaapi --enable-vdpau --enable-libvorbis --enable-libvmaf --enable-libvpx --enable-libwebp --enable-xlib --enable-libxcb --enable-libxcb-shm --enable-libxcb-xfixes --enable-libxcb-shape --enable-lzma --disable-nvenc --disable-openal --enable-libopencore-amrnb --disable-opengl --enable-libopenjpeg --disable-openssl --disable-libpulse --enable-librtmp --enable-sdl2 --enable-libsoxr --enable-libspeex --disable-libvidstab --enable-libvo-amrwbenc --enable-libwavpack --enable-libx264 --disable-libx265 --disable-libxavs --enable-libxvid --enable-libzmq --enable-zlib --disable-debug --enable-optimizations --disable-extra-warnings --disable-stripping
libavutil 56. 51.100 / 56. 51.100
libavcodec 58. 91.100 / 58. 91.100
libavformat 58. 45.100 / 58. 45.100
libavdevice 58. 10.100 / 58. 10.100
libavfilter 7. 85.100 / 7. 85.100
libavresample 4. 0. 0 / 4. 0. 0
libswscale 5. 7.100 / 5. 7.100
libswresample 3. 7.100 / 3. 7.100
libpostproc 55. 7.100 / 55. 7.100

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'test-timecode.mp4':

Metadata:

major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf58.45.100

Duration: 00:00:20.00, start: 0.000000, bitrate: 48 kb/s

Stream #0:0(und): Video: h264 (High 4:4:4 Predictive) (avc1 / 0x31637661), yuv444p, 320x240 [SAR 1:1 DAR 4:3], 44 kb/s, 30 fps, 30 tbr, 15360 tbn, 60 tbc (default)
Metadata:

handler_name : VideoHandler

File 'out.mp4' already exists. Overwrite? [y/N] y
Output #0, mp4, to 'out.mp4':

Metadata:

major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf58.45.100
Stream #0:0(und): Video: h264 (High 4:4:4 Predictive) (avc1 / 0x31637661), yuv444p, 320x240 [SAR 1:1 DAR 4:3], q=2-31, 44 kb/s, 30 fps, 30 tbr, 15360 tbn, 15360 tbc (default)
Metadata:

handler_name : VideoHandler

Stream mapping:

Stream #0:0 -> #0:0 (copy)

Press [q] to stop, ? for help
frame= 182 fps=0.0 q=-1.0 Lsize= 40kB time=00:00:04.96 bitrate= 65.5kbits/s speed=4.94e+03x
video:37kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 8.035690%
`

Results from ffprobe. The top-level duration is incorrect (because it includes the extra 1s of delay at the beginning), but the stream duration is correct.

`
$ ffprobe -show_streams -show_format out.mp4 2>&1 | grep duration=
duration=5.166992 # stream duration - correct
duration=6.167000 # top level duration - incorrect
`

Attachments (4)

test-timecode.mp4 (117.7 KB ) - added by j0sh 2 years ago.
test-timecode.2.mp4 (117.7 KB ) - added by j0sh 2 years ago.
gop-600.mp4 (614.6 KB ) - added by j0sh 2 years ago.
40s timecode with 20-second GOP (mp4)
gop-600.ts (907.5 KB ) - added by j0sh 2 years ago.
40s timecode with 20-second GOP (mpegts)

Download all attachments as: .zip

Change History (9)

by j0sh, 2 years ago

Attachment: test-timecode.mp4 added

by j0sh, 2 years ago

Attachment: test-timecode.2.mp4 added

by j0sh, 2 years ago

Attachment: gop-600.mp4 added

40s timecode with 20-second GOP (mp4)

by j0sh, 2 years ago

Attachment: gop-600.ts added

40s timecode with 20-second GOP (mpegts)

comment:1 by j0sh, 2 years ago

Additional samples for testing this patch - https://patchwork.ffmpeg.org/project/ffmpeg/patch/20201219231319.56995-1-martin@martin.st/

These are 40 second clips with a 600-frame (20 second @ 30fps) GOP, so we're creating an edit list mid-GOP:

Sample 1 (mp4)

Attached as gop-600.mp4 : Works nicely. Command to generate the sample:

ffmpeg -f lavfi -i testsrc=duration=40:size=640x480:rate=30 -an -c:v libx264 -g 600 -movflags faststart gop-600.mp4 -y

Clip the sample via:

ffmpeg -ss 17.316666999999999 -i gop-600.mp4 -t 5 -c copy -movflags +faststart -y cut-mp4-600.mp4

Inspect the result: ffprobe cut-mp4-600.mp4 should yield something like: Duration: 00:00:05.12, start: 0.000000, bitrate: 573 kb/s. All good.

Sample 2 (mpegts) - this does not seem to be quite correct.

As gop-600.ts. Command to generate the sample:

ffmpeg -f lavfi -i testsrc=duration=40:size=640x480:rate=30 -an -c:v libx264 -g 600 gop-600.ts -y

Cut with: ffmpeg -ss 17.316666999999999 -i gop-600.ts -t 5 -c copy -movflags +faststart -y cut-ts-600.mp4

The output duration seems okay, but playback starts at the beginning of the *next* GOP at the 20-second mark, while the clip should start at 17 seconds. The difference from the expected value seems to be exactly the probed start_time value:

ffprobe cut-ts-600.mp4 yields Duration: 00:00:05.12, start: 2.683000, bitrate: 79 kb/s

Specifically - since playback begins at 20s, and the probed start time is 2.683, so 20-2.683 = 17.317 which should have been the position of the initial cut.

comment:2 by Carl Eugen Hoyos, 2 years ago

Component: undeterminedavformat
Keywords: mov edts added
Version: unspecifiedgit-master

comment:4 by Balling, 20 months ago

Status: newopen

Okay, so gop-600.mp4 is indeed fixed, but cut-ts-600.mp4 is VFR.

ffmpeg -i cut-ts-600.mp4 -vf vfrdet -an -f null -
[Parsed_vfrdet_0 @ 0000023d9ae4ed40] VFR:0.014085 (1/70) min: 3000 max: 6000 avg: 6000

And BTW, cut-mp4-600.mp4 is also VFR...

in reply to:  1 comment:5 by j0sh, 19 months ago

Resolution: fixed
Status: openclosed

The issue with cutting a mpegts source as described in [1] has more to do with mpegts itself being non-seekable, than anything to do with mp4.

I can confirm that c2424b1f35a1c6c06f1f9fe5f77a7157ed84e1cd fixes the original report.

[1] https://trac.ffmpeg.org/ticket/9028?replyto=1#comment:1

Note: See TracTickets for help on using tickets.