179 lines
5.7 KiB
Python
Executable File
179 lines
5.7 KiB
Python
Executable File
#!/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")
|
|
|
|
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, "ai_transcriber_v2", "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")
|
|
|
|
# 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("-" * 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() |