Files
GigaMux/check_files.py

291 lines
12 KiB
Python

import os
import json
import subprocess
from pathlib import Path
import logging
from datetime import datetime
import sys
# ANSI color codes
class Colors:
GREEN = '\033[92m'
RED = '\033[91m'
YELLOW = '\033[93m'
ENDC = '\033[0m'
# Set up logging
log_dir = "logs"
os.makedirs(log_dir, exist_ok=True)
log_file = os.path.join(log_dir, f"check_{datetime.now().strftime('%Y%m%d_%H%M%S')}.log")
logging.basicConfig(filename=log_file, level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
def write_debug_info(message):
logging.info(message)
def get_file_info(file_path):
try:
cmd = [
'ffprobe',
'-v', 'error',
'-show_entries', 'format=duration,size:stream=codec_name,codec_type,width,height,r_frame_rate,channels,channel_layout',
'-of', 'json',
str(file_path)
]
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode != 0:
return None, f"ffprobe failed: {result.stderr}"
info = json.loads(result.stdout)
if 'format' not in info:
return None, "No format information in ffprobe output"
return info, None
except Exception as e:
return None, f"Error running ffprobe: {str(e)}"
def format_file_size(size_bytes):
size_mb = size_bytes / (1024 * 1024)
if size_mb >= 1024: # If size is 1GB or larger
size_gb = size_mb / 1024
return f"{size_gb:.2f} GB"
return f"{size_mb:.2f} MB"
def check_file(input_path, output_path):
try:
input_info, input_error = get_file_info(input_path)
if input_error:
return f"Input file error: {input_error}"
output_info, output_error = get_file_info(output_path)
if output_error:
return f"Output file error: {output_error}"
# Check if output file exists
if not os.path.exists(output_path):
return f"Missing output file: {output_path}"
# Check duration difference
input_duration = float(input_info['format']['duration'])
output_duration = float(output_info['format']['duration'])
duration_diff = abs(input_duration - output_duration)
if duration_diff > 0.1: # More than 0.1 seconds difference
return f"Duration mismatch: Input={input_duration:.2f}s, Output={output_duration:.2f}s, Diff={duration_diff:.2f}s"
# Check video streams
input_video = next((s for s in input_info['streams'] if s['codec_type'] == 'video'), None)
output_video = next((s for s in output_info['streams'] if s['codec_type'] == 'video'), None)
if not input_video or not output_video:
return "Missing video stream in input or output"
# Check video resolution
if input_video['width'] != output_video['width'] or input_video['height'] != output_video['height']:
return f"Resolution mismatch: Input={input_video['width']}x{input_video['height']}, Output={output_video['width']}x{output_video['height']}"
# Check audio streams
input_audio = [s for s in input_info['streams'] if s['codec_type'] == 'audio']
output_audio = [s for s in output_info['streams'] if s['codec_type'] == 'audio']
if len(input_audio) != len(output_audio):
return f"Audio stream count mismatch: Input={len(input_audio)}, Output={len(output_audio)}"
# Check audio channels
for i, (in_audio, out_audio) in enumerate(zip(input_audio, output_audio)):
if in_audio['channels'] != out_audio['channels']:
return f"Audio channel mismatch in stream {i}: Input={in_audio['channels']}, Output={out_audio['channels']}"
# Check file size
input_size = int(input_info['format']['size'])
output_size = int(output_info['format']['size'])
if output_size < input_size * 0.1: # Output less than 10% of input size
return f"{Colors.YELLOW}Suspiciously small output: Input={format_file_size(input_size)}, Output={format_file_size(output_size)}{Colors.ENDC}"
return None # No issues found
except Exception as e:
return f"Error checking file: {str(e)}"
def main():
# Start debug section in the log file
logging.info("=== Debug Output ===")
input_dir = "input"
output_dir = "output"
# Initialize issue counters
issue_counts = {
"Missing from output": 0,
"Missing from input": 0,
"Duration mismatch": 0,
"Missing video stream": 0,
"Resolution mismatch": 0,
"Audio stream count mismatch": 0,
"Audio channel mismatch": 0,
"Suspiciously small output": 0,
"Other errors": 0
}
write_debug_info(f"\nChecking directories at {datetime.now()}")
write_debug_info(f"Input dir: {input_dir}")
write_debug_info(f"Output dir: {output_dir}")
# Check if directories exist
write_debug_info(f"\nDirectory existence check:")
write_debug_info(f"Input directory exists: {os.path.exists(input_dir)}")
write_debug_info(f"Output directory exists: {os.path.exists(output_dir)}")
# Try to list contents using different methods
write_debug_info("\nTrying 'dir' command:")
try:
result = subprocess.run(['cmd', '/c', 'dir', input_dir], capture_output=True, text=True)
write_debug_info("Input directory contents (dir command):")
write_debug_info(result.stdout)
except Exception as e:
write_debug_info(f"Error with dir command: {str(e)}")
write_debug_info("\nTrying os.listdir():")
try:
write_debug_info("Input directory contents (os.listdir):")
for item in os.listdir(input_dir):
full_path = os.path.join(input_dir, item)
write_debug_info(f" {item} - Exists: {os.path.exists(full_path)} - Is file: {os.path.isfile(full_path)}")
except Exception as e:
write_debug_info(f"Error with os.listdir: {str(e)}")
write_debug_info("\nTrying Path.iterdir():")
try:
write_debug_info("Input directory contents (Path.iterdir):")
for item in Path(input_dir).iterdir():
write_debug_info(f" {item.name} - Exists: {item.exists()} - Is file: {item.is_file()}")
except Exception as e:
write_debug_info(f"Error with Path.iterdir: {str(e)}")
print(f"\nDebug information has been written to {log_file}")
print("Please check that log to see what's actually in the directories")
# Continue with the rest of the script...
print("\nChecking files for inconsistencies...")
logging.info("Starting file check")
# First verify the directories exist
print("\nVerifying directories:")
print(f"Input directory exists: {os.path.isdir(input_dir)}")
print(f"Output directory exists: {os.path.isdir(output_dir)}")
if not os.path.isdir(input_dir) or not os.path.isdir(output_dir):
print("Error: One or both directories do not exist!")
return
issues_found = []
# Get list of files that exist in both directories, verifying each file exists
input_files = set()
for f in os.listdir(input_dir):
if f.endswith(('.mp4', '.DVR.mp4')):
full_path = os.path.join(input_dir, f)
if os.path.isfile(full_path):
input_files.add(f)
write_debug_info(f"Found real file in input: {f}")
else:
write_debug_info(f"Found non-existent file in input: {f}")
output_files = set()
for f in os.listdir(output_dir):
if f.endswith(('.mp4', '.DVR.mp4')):
full_path = os.path.join(output_dir, f)
if os.path.isfile(full_path):
output_files.add(f)
write_debug_info(f"Found real file in output: {f}")
else:
write_debug_info(f"Found non-existent file in output: {f}")
# Debug: Print and log what files were found
logging.info("Files found in input directory:")
for f in sorted(input_files):
logging.info(f" {f}")
logging.info("Files found in output directory:")
for f in sorted(output_files):
logging.info(f" {f}")
# Report missing files
missing_in_output = input_files - output_files
missing_in_input = output_files - input_files
if missing_in_output:
print(f"\n{Colors.YELLOW}Files missing from output directory:{Colors.ENDC}")
for f in sorted(missing_in_output):
print(f" {f}")
logging.warning(f"File missing from output: {f}")
issues_found.append((f, "Missing from output"))
issue_counts["Missing from output"] += 1
if missing_in_input:
print(f"\n{Colors.YELLOW}Files missing from input directory:{Colors.ENDC}")
for f in sorted(missing_in_input):
print(f" {f}")
logging.warning(f"File missing from input: {f}")
issues_found.append((f, "Missing from input"))
issue_counts["Missing from input"] += 1
files_to_check = input_files.intersection(output_files)
logging.info(f"Number of matching files found: {len(files_to_check)}")
if not files_to_check:
msg = "No matching files found in both input and output directories"
print(f"\n{Colors.YELLOW}{msg}{Colors.ENDC}")
logging.warning(msg)
return
for input_file in sorted(files_to_check):
input_path = os.path.join(input_dir, input_file)
output_path = os.path.join(output_dir, input_file)
print(f"\nChecking: {input_file}")
logging.info(f"Checking file: {input_file}")
issue = check_file(input_path, output_path)
if issue:
issues_found.append((input_file, issue))
print(f"{Colors.RED}ISSUE FOUND: {issue}{Colors.ENDC}")
logging.warning(f"Issue with {input_file}: {issue}")
# Count the type of issue
if "Duration mismatch" in issue:
issue_counts["Duration mismatch"] += 1
elif "Missing video stream" in issue:
issue_counts["Missing video stream"] += 1
elif "Resolution mismatch" in issue:
issue_counts["Resolution mismatch"] += 1
elif "Audio stream count mismatch" in issue:
issue_counts["Audio stream count mismatch"] += 1
elif "Audio channel mismatch" in issue:
issue_counts["Audio channel mismatch"] += 1
elif "Suspiciously small output" in issue:
issue_counts["Suspiciously small output"] += 1
else:
issue_counts["Other errors"] += 1
else:
print(f"{Colors.GREEN}No issues found{Colors.ENDC}")
logging.info(f"No issues found for {input_file}")
# Print summary
print("\nSummary of issues found:")
if issues_found:
print("\nIssue counts:")
for issue_type, count in issue_counts.items():
color = Colors.RED if count > 0 else Colors.GREEN
print(f"{issue_type}: {color}{count}{Colors.ENDC}")
print("\nDetailed issues:")
for file, issue in issues_found:
print(f"\n{file}:")
print(f"{Colors.RED} {issue}{Colors.ENDC}")
else:
print(f"{Colors.GREEN}No issues found in any files!{Colors.ENDC}")
print("\nIssue counts:")
for issue_type in issue_counts:
print(f"{issue_type}: {Colors.GREEN}0{Colors.ENDC}")
if __name__ == "__main__":
main()