mrdarkbr/wan22-code-backup
056
1import os2import sys3import argparse4import subprocess5import time6from pathlib import Path7 8 9def clean_path(p: str) -> str:10 """Remove aspas e espaços extras de caminhos arrastados no terminal do Windows."""11 if not p:12 return ""13 p = p.strip()14 if (p.startswith('"') and p.endswith('"')) or (p.startswith("'") and p.endswith("'")):15 p = p[1:-1].strip()16 return os.path.abspath(p)17 18 19def main():20 parser = argparse.ArgumentParser(description="Cliente Face Swap com MaskVidExperiments no Modal")21 parser.add_argument("--source", "-s", type=str, help="Caminho da Foto 1 (rosto de origem)")22 parser.add_argument("--target", "-t", type=str, help="Caminho do Vídeo 2 (vídeo de destino)")23 parser.add_argument("--output", "-o", type=str, default="", help="Caminho do arquivo de saída .mp4")24 parser.add_argument("--crop-scale", type=float, default=2.2, help="Escala de enquadramento do MaskVid (padrão: 2.2)")25 parser.add_argument("--mp", "--megapixels", type=float, default=1.0, help="Resolução alvo em Megapixels para o crop facial (padrão: 1.0 MP)")26 parser.add_argument("--no-enhance", action="store_true", help="Desativa o restaurador facial GFPGAN HD")27 parser.add_argument("--enhance-weight", type=float, default=0.90, help="Força do aprimoramento facial HD (0.0 a 1.0, padrão: 0.90)")28 29 args = parser.parse_args()30 31 source_path = clean_path(args.source) if args.source else ""32 target_path = clean_path(args.target) if args.target else ""33 enhance = not args.no_enhance34 enhance_weight = args.enhance_weight35 megapixels = args.mp36 37 print("=" * 65)38 print(" 🎭 MASKVID EXPERIMENTS - FACE SWAP EM VÍDEO (MODAL)")39 print("=" * 65)40 print()41 42 # Se não passou foto por argumento, solicita interativamente43 while not source_path or not os.path.exists(source_path):44 if source_path and not os.path.exists(source_path):45 print(f"❌ Arquivo não encontrado: {source_path}")46 print("📌 [1/2] Arraste e solte aqui a FOTO 1 (Rosto de Origem):")47 try:48 source_path = clean_path(input("👉 Foto 1: "))49 except KeyboardInterrupt:50 print("\nOperação cancelada.")51 sys.exit(0)52 53 # Se não passou vídeo por argumento, solicita interativamente54 while not target_path or not os.path.exists(target_path):55 if target_path and not os.path.exists(target_path):56 print(f"❌ Arquivo não encontrado: {target_path}")57 print("\n📌 [2/2] Arraste e solte aqui o VÍDEO 2 (Vídeo de Destino):")58 try:59 target_path = clean_path(input("👉 Vídeo 2: "))60 except KeyboardInterrupt:61 print("\nOperação cancelada.")62 sys.exit(0)63 64 # Auto-correção se o usuário inverteu os arquivos (ex: passou vídeo na Foto 1 e imagem no Vídeo 2)65 vid_exts = {".mp4", ".mov", ".avi", ".mkv", ".webm", ".flv", ".wmv"}66 img_exts = {".jpg", ".jpeg", ".png", ".webp", ".bmp", ".jfif"}67 src_ext = Path(source_path).suffix.lower()68 tgt_ext = Path(target_path).suffix.lower()69 70 if src_ext in vid_exts and tgt_ext in img_exts:71 print("\n💡 [Info] Detectado que a Foto 1 é um vídeo e o Vídeo 2 é uma foto.")72 print("🔄 Invertendo automaticamente para a ordem correta!")73 source_path, target_path = target_path, source_path74 75 # Define saída76 if not args.output:77 timestamp = time.strftime("%Y%m%d_%H%M%S")78 target_name = Path(target_path).stem79 output_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "geradas")80 os.makedirs(output_dir, exist_ok=True)81 output_path = os.path.join(output_dir, f"faceswap_{target_name}_{timestamp}.mp4")82 else:83 output_path = clean_path(args.output)84 os.makedirs(os.path.dirname(os.path.abspath(output_path)), exist_ok=True)85 86 print()87 print("-" * 65)88 print(f"📸 Foto 1 (Origem) : {source_path}")89 print(f"🎥 Vídeo 2 (Alvo) : {target_path}")90 print(f"💾 Saída : {output_path}")91 print("-" * 65)92 print("\n⏳ Enviando para a nuvem do Modal e processando...")93 print(" (O primeiro start pode demorar 1-2 minutos para inicializar a GPU)\n")94 95 modal_script = os.path.join(os.path.dirname(os.path.abspath(__file__)), "maskvid_modal.py")96 97 cmd = [98 sys.executable, "-m", "modal", "run", modal_script,99 "--source", source_path,100 "--target", target_path,101 "--output", output_path,102 "--enhance-weight", str(enhance_weight),103 "--crop-scale", str(args.crop_scale),104 "--megapixels", str(megapixels),105 ]106 if not enhance:107 cmd.extend(["--no-enhance"])108 109 start_time = time.time()110 try:111 proc = subprocess.run(cmd, check=True)112 elapsed = time.time() - start_time113 print()114 print("=" * 65)115 print(f"🎉 SUCESSO! Vídeo gerado em {elapsed:.1f} segundos.")116 print(f"📁 Local: {output_path}")117 print("=" * 65)118 119 # Abre o vídeo gerado automaticamente no Windows120 if os.path.exists(output_path):121 try:122 os.startfile(output_path)123 except Exception:124 pass125 except subprocess.CalledProcessError as e:126 print(f"\n❌ Erro na execução do Modal (Código de saída: {e.returncode}).")127 sys.exit(e.returncode)128 except Exception as e:129 print(f"\n❌ Ocorreu um erro: {e}")130 sys.exit(1)131 132 133if __name__ == "__main__":134 main()135 