Skip to content

Instantly share code, notes, and snippets.

@Deathproof76
Last active August 25, 2023 11:53
Show Gist options
  • Save Deathproof76/fdc283c77d9e4f1d532bfe71314df0d2 to your computer and use it in GitHub Desktop.
Save Deathproof76/fdc283c77d9e4f1d532bfe71314df0d2 to your computer and use it in GitHub Desktop.
Find all defective video files (mp4/mkv/avi) with ffprobe in directory and subfoldes with "moov atom not found" in error_output or "Invalid data found when processing input" and print full path to txt file
import os
import subprocess
import time
import sys
import select
# Detailed introductory message
print("DESCRIPTION:")
print("------------")
print("This script will recursively search the current directory and its subdirectories for video files with extensions .mp4, .mkv, and .avi.")
print("Each video file will be checked using 'ffprobe', a tool from the FFmpeg suite, to determine its integrity.")
print("The script deems a video file as 'defective' if 'ffprobe' returns an error containing 'moov atom not found' or 'Invalid data found when processing input'.")
print("Defective files will have their full system path written immediately to 'defect_files.txt' in the directory where the script was executed.")
print("All unique ffprobe errors will be logged to 'ffprobe_errors.txt'.")
print("\nStarting in:")
# 15-second countdown
def countdown(seconds):
for i in range(seconds, 0, -1):
# Check if there's input on stdin (i.e., a keypress)
i, o, e = select.select([sys.stdin], [], [], 1)
if i:
sys.stdin.readline() # Clear the input buffer
break
print(f"{i} seconds...")
time.sleep(1)
countdown(15)
# Get a list of all video files in the current directory and subdirectories
video_extensions = ['.mp4', '.mkv', '.avi']
video_files = [os.path.join(root, file)
for root, dirs, files in os.walk('.')
for file in files if os.path.splitext(file)[1] in video_extensions]
defective_files = []
unique_errors = set()
# Check each video file with ffprobe
for index, video_file in enumerate(video_files, start=1):
print(f"Checking file {index}/{len(video_files)}: {video_file}")
try:
subprocess.run(['ffprobe', video_file], stderr=subprocess.PIPE, stdout=subprocess.PIPE, check=True)
except subprocess.CalledProcessError as e:
error_output = e.stderr.decode('utf-8')
unique_errors.add(error_output.strip()) # Add error message to the set of unique errors
if "moov atom not found" in error_output or "Invalid data found when processing input" in error_output:
defective_files.append(os.path.abspath(video_file))
# Write unique ffprobe errors to a log file
with open('ffprobe_errors.txt', 'w') as f:
for error in unique_errors:
f.write(error + '\n\n')
# Write all defective file paths to defect_files.txt, each on a new line
with open('defect_files.txt', 'w') as f:
for file in defective_files:
f.write(file + '\n')
# Write all defective file paths to defect_files_one_line.txt in a single line
with open('defect_files_one_line.txt', 'w') as f:
f.write(' '.join(defective_files))
print(f"Finished checking. Found {len(defective_files)} defective files.")
print(f"Check 'defect_files.txt' and 'defect_files_one_line.txt' for lists of defective files, and 'ffprobe_errors.txt' for a log of unique errors.")
@Deathproof76
Copy link
Author

Deathproof76 commented Aug 25, 2023

Google Takeout broke a lot of videos in my case, found out late. This helped me identify them. Just put the check_videos.py script in relevant folder make executable. Have ffprobe on path, do "python check_videos.py" and it checks all files in the folder and subfolders and it will output three txt files with the full filepath of affected files. One with only full path of files with errors regarding "moov atom not found" in ffprobe error_output or "Invalid data found when processing input", another with the same but in a single line and one with the full ffprobe error output (to doublecheck).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment