3

I am trying to determine the duration of an MP4 video using ffmpeg, which is possible of course, except that when the data is streamed in via stdin (a requirement in my case) the duration is reported to be smaller than it actually is. I have the same problem with ffprobe.

The video's actual length is ~13 seconds.

Examples below of the output I receive using ffprobe.

Reading file from disk (correct duration):

$ ffprobe video.mp4
...
Duration: 00:00:13.05, start: 0.000000, bitrate: 736 kb/s
...

Streaming in the file (incorrect duration):

$ cat video.mp4 | ffprobe -i -
...
Duration: 00:00:08.40, start: 0.080000, bitrate: N/A
...

How can I get ffprobe to report the correct duration whilst also streaming in the file via stdin?

sdgluck
  • 24,894
  • 8
  • 75
  • 90

2 Answers2

4

You can use ffprobe's -show_packets option, which will "Show information about each packet contained in the input multimedia stream". (Read about it in the ffprobe docs.)

With this option ffprobe will output an entry for each packet in the stream like so:

dts_time=13.008000

So we can grep the output for dts_time:

$ cat video.mp4 | ffprobe -i - -show_packets | grep dts_time
...
dts_time=13.008000
dts_time=13.029333

The last line of the output will contain the timestamp of the last packet, which can be taken as the approximate duration of the video (see comments for why this is approximate only):

$ cat video.mp4 \
    | ffprobe -i - -show_packets -v quiet \
    | grep dts_time \
    | tail -n 1 \
    | awk -F"=" '{print $2}'
13.029333
sdgluck
  • 24,894
  • 8
  • 75
  • 90
  • 3
    This gives a result that's off by the duration of the last packet. – Aleksandr Dubinsky Mar 09 '20 at 13:39
  • 1
    @AleksandrDubinsky - yes, you should add the last packet's `dts_time` and `duration_time` together to get the total duration. This is a floating point value, so may not be exactly what `format=duration` would have shown, but shouldn't be off by more than a millisecond. – Guss May 11 '21 at 15:59
0

Your input MP4s look to be fragmented, in which case, ffmpeg will stop probing after the first fragment moof box, and report its duration. This is not an issue with regular MP4s.

You can run cat fragmented.mp4 | ffmpeg -i - -c copy -f null - 2>&1 | grep -oP "(?<=time=)[\d:\.]+" for such files.

Gyan
  • 85,394
  • 9
  • 169
  • 201
  • the "time=" string does not give an entirely accurate duration. Looks like it's off by one packet. But I'm not sure that it won't be off by an arbitrary amount of time. – Aleksandr Dubinsky Mar 09 '20 at 13:46
  • 1
    Yes, `time=`reading is for the timestamp of the last packet. Its duration is not accounted for in the status – Gyan Mar 09 '20 at 14:13