Last active
August 25, 2023 12:13
-
-
Save Deathproof76/76f5c087a15bcdcaeeeed3c59228766b to your computer and use it in GitHub Desktop.
Check video files with ffprobe if there is only one i-frame in the first 20 seconds of the file
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
import subprocess | |
import time | |
import sys | |
import select | |
def rename_defective_file(filepath): | |
"""Rename the defective file by appending '_(i_frame_defect)' before the file extension.""" | |
root, ext = os.path.splitext(filepath) | |
new_name = f"{root}_(i_frame_defect){ext}" | |
os.rename(filepath, new_name) | |
return new_name | |
# Detailed introductory message | |
print("DESCRIPTION:") | |
print("------------") | |
print("This script will recursively search the current directory and its subdirectories for video files.") | |
print("Each video file will be checked using 'ffprobe' to determine if there's only one I-frame in the first 20 seconds.") | |
print("Files with only one I-frame in the first 20 seconds will be deemed 'defective'.") | |
# Provide options to the user | |
print("\nOPTIONS:") | |
print("1. Just output the full path of affected files to 'defect_files.txt'.") | |
print("2. Output the full path of affected files to 'defect_files.txt' and rename the defective files by appending '_(i_frame_defect)' to their filename.") | |
# Get user's choice | |
choice = input("\nChoose an option (1/2): ") | |
# 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 = [] | |
# Check each video file with ffprobe for I-frames in the first 20 seconds | |
for index, video_file in enumerate(video_files, start=1): | |
print(f"Checking file {index}/{len(video_files)}: {video_file}") | |
command = [ | |
'ffprobe', | |
'-select_streams', 'v', | |
'-show_frames', | |
'-read_intervals', '%+#20', | |
'-of', 'csv=p=0', | |
'-i', video_file | |
] | |
result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) | |
output = result.stdout.decode('utf-8') | |
i_frames = sum(1 for line in output.splitlines() if line.split(',')[1] == 'I') | |
if i_frames == 1: | |
if choice == '2': | |
video_file = rename_defective_file(video_file) | |
defective_files.append(os.path.abspath(video_file)) | |
# 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"\nFinished checking. Found {len(defective_files)} files with only one I-frame in the first 20 seconds.") | |
print(f"Check 'defect_files.txt' and 'defect_files_one_line.txt' for lists of defective files.") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
ffmpeg6 with libvpl (onevpl) can produce files with a broken gop, when using qsv to encode to hevc because of bad default settings. Files have only a single i-frame. Even though the files seem intact, the have problems when seeking(long buffering, the bigger the file the worse). This script identifies those files and outputs the full filepath to a txt file for batch ops.
first option: filepaths to txt file
second option: same + rename the affected files by appending _(iframe_defect) between filename and extension