Home > front end >  Is using timestamp in FFmpeg output a valid way to check video integrity
Is using timestamp in FFmpeg output a valid way to check video integrity

Time:01-02

I am using the timestamps that FFmpeg outputs to get information about the video integrity. So far I have tested this on about 50 videos and only had one "Unusual time skip" false positive.

Is this method of checking a valid way to do this, could there be legitimate reasons why the time skip would significantly increase and is there a more accurate way to determine an invalid time skip than $dif*2?

ffmpegIntegrityCheck() {
    local frame=0
    local prevFrame=0
    local duration=0
    local timestamp=0
    local seconds=0
    local prevSeconds=0
    local dif=0
    local line=""

    ffmpeg -v debug -progress - -nostats -i "$1" -f null - 2>&1 \
    | while read -r line; do
        # Get the video duration
        if [[ "$duration" = 0 && "$line" =~ "Duration: " ]]; then
            duration=${line#* }
            duration=${duration%, start*}
            duration=${duration%.*}
            echo "Duration $duration"

        # Check if the frame number stops increasing
        elif [[ "$line" =~ "frame=" ]]; then
            frame=${line#*=}

            if [ "$frame" = "$prevFrame" ]; then
                echo "No frame change at $timestamp frame $frame"
            fi
            prevFrame="$frame"

        # Check the increase in seconds between each timestamp,
        elif [[ "$line" =~ "out_time=" ]]; then
            timestamp=${line#*=}
            timestamp=${timestamp%.*}
            seconds=$(echo "$timestamp" \
                    | awk -F: '{ print ($1 * 3600)   ($2 * 60)   $3 }')

            if [ "$dif" != 0 ] && (( $seconds-$prevSeconds > $dif*2 )); then
                echo "Unusual time skip at $timestamp"
            else
                dif=$(($seconds-$prevSeconds))
            fi
            prevSeconds="$seconds"

        # Check if the last timestamp matches the duration 
        elif [[ "$line" = "progress=end" ]]; then
            if [ "$duration" != "$timestamp" ]; then
                duration=$(echo "$duration" \
                         | awk -F: '{ print ($1 * 3600)   ($2 * 60)   $3 }')

                if (( $seconds < $duration-1 || $seconds > $duration 1 )); then
                    echo "End time mismatch at $timestamp"
                fi
            fi
        fi
    done
}

The reason I am trying to check with more than just ffmpeg -v error is because I have found corrupted files where ffmpeg has reported no errors. I have also found files where FFmpeg reports errors but when I watch the video there are no problems so I would like to try and check whether there are any playback problems without watching it.

The logic behind looking at the timestamp jumps was that if the file all of a sudden starts processing significantly faster, I assume it is having errors and skipping some processing. This assumption does seem to match my results with files where ffmpeg -v error is reporting errors but it does produce some false positives

The log from a file producing errors in FFmpeg:

Duration 01:36:32
No frame change at 00:48:29 frame 69673
Unusual time skip at 00:49:42
No frame change at 00:49:42 frame 69673
Unusual time skip at 00:50:58
No frame change at 00:50:58 frame 69673
Unusual time skip at 00:51:44
No frame change at 00:51:44 frame 69673
Unusual time skip at 00:53:09
No frame change at 00:53:09 frame 69673
Unusual time skip at 00:54:04
No frame change at 00:54:04 frame 69673
Unusual time skip at 00:55:25
No frame change at 00:55:25 frame 69673
Unusual time skip at 00:56:32
No frame change at 00:56:32 frame 69673
Unusual time skip at 00:57:30
No frame change at 00:57:30 frame 69673
Unusual time skip at 00:58:08
No frame change at 00:58:08 frame 69673
Unusual time skip at 00:59:37
No frame change at 00:59:37 frame 69673
No frame change at 01:00:02 frame 69673
Unusual time skip at 01:01:19
No frame change at 01:01:19 frame 69673
Unusual time skip at 01:02:33
No frame change at 01:02:33 frame 69673
Unusual time skip at 01:03:39
No frame change at 01:03:39 frame 69673
No frame change at 01:03:39 frame 69673
No frame change at 01:06:02 frame 69673
No frame change at 01:06:25 frame 69673
Unusual time skip at 01:08:18
No frame change at 01:08:18 frame 69673
Unusual time skip at 01:09:19
No frame change at 01:09:19 frame 69673
Unusual time skip at 01:10:19
No frame change at 01:10:19 frame 69673
Unusual time skip at 01:11:26
No frame change at 01:11:26 frame 69673
Unusual time skip at 01:12:39
No frame change at 01:12:39 frame 69673
Unusual time skip at 01:13:53
No frame change at 01:13:53 frame 69673
Unusual time skip at 01:14:55
No frame change at 01:14:55 frame 69673
No frame change at 01:14:59 frame 69673
Unusual time skip at 01:17:04
No frame change at 01:17:04 frame 69673
No frame change at 01:17:04 frame 69673
No frame change at 01:19:01 frame 69673
No frame change at 01:19:25 frame 69673
Unusual time skip at 01:21:07
No frame change at 01:21:07 frame 69673
No frame change at 01:21:40 frame 69673
Unusual time skip at 01:23:34
No frame change at 01:23:34 frame 69673
No frame change at 01:24:18 frame 69673
No frame change at 01:25:34 frame 69673
No frame change at 01:26:41 frame 69673
No frame change at 01:27:48 frame 69673
No frame change at 01:28:06 frame 69673
Unusual time skip at 01:29:01
No frame change at 01:29:01 frame 69673
Unusual time skip at 01:30:38
No frame change at 01:30:38 frame 69673
No frame change at 01:30:38 frame 69673
No frame change at 01:33:15 frame 69673
No frame change at 01:33:51 frame 69673
Unusual time skip at 01:35:24
No frame change at 01:35:24 frame 69673
End time mismatch at 01:36:16

CodePudding user response:

Based on my results so far I can say that checking "End time mismatch" is useful but checking "Unusual time skip" so far, isn't telling me anything that ffmpeg -v error was missing, I may be able to use it to quantify error though.

I have found several files with "End time mismatch" where the file stops playing too early but ffmpeg error/debug output doesn't report any problems.

Duration 01:53:53
progress=end
End time mismatch at 00:10:29

[AVIOContext @ 0x5587868cfcc0] Statistics: 0 seeks, 21 writeouts
video:7894kB audio:108396kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
Input file #0 (vid.avi):
Input stream #0:0 (video): 15082 packets read (74354639 bytes); 15082 frames decoded;
Input stream #0:1 (audio): 24088 packets read (8809327 bytes); 24088 frames decoded (27749376 samples);
Total: 39170 packets (83163966 bytes) demuxed
Output file #0 (pipe:):
Output stream #0:0 (video): 15082 frames encoded; 15082 packets muxed (8083952 bytes);
Output stream #0:1 (audio): 24088 frames encoded (27749376 samples); 24088 packets muxed (110997504 bytes);
Total: 39170 packets (119081456 bytes) muxed
39170 frames successfully decoded, 0 decoding errors
[AVIOContext @ 0x5587868d8c40] Statistics: 713804051 bytes read, 18836 seeks

ffprobe -show_streams -show_format FILE results

[STREAM]
index=0
codec_name=mpeg4
codec_long_name=MPEG-4 part 2
profile=Advanced Simple Profile
codec_type=video
codec_time_base=417083/10000000
codec_tag_string=DX50
codec_tag=0x30355844
width=608
height=320
coded_width=608
coded_height=320
has_b_frames=1
sample_aspect_ratio=1:1
display_aspect_ratio=19:10
pix_fmt=yuv420p
level=5
color_range=unknown
color_space=unknown
color_transfer=unknown
color_primaries=unknown
chroma_location=left
field_order=unknown
timecode=N/A
refs=1
quarter_sample=false
divx_packed=false
id=N/A
r_frame_rate=10000000/417083
avg_frame_rate=10000000/417083
time_base=417083/10000000
start_pts=0
start_time=0.000000
duration_ts=163848
duration=6833.821538
bit_rate=N/A
max_bit_rate=N/A
bits_per_raw_sample=N/A
nb_frames=163848
nb_read_frames=N/A
nb_read_packets=N/A
DISPOSITION:default=0
DISPOSITION:dub=0
DISPOSITION:original=0
DISPOSITION:comment=0
DISPOSITION:lyrics=0
DISPOSITION:karaoke=0
DISPOSITION:forced=0
DISPOSITION:hearing_impaired=0
DISPOSITION:visual_impaired=0
DISPOSITION:clean_effects=0
DISPOSITION:attached_pic=0
DISPOSITION:timed_thumbnails=0
[/STREAM]
[STREAM]
index=1
codec_name=mp3
codec_long_name=MP3 (MPEG audio layer 3)
profile=unknown
codec_type=audio
codec_time_base=1/44100
codec_tag_string=U[0][0][0]
codec_tag=0x0055
sample_fmt=fltp
sample_rate=44100
channels=2
channel_layout=stereo
bits_per_sample=0
id=N/A
r_frame_rate=0/0
avg_frame_rate=0/0
time_base=1/14000
start_pts=0
start_time=0.000000
duration_ts=N/A
duration=N/A
bit_rate=112000
max_bit_rate=N/A
bits_per_raw_sample=N/A
nb_frames=95673053
nb_read_frames=N/A
nb_read_packets=N/A
DISPOSITION:default=0
DISPOSITION:dub=0
DISPOSITION:original=0
DISPOSITION:comment=0
DISPOSITION:lyrics=0
DISPOSITION:karaoke=0
DISPOSITION:forced=0
DISPOSITION:hearing_impaired=0
DISPOSITION:visual_impaired=0
DISPOSITION:clean_effects=0
DISPOSITION:attached_pic=0
DISPOSITION:timed_thumbnails=0
[/STREAM]
[FORMAT]
filename=vid.avi
nb_streams=2
nb_programs=0
format_name=avi
format_long_name=AVI (Audio Video Interleaved)
start_time=0.000000
duration=6833.821538
size=732241860
bit_rate=857197
probe_score=100
TAG:encoder=AVI-Mux GUI 1.17.8.3, Feb 16 201019:42:50
TAG:JUNK=
[/FORMAT]

CodePudding user response:

This looks to be an instance of an XY question.

Checking timestamp intervals will not tell you whether the file is corrupt i.e.

  1. is the container metadata missing (fully or partially) or malformed ?
  2. is any of the media data missing or malformed ?

At most, it will identify if a portion of the file will lead to subjective 'freezes' due to prolonged video frames or silences due to a large inter-packet intervals in the audio.

Running ffmpeg -i INPUT and checking the exit code is sufficient to identify if the input header has any fatal errors.

To check media data, decoding the file is sufficient.

ffmpeg -v 48 -i INPUT -f null -

After completion, check the logs for Packet corrupt to identify errors at the packet encapsulation level. And at the end of the log, look for a line of this form: X frames successfully decoded, Y decoding errors for corrupt frames.

  • Related