28

I'm desperately searching for a convenient method to check the integrity of .mp4 files inside a specific directory with folders in it. Both the names of the .mp4 files and the folders contain spaces, special characters and numbers.

I've already found a proper ffmpeg command to quickly identify a damaged .mp4 file, taken from here: ffmpeg -v error -i filename.mp4 -map 0:1 -f null - 2>error.log

If the created error.log contains some entries, then the file is obviously corrupted. The opposite would be an empty error.log.

The next step would be to apply this command to every .mp4 file within the folder and its subfolders. Some guides, like here and here, do describe how to apply a ffmpeg command recursively, but my coding skills are limited, so therefore I can't find a way to combine these commands to get the following:

A way to test all .mp4 files inside a folder (recursively) with the aforementioned ffmpeg command, that should create .log files, only if a video file does contain errors (read has some content) and it should inherit the name of the broken file, to know which file is corrupted.

Using Ubuntu Gnome 15.10.

Community
  • 1
  • 1
DMT
  • 424
  • 2
  • 6
  • 12
  • 1
    Do you need a batch script (Windows) or a shell script (Unix)? – Andrea Dusza Dec 03 '15 at 23:11
  • A shell script, since I'm using Ubuntu Gnome 15.10. Many thanks in advance. – DMT Dec 04 '15 at 10:16
  • 1
    A similar question but on the suitable SE network website: [How can I check the integrity of a video file (avi, mpeg, mp4...)?](https://superuser.com/questions/100288/how-can-i-check-the-integrity-of-a-video-file-avi-mpeg-mp4) – Gras Double Sep 24 '22 at 16:27
  • A GUI wrapper for `ffmpeg` to batch scan video files for integrity within a selected directory: https://github.com/nhershy/CorruptVideoFileInspector – nhershy Mar 12 '23 at 22:15

6 Answers6

29

Try this command:

find . -name "*.mp4" -exec ffmpeg -v error -i "{}" -map 0:1 -f null - 2>error.log \;

The find command finds all files in the current directory recursively which correspond to the given pattern: "*.mp4". After -exec comes the command you want to run for all files. "{}" substitutes the name of the current file, where the quotes allow spaces in file names. The command has to end with \;.

EDIT:

The code above generates only one log file, which makes it impossible to know which file was broken. To instead create separate .log files for each of the .mp4 files, you can use the {} symbol one more time:

find . -name "*.mp4" -exec sh -c "ffmpeg -v error -i '{}' -map 0:1 -f null - 2>'{}.log'" \;
Mitch McMabers
  • 3,634
  • 28
  • 27
Andrea Dusza
  • 2,080
  • 3
  • 18
  • 28
  • Andrea, thanks for responding fast! Your command works only partially: While it takes into account all files inside a folder with its subfolders, only one error.log is created for all files. The bad thing is, that I can't identify the broken video files from the content of this .log file alone, because it shows me only the broken bytes of a file, but not the filename itself. Therefore I'm searching for a command, that will create a separate .log file for each damaged video file, that will have the same name as the damaged video file. – DMT Dec 04 '15 at 15:22
  • This time your updated command created a single .log file called {}.log. Something went wrong. – DMT Dec 04 '15 at 22:07
  • 1
    @dmt I updated the second command, try it! If that still does not work, my last idea is to use the first version with a more verbose logging level: `-v verbose` instead of `-v error`. This way you'd have one log file, but more information, so you would hopefully see which file contains the broken bytes. – Andrea Dusza Dec 04 '15 at 23:50
  • Your updated command didn't work very well again, but the first one with `-v verbose` finally was sufficient to find the broken video files. Huge thanks! – DMT Dec 05 '15 at 09:59
  • Try adding an explicit star. This avoids the implicit `./` that disrupts the redirection:```find * -name "*.mp4" -exec sh -c "ffmpeg -v error -i {} -map 0:1 -f null - 2>{}.log" \;``` – Steve Pitchers May 25 '16 at 16:36
  • Better still: `find *.mp4 -exec sh -c "ffmpeg -v error -i {} -map 0:1 -f null - 2>{}.log" \;` – Steve Pitchers May 25 '16 at 16:37
  • 2
    In case you have space in file name `find -name "*.mp4" -exec sh -c "ffmpeg -v error -i '{}' -map 0:1 -f null - 2>'{}.log'" \;` – dismine Dec 24 '16 at 17:42
  • Thanks a lot, the 2nd command above is brilliant, it creates a .log per file, and does it very rapidly. The `-f null` is responsible for reading files rapidly and just checking frame integrity. Without that flag, it would take almost as long as to watch the movie. – Mitch McMabers Feb 21 '20 at 11:32
12

I recently met with the same problem, but I think there's a simple hack to find out which files are broken:

find -name "*.mp4" -exec sh -c "echo '{}' >> errors.log; ffmpeg -v error -i '{}' -map 0:1 -f null - 2>> errors.log" \;

This way the errors follow the filename (and path).

spot
  • 133
  • 1
  • 7
  • 4
    For even better formatting sourcery `find . -name "*.mp4" -exec sh -c "echo '{}\t\c' >> errors.log; ffmpeg -v error -i '{}' -map 0:1 -f null - 2>> errors.log;echo ''>>errors.log" \;` – awiebe Aug 28 '17 at 03:50
2
find /dir/subdir -iname "*.mp4" -print0 | while read -d $'\0' file; do ERR=`ffprobe -v error "$file" 2>&1`; if [ "$ERR" != "" ]; then echo "$file"; fi; done
Suvier
  • 31
  • 3
1

The issue with the other answers using ffmpeg to recode to null format is that they take a long time. 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.

shivams
  • 923
  • 12
  • 27
  • @llogan This answer only uses thumbnail generation as an alternative to the null encoder. The goal is still finding corrupt video files, although it's much less informative than the other solutions. – Wlerin Jun 06 '20 at 15:08
1

A batch file for Windows systems, assuming that ffmpeg is somewhere in your path:

@echo off
for /r %%f in (*.mp4) do (
    ffmpeg -hide_banner -v error -i "%%f" -map 0:1 -f null - 2>out.txt
    if errorlevel 1 (
        type out.txt
        echo   %%f
    )
)
if exist out.txt del out.txt 1>nul 2>nul
pause

This will list the error followed by the indented file name only for those files in error.

Greg Searle
  • 459
  • 5
  • 3
0

I will leave this here mainly for me and maybe other people that want to use ffmpeg to batch find in multiple folders videos with errors or corrupt files, create a subfolder and move the files in that subfolder.

Here is my bash script for recursive find mp4 files with errors and move them inside 00errors folder.

#!/bin/bash

ROOTPATH="/mnt/f/00test/" # manually define root  path to your folder that has subfolders
for subdir in *; do
  cd ${ROOTPATH}${subdir} 
  mkdir 00errors
  
  for path in *.mp4; do

    ffmpeg error -i "${path}"
    RC=$?

    if [ "${RC}" -ne "0" ]; then
        # Do something to handle the error.
        mv ${path} ./00errors
    fi

  done
  cd ../
done

Edit:

In the meantime I found this app HBBatchBeast for HandBrake and FFmpeg/FFprobe (Windows, macOS, Linux & Docker)

https://github.com/HaveAGitGat/HBBatchBeast

Avram Virgil
  • 1,170
  • 11
  • 22
  • your script moves EVERY video from a folder to a subfolder, regardless if the video is corrupted or not – inside83 Apr 05 '21 at 14:04