#!/usr/bin/env python3 import os import sys import subprocess import shutil def clear_screen(): os.system('cls' if os.name == 'nt' else 'clear') def get_input(prompt, default=None): """Helper to get input with a default value.""" if default: user_input = input(f"{prompt} [{default}]: ").strip() return user_input if user_input else default else: return input(f"{prompt}: ").strip() def get_yes_no(prompt, default="y"): """Helper to get boolean input.""" display_default = "Y/n" if default.lower() in ["y", "yes"] else "y/N" choice = get_input(f"{prompt} ({display_default})", default).lower() return choice in ["y", "yes", "true", "1"] def print_header(): print("==========================================") print(" AI Video Transcriber & Translator V2") print(" (Powered by Google GenAI SDK)") print("==========================================") print("") def main(): clear_screen() print_header() # Try to load the .env file so the wizard knows what's already configured try: from dotenv import load_dotenv script_dir = os.path.dirname(os.path.abspath(__file__)) env_path = os.path.abspath(os.path.join(script_dir, '../../.env_files/.env.aitranscribe')) if os.path.exists(env_path): load_dotenv(env_path) except ImportError: pass # 1. Input File/Folder (Multiple) input_paths = [] while True: prompt_text = "Enter a path to a video file or folder" if input_paths: prompt_text += " (or press Enter to finish)" input_path = get_input(prompt_text) if not input_path: if input_paths: break else: print("Error: You must provide at least one path.") continue # Clean up input input_path = input_path.strip('"\'') input_path = input_path.replace(r'\ ', ' ') # Expand user (~) and resolve absolute path input_path = os.path.abspath(os.path.expanduser(input_path)) if os.path.exists(input_path): input_paths.append(input_path) print(f"Added: {input_path}") else: print(f"Error: Path '{input_path}' does not exist. Please try again.\n") print("\nSelected Inputs:") for p in input_paths: print(f" - {p}") print("") # 2. Languages source_lang = get_input("Source Language (e.g., French, es)", default="auto") target_lang = get_input("Target Language for translation", default="English") print("") # 3. Model Size print("Model Size Options: tiny, base, small, medium, large, auto") model_size = get_input("Whisper Model Size", default="auto") print("") # 4. Features do_cleanup = get_yes_no("Cleanup temporary audio files after processing?", default="y") do_embed = get_yes_no("Embed subtitles into the video file (Soft Subs)?", default="y") do_diarize = get_yes_no("Enable Speaker Diarization (Identify speakers)?", default="n") do_delete_source = False if do_embed: print("\n⚠️ WARNING: Using this next option will PERMANENTLY DELETE the original video files.") print(" It will only run if the new subtitled video is successfully created.") do_delete_source = get_yes_no("Delete original source files after embedding?", default="n") do_prefer_deep = get_yes_no("Prefer DeepTranslate (Free) over Gemini API?", default="n") do_prefer_local = get_yes_no("Prefer Local LLM (Ollama) over all cloud options?", default="n") hf_token = None if do_diarize: if not os.getenv("HF_TOKEN"): print("\nSpeaker Diarization requires a HuggingFace Token.") hf_token = get_input("Enter your HuggingFace Token (hidden)", default="") else: print("Using HF_TOKEN from environment.") # 5. Build Command # Point to v2 main script script_dir = os.path.dirname(os.path.abspath(__file__)) main_script = os.path.join(script_dir, "main.py") cmd = [sys.executable, main_script] cmd.extend(input_paths) cmd.extend(["--lang", target_lang]) cmd.extend(["--model", model_size]) if source_lang != "auto": cmd.extend(["--source-lang", source_lang]) if do_cleanup: cmd.append("--cleanup") if do_embed: cmd.append("--embed") if do_delete_source: cmd.append("--delete-source") if do_diarize: cmd.append("--diarize") if hf_token: cmd.extend(["--hf-token", hf_token]) if do_prefer_deep: cmd.append("--prefer-deep") if do_prefer_local: cmd.append("--prefer-local") # 6. Confirmation and Execution clear_screen() print_header() print("Configuration Complete!") print("-" * 30) print("Inputs:") for p in input_paths: print(f" - {p}") print(f"Source Lang: {source_lang}") print(f"Target Lang: {target_lang}") print(f"Model: {model_size}") print(f"Cleanup: {do_cleanup}") print(f"Embed Subs: {do_embed}") print(f"Delete Src: {do_delete_source}") print(f"Diarization: {do_diarize}") print(f"Prefer Deep: {do_prefer_deep}") print(f"Prefer Local: {do_prefer_local}") print("-" * 30) if not get_yes_no("Run this job now?", default="y"): print("Aborted.") sys.exit(0) print("\nStarting Job (V2)...") try: # Pass environment variables including HF_TOKEN if set env = os.environ.copy() if hf_token: env["HF_TOKEN"] = hf_token subprocess.run(cmd, check=True, env=env) print("\n✅ Job Complete!") except subprocess.CalledProcessError as e: print(f"\n❌ Job Failed with error code {e.returncode}") except KeyboardInterrupt: print("\nJob interrupted by user.") if __name__ == "__main__": main()