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()