import os import sys import argparse import subprocess import time from pathlib import Path def count_files(source, extensions): count = 0 if os.path.isfile(source): if Path(source).suffix[1:].lower() in extensions: count = 1 else: for ext in extensions: count += len(list(Path(source).rglob(f'*.{ext}'))) return count def progress_bar(iteration, total, prefix='', suffix='', decimals=1, length=50, fill='█', print_end="\r"): percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total))) filled_length = int(length * iteration // total) bar = fill * filled_length + '-' * (length - filled_length) print(f'\r{prefix} |{bar}| {percent}% {suffix}', end=print_end) if iteration == total: print() def get_conversion_command(source_path, target_path, voice_mode=False): ext = Path(source_path).suffix[1:].lower() audio_extensions = ['mp3', 'wav', 'm4a', 'opus'] video_extensions = ['mp4', 'avi', 'mov', 'webm', 'mkv'] image_extensions = ['jpg', 'jpeg', 'png', 'gif'] if ext in video_extensions: target_path = os.path.splitext(target_path)[0] + '.mp4' elif ext in audio_extensions: target_path = os.path.splitext(target_path)[0] + '.mp3' elif ext in image_extensions: target_path = os.path.splitext(target_path)[0] + '.jpeg' if ext in audio_extensions: if voice_mode: return ['ffmpeg', '-i', source_path, '-vn', '-ar', '22050', '-ac', '1', '-b:a', '32k', '-c:a', 'libmp3lame', target_path] else: return ['ffmpeg', '-i', source_path, '-vn', '-ar', '44100', '-ac', '2', '-b:a', '128k', '-c:a', 'libmp3lame', target_path] elif ext in video_extensions: if ext == 'mkv': return ['ffmpeg', '-i', source_path, '-c', 'copy', target_path] else: return ['ffmpeg', '-i', source_path, '-vf', "fps=30,scale='min(1280,iw)':min'(720,ih)':force_original_aspect_ratio=decrease,pad=1280:720:(ow-iw)/2:(oh-ih)/2", '-c:v', 'libx264', '-crf', '23', '-preset', 'medium', '-c:a', 'aac', '-b:a', '128k', target_path] elif ext in image_extensions: return ['ffmpeg', '-i', source_path, '-vf', "scale='min(1280,iw)':min'(720,ih)':force_original_aspect_ratio=decrease,pad=1280:720:(ow-iw)/2:(oh-ih)/2", '-q:v', '2', target_path] else: return None def convert_files(source, target, dry_run=False, voice_mode=False, delete_original=False): all_extensions = ['mp3', 'wav', 'm4a', 'opus', 'mp4', 'avi', 'mov', 'webm', 'mkv', 'jpg', 'jpeg', 'png', 'gif'] total_files = count_files(source, all_extensions) if dry_run: print(f"Dry run: {total_files} file(s) would be converted") return processed_files = 0 def process_file(source_path, target_path): nonlocal processed_files cmd = get_conversion_command(source_path, target_path, voice_mode) if cmd: print(f"Converting {source_path} to {target_path}") if not dry_run: try: result = subprocess.run(cmd, check=True, capture_output=True, text=True) if delete_original: os.remove(source_path) print(f"Deleted original file: {source_path}") except subprocess.CalledProcessError as e: print(f"Erreur lors de la conversion : {e}") print(f"Sortie d'erreur : {e.stderr}") return processed_files += 1 progress_bar(processed_files, total_files, prefix='Progress:', suffix='Complete') else: print(f"Skipping unsupported file: {source_path}") if os.path.isfile(source): target_dir = os.path.dirname(target) if os.path.isfile(target) else target os.makedirs(target_dir, exist_ok=True) process_file(source, target) else: for root, _, files in os.walk(source): for file in files: source_path = os.path.join(root, file) relative_path = os.path.relpath(source_path, source) target_path = os.path.join(target, relative_path) os.makedirs(os.path.dirname(target_path), exist_ok=True) process_file(source_path, target_path) def main(): parser = argparse.ArgumentParser(description='Convert audio, video, and image files.') parser.add_argument('source', help='Source file or directory containing files to convert') parser.add_argument('target', help='Target file (if source is a file) or directory for converted files') parser.add_argument('--dry-run', action='store_true', help='Perform a dry run without actually converting files') parser.add_argument('--voice-mode', action='store_true', help='Optimize audio encoding for voice') parser.add_argument('--delete-original', action='store_true', help='Delete original files after successful conversion') args = parser.parse_args() if not os.path.exists(args.source): print(f"Error: Source path '{args.source}' does not exist.") sys.exit(1) start_time = time.time() convert_files(args.source, args.target, args.dry_run, args.voice_mode, args.delete_original) end_time = time.time() print(f"\nTotal execution time: {end_time - start_time:.2f} seconds") if __name__ == "__main__": main()