193

This title could be somewhat misleading, so let me explain ...

I'm downloading a video file ... mpeg, avi - being one of the popular formats. Now, if I am downloading it, and the download breaks in the middle of the uhm ... download, then, for example, Windows Media Player will give out some error and refuse to play it (although the file is, let's say, 98% complete). But, players like KMPlayer, or MediaPlayer Classic will play it up until that point (as the matter of fact, they can play it while it is being downloaded as well).

So, I'm interested, ... without using any means of download (download managers and alike) to secure the file is completely downloaded, how can one verify whether the video file is downloaded whole, and that it is complete ?

3

14 Answers 14

228

You can use a feature in ffmpeg video converter: if you will specify it to recode video to nothing it will just read input file and report any errors that will appear. This is a very fast process because video frames are just being read, checked and silently dropped.

Example command line: (for Linux)

ffmpeg -v error -i file.avi -f null - 2>error.log

-v error means a certain level of verbosity (to show some errors that are normally hidden because they don't affect playability a much).

You will get a full error log with some generic information about file ffmpeg will output, so this will probably require your attention, through filters can be written to perform batch check of similar files.

FFmpeg is also available for Windows here. The command line will be almost identical with an exception of stderr redirect:

ffmpeg.exe -v error -i file.avi -f null - >error.log 2>&1
14
  • 19
    Another option is ffprobe that comes in package with ffmpeg. It doesn't do any conversion but simply reads metadata info from file. Therefore it will detect errors in metadata but won't find any problems within file itself. Personally using ffprobe to make fast verification of uploaded before processing further
    – mente
    Oct 1, 2013 at 7:41
  • 2
    Example error from file with the end chopped off: [mov,mp4,m4a,3gp,3g2,mj2 @ 0x161a180] moov atom not found video-head.mp4: Invalid data found when processing input Sep 7, 2015 at 23:09
  • 5
    If, as the OP states, "download breaks in the middle of the uhm ... download", it's very likely that all streams will be disrupted, so you can detect this error by restricting decoding to just one audio track (using -map), which will significantly speed up operation: ffmpeg -v error -i in.mkv -map 0:1 -f null … If there is an error, it'll log the byte position, which you can use to truncate the file (a megabyte or two earlier to be safe) and then resume downloading.
    – Lumi
    Oct 25, 2015 at 10:49
  • 17
    It took maybe 4 1/2 minutes for me to test a 1GB 1hour long .mkv file, on an oldish hex core processor. All cores were maxed during the test. I hex edited a copy of the file and added some blocks of 00 to simulate damage. The error log reported the errors correctly. Files without errors returned an empty error.log Sep 14, 2017 at 0:08
  • 8
    "Same speed as if it would been converting." I can confirm this. However, disabling transcoding by adding -c copy solves the problem: ffmpeg -v error -i file.avi -c copy -f null -
    – Daniel
    Jun 1, 2022 at 7:55
17

I liked idea of using ffmpeg -f null above, but I'd actually like to automate process of using that output. In particular, common scenario I have with my music video collection is that I have few clips which have same resolution, and I'd like to diff verification logs for those files to remove ones broken the most.

Unfortunately, ffmpeg so far doesn't have a way to disable its interactive mode, which outputs noise for this case of usage. I ended up hacking simple wrapper script to do filtering:

#!/usr/bin/env python
import sys
import os
import re

t = os.popen('ffmpeg -v 5 -i "%s" -f null - 2>&1' % sys.argv[1]).read()
t = re.sub(r"frame=.+?\r", "", t)
t = re.sub(r"\[(.+?) @ 0x.+?\]", "[\\1]", t)
print t

Example output:

[mpeg1video]ac-tex damaged at 21 17
[mpeg1video]Warning MVs not available
[mpeg1video]concealing 22 DC, 22 AC, 22 MV errors
[mpeg1video]Warning MVs not available
[mpeg1video]concealing 22 DC, 22 AC, 22 MV errors
[mpeg1video]ac-tex damaged at 13 9
3
  • 2
    Traceback (most recent call last): File "F:\filecheck.py", line 6, in <module> t = os.popen('ffmpeg -v 5 -i "%s" -f null - 2>&1' % sys.argv[1]).read() IndexError: list index out of range Jul 16, 2017 at 14:54
  • list index out of range means no file name was supplied at the command line. So the proper usage would be e.g. script.py filename.mp4 or perhaps python script.py filename.mp4. Jan 17, 2020 at 20:10
  • ffmpeg can be told to output only error information with -v error. Another useful option is -xerror which tells it to stop processing on frame errors with a non-zero return code. You can just check the return code and not parse anything at all. Aug 20, 2023 at 9:55
11

For windows, You can 'batch' check integrity for videos on current folder and all subfolders with this bat file:

checkvideo.bat

@echo off

set "filtro=%1"
if [%filtro%]==[] (
    set "filtro=*.mp4"
    )

for /R %%a in (%filtro%) do call :doWork "%%a"

    PAUSE
    exit /B

:doWork
    C:\ffmpeg\bin\ffmpeg.exe -v error -i %1 -f null - > "%~1.log" 2>&1
    

Use:

checkvideo.bat [filter]

If you don't give one filter, will get '*.mp4'.

Samples: checkvideo.bat checkvideo.bat *.avi

Setup: Download FFmpeg for Windows from here: https://ffmpeg.zeranoe.com/builds/ and unzip them Change C:\ffmpeg\bin\ in the bat file for the path where you have unzipped ffmpeg Put checkvideo.bat on a folder included in the Path or add his folder to Path environment variable

UPDATE: As of September 18,2020, the above link is no longer valid so Windows users can download FFmpeg form here or here

1
  • Juan Antonio Tubío's answer is working for me to check video integrity. But how can I read log file and detect time where video is corrupted. Log example. [h264 @ 00000173649787c0] cabac decode of qscale diff failed at 64 7 [h264 @ 00000173649787c0] error while decoding MB 64 7, bytestream 38638
    – J.Duck
    Mar 20, 2018 at 14:36
5

This one liner using ffprobe checks each input and returns either OK or ERROR, followed by the name of the file.

for i in *; do ffprobe -v error "$i" 2>/dev/null && echo "OK => '$i'" || echo "ERROR => '$i'"; done

I created a fake .mp4 file by running touch video.mp4 to simulate a corrupted video. Result:

OK => 'How To Be A Gardener 1x1 - Know Your Plot.mp4'
OK => 'How To Be A Gardener 1x2 - Understand Plants.mp4'
OK => 'How To Be A Gardener 1x3 - Planting Schemes & Themes.mp4'
OK => 'How To Be A Gardener 1x4 - Practical Planting.mp4'
OK => 'How To Be A Gardener 1x5 - Caring For Your Garden.mp4'
OK => 'How To Be A Gardener 1x6 - Problem Solving.mp4'
OK => 'How To Be A Gardener 1x7 - The Productive Garden.mp4'
OK => 'How To Be A Gardener 1x8 - The Gardening Year.mp4'
ERROR => 'video.mp4'

The actual ffprobe errors can be shown by removing the 2>/dev/null redirection:

for i in *; do ffprobe -v error "$i" && echo "OK => '$i'" || echo "ERROR => '$i'"; done
OK => 'How To Be A Gardener 1x1 - Know Your Plot.mp4'
OK => 'How To Be A Gardener 1x2 - Understand Plants.mp4'
OK => 'How To Be A Gardener 1x3 - Planting Schemes & Themes.mp4'
OK => 'How To Be A Gardener 1x4 - Practical Planting.mp4'
OK => 'How To Be A Gardener 1x5 - Caring For Your Garden.mp4'
OK => 'How To Be A Gardener 1x6 - Problem Solving.mp4'
OK => 'How To Be A Gardener 1x7 - The Productive Garden.mp4'
OK => 'How To Be A Gardener 1x8 - The Gardening Year.mp4'
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x559de0c58900] moov atom not found
video.mp4: Invalid data found when processing input
ERROR => 'video.mp4'

Adjust the for loop to check only specific extensions or files:

for i in *.mkv; do ...
for i in *S01E*.mp4; do ...
1

Although this is an old post, and I'm sure there's other ways to valid video files now. However, for a full video file check, you can use mplayer.exe.

Using the below (.bat) script will recursively check video files and save validated ones in a integritychecked.log file (to skip next time its run).

if not "%1" equ "" (
    pushd %1
) else (
    pushd "%~dp0"
)

setlocal EnableDelayedExpansion
for /F "tokens=1,2 delims=#" %%a in ('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do (
  set "DEL=%%a"
)

echo This script with validate video files in the folder/sub-folders. Please ensure mplayer.exe is accessible in PATH.
echo.
echo Either run this script from the desired (parent) directory or specify the directory when running this script. eg checkvideo.bat <full path>
echo.
pause
echo.

REM Append date and time to integritychecked.log file
for /f "tokens=1-9 delims=/:. " %%d in ("%date% %time: =0%") do echo Started: %%g%%f%%e_%%h%%i%%j>>integritychecked.log

FOR /F "delims=*" %%G in ('dir /b /s *.mkv *.mp4 *.mpg *.mpeg *.xvid *.webm *.m2v *.m4v *.3gp *.3g2 *.avi *.mov *.flv *.wmv') DO (
    REM Confirm if already checked or not from log file 
    set found=0
    for /F "usebackq tokens=*" %%s in ("integritychecked.log") do (
        if %%G equ %%s (
            set found=1
            REM echo "FOUND = %%G = %%s"
        )
    )

    if !found! equ 0 (
        echo Verifying "%%G"
        mplayer -tsprobe 10000000 -benchmark -forcedsubsonly  -mc 0 -nosound -nosub -noautosub -vo null "%%G" 2>"%%G.log"
        REM ffmpeg -v error -i "%%G" -map 0:1 -f null - 2>"%%G.log"
        FOR %%F in ("%%G.log") DO (
            if %%~zF equ 0 (
                del %%F
                call :colour 0a "Video is good"
                echo.
                echo. 
            ) else (
                call :colour 0c "Error in video file:"
                echo.
                type %%F
                call :colour 0e "This can be found in the video's .log file"
                echo.
                echo.
            )
        )
        REM Save entry to log file (as checked)
        echo %%G>>integritychecked.log
    ) else (
        echo already verified "%%G"...skipping.
    )
)
call :colour 0a "Verifying complete!" && echo.
pause
cd %~p0
exit /b

:colour
set "param=^%~2" !
set "param=!param:"=\"!"
rem Prepare a file "X" with only one dot
<nul > X set /p ".=."
findstr /p /A:%1 "." "!param!\..\X" nul
<nul set /p ".=%DEL%%DEL%%DEL%%DEL%%DEL%%DEL%%DEL%"
rem Delete "X" file
del X
exit /b
3
  • When using the mplayer replacement mpv under linux, the command line is mpv --quiet --no-sub --no-sub-auto --no-audio --untimed --vo=null >error.log 2>&1 (errors are not reported on standard error but on standard output).
    – wolfmanx
    Dec 31, 2021 at 5:32
  • 1
    True - i use this as well: mpv --vo=null --no-video --untimed --framedrop=no --vd-lavc-bitexact --audio-display=no --ao=null --ao-null-untimed --autoload-files=no "${fname}" >"${fname}.log" (the log output will capture issues such as 'Error parsing option.....', 'Corrupt file detected...', '...frame sync error', 'Failed to recognize file format.', etc. which I also use to identify failed video files).
    – jkeys
    Jan 5, 2022 at 4:25
  • Recently I found a couple of videos, which were cut short. These are not detected by the standard check, since there is nothing wrong with the stream besides being shorter than intended. So I check for those by producing a single frame image 5 seconds before the containers end: ffmpeg -hide_banner -loglevel error -nostdin -y -nostats -fflags +genpts -sseof -5 -i "file:${_video}" -update 1 -frames:v 1 "file:${_video}.jpg" >>"${_video}.log" 2>&1; if test ! -s "${_video}.jpg"; then _result='BAD'; else _result='GOOD'; test ! -s "${_video}.log" || _result='WARN'; fi
    – wolfmanx
    Oct 7, 2023 at 21:54
1

I really liked the ffmpeg version provided by How can I check the integrity of a video file (avi, mpeg, mp4...)? but I wanted a version that would only tell me if ffmpeg failed to play the video in a way that stopped it (I can deal with frame drops), and I wanted it to be linux based. I came to the solution below. I also wanted more information about what was happening while it was scanning, so I opted for scanned/total/errored outputting whenever a file starts scanning.

#!/bin/bash
# Name: mediaCheck
# Purpose: Confirm all media in a path can be played back using ffmpeg
# Requires:
# * ffmpeg in $PATH
# * date in $PATH
# * find in $PATH

function checkReqs {
 # checks requirements for the script
 requires="ffmpeg date find"
 re=0
 for i in $requires; do
  if ! which $i > /dev/null; then
   ((re++))
   echo "$i is required in path for this script"
   fi
  done
 if [ "$re" -gt 0 ]; then
  echo "Requirements not met"
  exit 1
  fi
}

function pathCheck {
 # if there isn't a path, use pwd, otherwise clean up whatever is provided.
 if [ -z "$1" ]; then
  lPath=mediaCheck.log
  cPath=$(pwd)
  else
   cPath=$(readlink -f $1)
   lPath=$1
   fi
 }

function pdate {
 # my prefered date formatting
 date +%FT%H:%M:%S
}

function checkMedia {
 # the actual ffmpeg command
 ffmpeg -v error -i $1 -f null - &> "$1.log"
}

function findItems {
 # our main loops
 # first a set of common file types
 for mtype in flv avi m4v mkv mp4; do
  c=0; e=0
  # Get a total per file type
  ttotal=$(find $1 -type f -name \*.$mtype | wc -l)
  # then the actual lookup and check
  for i in $(find $1 -type f -name \*.$mtype); do
    echo -ne "$(pdate) $c out of $ttotal $mtype files checked with $e errors.\r"
    ((c++))
    # check media, and if we fail, increment error counter.
    if ! checkMedia "$i" ; then
    ((e++))
    echo "$i failed" >> $lPath.log
    fi
   done
   echo "$(pdate) $c out of $ttotal $mtype files checked with $e errors."
   unset c e
  done
}

# set blank cpath
cPath=''

# uncomment the line below if this script isn't behaving as expected
# set -x

# Check requirements before anything else
checkReqs
# Then generate a path
pathCheck $1

# Make sure we don't stumble on names with spaces
IFS=$'\n'

echo "$(pdate) scan started."
findItems $cPath
echo "$(pdate) scan complete."
1

I have developed this python script which checks media files integrity (or tries to), please read instructions for details and limits, also feedbacks are appreciated: https://github.com/ftarlao/check-media-integrity

0

The issue with the other answer using ffmpeg to recode to null format is that it takes really a long time. Especially, if you want to check multiple files in a directory.

A quick way would be to generate thumbnails for all the videos, and see where thumbnail generation fails.

find . -iname "*.mp4" | while read -r line; do 
  line=`echo "$line" | sed -r 's/^\W+//g'`; 
  echo 'HERE IT IS ==>' "$line"; 
  if ffmpeg -i "$line" -t 2 -r 0.5 %d.jpg; 
    then echo "DONE for" "$line"; 
  else echo "FAILED for" "$line" >>error.log; 
  fi; 
done;

This method turned out to be much FASTER than other methods.

However, there is a CAVEAT. This method can yield wrong results, because sometimes thumbnail can be generated even for corrupt files. E.g. if the video file is corrupted only at the end, this method will fail.

3
  • On today's multi-processor computers, you can check multiple videos in parallel. make's -j flag will help...
    – Mikhail T.
    Jun 13, 2020 at 22:00
  • 1
    This doesn't check the integrity of the files. It just catches files that aren't media files at all, or happen to be broken at just the point from where ffmpeg decides to try to generate a thumbnail. Aug 26, 2021 at 15:21
  • as per comment in answer superuser.com/a/100290/73961 one can add the option -c copy so that audio/video stream is just copied and not re-encoded (as per man page: "omit the decoding and encoding step for the specified stream, so it does only demuxing and muxing"), cutting my (very processor-intensive) time to correctly verify a 1gb file from ~2.5min to less than 1 second.
    – michael
    Oct 20, 2023 at 8:52
0

Easier version

for file in *.mp4; do ffmpeg -v error -i "$file" -f null - >error.log 2>&1; print "$file"; done

This will print the file name as they are being processed.

error.log will contain the errors.

1
  • Use make to create %.log from %.mp4. Then you can easily run multiple check-jobs in parallel with make's -j switch.
    – Mikhail T.
    Jun 13, 2020 at 22:03
0

fluent-ffmpeg

var ffmpeg = require('fluent-ffmpeg');
var ff = new ffmpeg();

ff.on('start', function(commandLine) {
  // on start, you can verify the command line to be used
})
.on('progress', function(data) {
  // do something with progress data if you like
})
.on('end', function() {
  // do something when complete
})
.on('error', function(err, stdout, stderr) {
  // handle error conditions
  console.log('Error: ' + err.message)
  console.log('ffmpeg output:\n' + stdout)
  console.log('ffmpeg stderr:\n' + stderr)
})
.addInput('path\to\file')
.addInputOption('-xerror')
.addInputOption('-v error')
.output('-')
.outputOptions('-f null')
.run();

Reference:

https://stackoverflow.com/questions/43349360/how-to-check-for-corrupted-webm-video-using-node-js-and-fluent-ffmpeg

0
def check(dirpath):
    files = [f for f in listdir(dirpath) if isfile(join(dirpath, f))]
    invalidfiles = []
    for filename in files:
        cmd_args = ['ffprobe', dirpath + '/' + filename]
        pipes = subprocess.Popen(cmd_args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        #If you are using python 2.x, you need to include shell=True in the above line
        std_out, std_err = pipes.communicate()
        if 'invalid data' in std_out.decode('utf-8').lower() :
            invalidfiles.append(dirpath + '/' + filename)
            continue
        if 'invalid data' in std_err.decode('utf-8').lower() :
            invalidfiles.append(dirpath + '/' + filename)
            continue
    return invalidfiles
1
  • 1
    As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.
    – Community Bot
    Jan 4, 2022 at 4:04
0

I wrote a wrapper for the ffmpeg command in the form of a GUI-based Python program to batch scan video files in a selected directory; assessing if the files are healthy or corrupt. This is based on the command posted above: ffmpeg -v error -i file.avi -f null - 2>error.log

The program is supported on Windows and macOS and is in the form of a portable executable for either OS. Simply download and run. Regards!

https://github.com/nhershy/CorruptVideoFileInspector

0
0

The one-liner I use is:

nice find . \( -iname \*.mp4 -o -iname \*.avi -o -iname \*.mkv \) -exec bash -c  'ffmpeg -v error -xerror -i "{}" -f null - || echo error in "{}"' \;
  • nice lowers the priority so as not to interfere with system performance
  • find looks for MP4/AVI/MKV files (case-insensitive) recursively, starting from the current directory
  • ffmpeg -xerror stops with an error code on the first decoding error
  • echo prints the damaged file's name

In my experience, adding -map 0:1 option to ffmpeg (in order to decode only audio) can significantly speed up processing, but at a price of false negatives. E.g. it rarely detects incomplete MP4 files, because audio data usually takes about 10% of the total clip, so the probability that an arbitrary cut through a file will damage the audio track is also about 10%.

-2

MediaInfo is a great tool for getting info about any video file you care to throw at it. This may be able to highlight the info you want.

Another tool is GSpot but it hasn't been updated since 2007.

Try giving each one a known good and known bad file and compare the results.

I used to use GSpot until it stopped being updated, then switched to MediaInfo

5
  • 1
    I have some old version of GSpot on my machine ... but it is a tool for something completely different (determining the code/decode...). It has nothing to do with this. I'll check out mediainfo.
    – Rook
    Jan 25, 2010 at 13:18
  • GSpot will report if file size or frame count do not match the expected from the index (somewhere on the left hand side, it's been a while since I used it!), also later versions added much functionality.
    – Shevek
    Jan 25, 2010 at 14:45
  • mediainfo can recursively scan directories: to get a report of all files at any level starting from the current folder simply run mediainfo *.
    – ccpizza
    Jun 12, 2016 at 22:00
  • 3
    mediainfo apparently does not check for completeness. I took a 33 MB webm video file and truncated it to the half. mediainfo still had nearly the same output for both, no apparent sign of corruption. After truncateing to 1 MB there still was no clear sign of corruption in the output. Only if you had a deeper look at the output, there was some contradictory information. But these parts depend on the format of the video file, so you cannot automate this detection.
    – Tino
    Dec 19, 2016 at 23:54
  • 8
    mediainfo does not read anything but metadata. This will not check the validity of your file in any way whatsoever. Dec 8, 2017 at 14:13

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .