VideoCheck

A CLI tool for finding corrupt video files.

I’ve been running a Plex server for about 7 years now. It has moved across three machines and numerous hard drives (including one that completely died on me). As such, my media library is a bit wonky at times. As my wife and I try to watch things from Plex, sometimes we end up with movies or shows that don’t play. Sometimes they play, but are not recognizable due to errors in the video.

Essentially, I have a problem with some broken files.

Corrupt Video Files

How a file gets corrupted is unclear. My files from from various… sources …and are of varying quality to begin with. Some files may have been corrupted from the start and I never noticed. Some may have gotten corrupted when moving between servers. Some could just be bit rot. It’s hard to say for sure, but I can say that I have close to 1k movies and almost 10k episodes of TV shows. Fixing these, or in most cases re-sourcing them, is going to be a long process.

Actually fixing a corrupt file is usually a hopeless endeavor. Once a file is broken, it’s basically gone. Sometimes re-encoding can smooth out the issues, but usually the file will need to be replaced.

But first I need to find which ones have problems.

Detecting a Corrupt File

There’s one very simple way to find a corrupt video: watch it.

For the amount of files I have, though, that’s not exactly feasible. Plus, one player might not notice some problems that would completely crash another player. VLC can play just about anything and will handle errors with grace, but Plex on a Roku might not play the same file at all. And who knows how Plex on iOS would handle it.

Enter the magic ffmpeg command:

ffmpeg -v error -t 120 -i movie.mkv -f null -

ffmpeg, for those unaware, is an amazing tool for doing just about anything to video and audio files. This command looks a bit strange if you’re unfamiliar with it. Let’s break it down:

  • -v error - Sets the verbosity to error. This means we will only see any output if there are errors. If the command finishes with no output, the file is clean.
  • -t 120 - Read only the first two minutes of the input file. This can be shorted for a quicker check or lengthened for a more thorough check. I find that two minutes is a good middle-ground that catches most errors.
  • -i movie.mkv - The file to scan. Note that the -t option has to come before we define the input.
  • -f null - Convert the file to nothing. This essentially makes ffmpeg read the file but not actually convert it.
  • - - Makes the shell discard the resulting file (which would be nothing anyways).

In short, the command takes a file, reads the first two minutes of it, and then spits out any errors it finds to the console. Run it against any file and if you see any results then that file is corrupted. Simple and easy to use.

Note that how fast this runs depends entirely on your hardware. On my 2020 Intel MacBook Pro, a 2 minute scan can take anywhere from 5-30 seconds, depending on the bitrate of the input file.

Scanning Lots of Files for Errors

The command is great when I’m ingesting new files into Plex. It’s rare that I am adding lots of files at once, so checking individual files is fine.

But what about the existing files?

Obviously, I could write some shell script that runs that ffmpeg command in a loop. The problem there is that I’m awful with shell scripts and I would want some more control over the inputs and outputs. I also want some better logging of what has and has not been scanned, and the results of each scan.

Yes, I know about Tdarr and I’ve tried to get it set up. It’s the most un-intuitive application I have ever used and I hated every moment about trying to configure it.

Then one day I stumbled on CliWrap, a .NET library for running command line processes. I’ve toyed with the idea of calling ffmpeg from .NET before, but I’ve never been happy with the available libraries for interfacing with it. This one, though, wouldn’t have to interface with ffmpeg directly. I could simply format the command in code then let the library run the command.

I know how to build CLIs in .NET, and I’ve even built one that can scan and act on files, so the rest came together pretty fast.

VideoCheck

VideoCheck is my new tool for scanning video files for errors. Point it at a directory (or a single file) and it will invoke the ffmpeg CLI to find errors. It keeps track of the files it has scanned and which ones have returned errors in a local database.

vcheck scan

The scanning part of the tool has some useful options, too. You can enable recursive scanning so it will crawl subdirectories. You can adjust how many minutes to scan for faster or more thorough checking. And when you’re all done, you can view or export the log to see which files need attention (read: replaced).

Like my renaming tool, I’ve made this repo public as I think others may find it helpful.

Just for some fun numbers, it took hours to scan my movies folder and it found just shy of 100 files with errors out of almost 1k. Once I fix the movies, I plan to use my gaming PC (with it’s much better cooling) to scan the TV shows folder, probably overnight.


Photo by Michael Dziedzic on Unsplash.