Reputation: 137
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
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