nix

Log | Files | Refs | README | LICENSE

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