archie
archie

Reputation: 137

Can VLC's method for estimating the duration of a video be reproduced by the means of ffmpeg?

This may seem to duplicate previous questions but it does not, as far as I can tell.

I have a bash script for indexing images and videos to a thumbnails database. A user of my script complained that some videos of hers are skipped over with an error message "corrupted metadata" even though VLC can play them smoothly. These are about 10 videos out of some 15 thousand, but I'd like to solve the problem.

I will focus on a single video from the bunch. File name: "Paper_and_discussion_M492.mkv", actual duration 02:03:47 (hh:mm:ss). The duration and bitrate fields in the video metadata are missing.

ffmpeg  -hide_banner -i "Paper_and_discussion_M492.mkv" 2> ffmpeg_data.txt

gives the following output:

  Input #0, matroska,webm, from 'Paper_and_discussion_M492.mkv':
  Metadata:
    COMPATIBLE_BRANDS: isomiso2avc1mp41
    MAJOR_BRAND     : isom
    MINOR_VERSION   : 512
    ENCODER         : Lavf58.76.100
  Duration: N/A, start: 0.000000, bitrate: N/A
  Stream #0:0: Video: hevc (Main), yuv420p(tv, progressive), 854x480 [SAR 1280:1281 DAR 16:9], 24 fps, 24 tbr, 1k tbn, 24 tbc (default)
    Metadata:
      HANDLER_NAME    : VideoHandler
      VENDOR_ID       : [0][0][0][0]
      ENCODER         : Lavc58.134.100 libx265
  Stream #0:1: Audio: vorbis, 44100 Hz, stereo, fltp (default)
    Metadata:
      HANDLER_NAME    : SoundHandler
      VENDOR_ID       : [0][0][0][0]
      ENCODER         : Lavc58.134.100 libvorbis
At least one output file must be specified

Therefore, as expected,

ffprobe -i <file> -show_entries format=duration -v quiet -of csv="p=0"

returns "N/A".

Decoding the whole file does work:

ffprobe -show_entries stream=r_frame_rate,nb_read_frames -select_streams v -count_frames -of compact=p=0:nk=1 -v 0 "Paper_and_discussion_M492.mkv"

but it obviously takes a lot of time, especially for a > 2 hours video.

The "faster answer" proposed by LSerni in https://superuser.com/questions/1179000/ffmpeg-get-duration-of-video-file-without-meta-data should give an estimate of duration based on bitrate; but bitrate is also "N/A" in the incriminated file(s). Their command-line solution based on ffmpeg ends with an error "division by zero".

However, if I open the file with VLC, it plays ok and VLC immediately shows the duration of the file as 02:03:47. I have checked that duration is precise. Search and jump are also very fast: if I skip 1 hr, playback promptly resumes at the right time.

So, a doubt is gnawing at me: How does VLC succeed where I consistently fail? It must have a way for recovering data that I might also be able to use to produce a correct estimate of duration.

My question is: is it possible to reproduce VLC's method (or equivalent) by means of ffmpeg?

Upvotes: 0

Views: 47

Answers (1)

Gyan
Gyan

Reputation: 93319

You just need the timestamp of the final frame, with something like

ffprobe -of compact=p=0:nk=1 -show_entries packet=pts_time -read_intervals 9999% -v 0 -i src.webm | tail -1

This is much quicker than decoding.

Upvotes: 1

Related Questions