aif2f (3603B)
1 #!/usr/bin/env python3 2 import subprocess 3 import argparse 4 from pathlib import Path 5 6 7 def check_artwork(file_path): 8 result = subprocess.run( 9 [ 10 "ffprobe", 11 "-v", "error", 12 "-select_streams", "v", 13 "-show_entries", "stream=codec_type", 14 "-of", "default=noprint_wrappers=1:nokey=1", 15 str(file_path), 16 ], 17 capture_output=True, 18 text=True, 19 ) 20 return "video" in result.stdout 21 22 23 def convert_aif_to_flac(input_path, delete_original=True): 24 output_path = input_path.with_suffix(".flac") 25 26 if output_path.exists(): 27 print(f"Skipping {input_path} - {output_path} already exists") 28 return True 29 30 print(f"Converting {input_path} to {output_path}") 31 32 try: 33 subprocess.run( 34 [ 35 "ffmpeg", 36 "-i", str(input_path), 37 "-c:a", "flac", 38 "-compression_level", "8", 39 "-map", "0:a", 40 "-map", "0:v?", 41 "-map_metadata", "0", 42 str(output_path), 43 ], 44 check=True, 45 capture_output=True, 46 ) 47 48 had_artwork = check_artwork(input_path) 49 if had_artwork: 50 if check_artwork(output_path): 51 print(f"Successfully converted {input_path} (artwork preserved)") 52 else: 53 print(f"Warning: Artwork may not have transferred for {input_path}") 54 else: 55 print(f"Successfully converted {input_path}") 56 57 if delete_original: 58 try: 59 input_path.unlink() 60 print(f"Deleted original file: {input_path}") 61 except Exception as e: 62 print(f"Warning: Could not delete original file {input_path}: {e}") 63 64 return True 65 66 except subprocess.CalledProcessError as e: 67 print(f"Error converting {input_path}:") 68 print(f"ffmpeg error: {e.stderr.decode()}") 69 return False 70 except Exception as e: 71 print(f"Unexpected error converting {input_path}: {e}") 72 return False 73 74 75 def main(): 76 parser = argparse.ArgumentParser( 77 description="Convert AIF/AIFF files to FLAC format recursively." 78 ) 79 parser.add_argument("folder_path", help="Path to the folder containing AIF files") 80 parser.add_argument( 81 "--keep-original", 82 action="store_true", 83 help="Keep original AIF files after conversion (default: delete)", 84 ) 85 args = parser.parse_args() 86 87 start_dir = Path(args.folder_path).resolve() 88 if not start_dir.exists(): 89 print(f"Error: The directory '{start_dir}' does not exist.") 90 return 91 if not start_dir.is_dir(): 92 print(f"Error: '{start_dir}' is not a directory.") 93 return 94 95 aif_files = list(start_dir.rglob("*.aif")) + list(start_dir.rglob("*.aiff")) 96 97 converted = 0 98 deleted = 0 99 errors = 0 100 101 for aif_file in aif_files: 102 try: 103 success = convert_aif_to_flac(aif_file, not args.keep_original) 104 if success: 105 converted += 1 106 if not args.keep_original and not aif_file.exists(): 107 deleted += 1 108 except Exception as e: 109 print(f"Failed to process {aif_file}: {e}") 110 errors += 1 111 112 print("\nConversion Complete!") 113 print(f"Successfully converted: {converted} files") 114 if not args.keep_original: 115 print(f"Original files deleted: {deleted} files") 116 if errors > 0: 117 print(f"Errors encountered: {errors} files") 118 119 120 if __name__ == "__main__": 121 main()