import os import subprocess from pathlib import Path import matchering as mg import sys def merge_stems_ffmpeg(stems_folder, output_file, ffmpeg_path): print(f"\n[STAGE 6] Mixing Stems using FFmpeg...") stems = [os.path.join(stems_folder, f) for f in os.listdir(stems_folder) if f.startswith("transformed_")] if not stems: print("[ERROR] No transformed stems found!") return False cmd = [ffmpeg_path, "-y"] for s in stems: cmd.extend(["-i", s]) cmd.extend([ "-filter_complex", f"amix=inputs={len(stems)}:duration=longest", "-ac", "2", output_file ]) subprocess.run(cmd, capture_output=True) return True def apply_mastering(input_file, output_file): print(f"\n[STAGE 5] Applying AI Mastering (Matchering)...") try: # Correct Matchering v2 usage: result is the target path string mg.process( target=input_file, reference=input_file, save_to=output_file ) print(f"[SUCCESS] Mastered file saved: {output_file}") return True except Exception as e: print(f"[ERROR] Mastering failed: {e}") # If matchering fails, we still have the final mix return False if __name__ == "__main__": FFMPEG_BIN = "D:/CODE/Apps/devtools/ffmpeg/bin/ffmpeg.exe" FX_DIR = os.path.join(os.getcwd(), "Outputs", "Transformed") MIXED_WAV = os.path.join(os.getcwd(), "Outputs", "Final_Mix.wav") MASTERED_WAV = os.path.join(os.getcwd(), "Outputs", "Titan_Master_Final.wav") if merge_stems_ffmpeg(FX_DIR, MIXED_WAV, FFMPEG_BIN): apply_mastering(MIXED_WAV, MASTERED_WAV)