import os import sys import re import subprocess from pathlib import Path def is_cuda_fully_functional(): """Checks if CUDA is fully available and functional by running a quick subprocess check""" try: # Run in a separate process to avoid importing torch in the main GUI process cmd = [ sys.executable, "-c", "import torch; import torch.nn as nn; " "print(torch.cuda.is_available() and len(torch.cuda.get_arch_list()) > 0 and float(nn.Conv2d(1, 1, 3).cuda()(torch.randn(1, 1, 8, 8).cuda()).to('cpu')[0,0,0,0]) is not None)" ] startupinfo = None if sys.platform == 'win32': startupinfo = subprocess.STARTUPINFO() startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW res = subprocess.run( cmd, capture_output=True, text=True, encoding="utf-8", errors="ignore", timeout=5, startupinfo=startupinfo ) return res.stdout.strip() == "True" except Exception: return False def extract_subtitles_from_video(video_path, blur_region, output_srt_path, log_fn=None): """ Subprocess wrapper for subtitle extraction using PaddleOCR. This prevents importing torch/paddleocr in the main process. """ if not blur_region: raise ValueError("Bạn phải khoanh vùng phụ đề trước khi chạy chế độ quét chữ!") video_path = Path(video_path) output_srt_path = Path(output_srt_path) # Format region: x,y,w,h,orig_w,orig_h region_str = ",".join(map(str, blur_region)) worker_script = Path(__file__).parent / "core" / "ocr_worker_cli.py" cmd = [ sys.executable, str(worker_script), "--video", str(video_path), "--output", str(output_srt_path), "--region", region_str ] if log_fn: log_fn(f"🚀 Khởi chạy quét phụ đề trong subprocess...") startupinfo = None if sys.platform == 'win32': startupinfo = subprocess.STARTUPINFO() startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW try: process = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, encoding="utf-8", errors="ignore", startupinfo=startupinfo ) # Parse output line-by-line for line in process.stdout: line_str = line.strip() if not line_str: continue # Parse progress: PROGRESS: XX% m = re.match(r"PROGRESS:\s*(\d+)%", line_str) if m: pct = int(m.group(1)) filled_len = int(20 * pct / 100) bar = "█" * filled_len + "░" * (20 - filled_len) if log_fn: # Output unified single-line progress bar log_fn(f"\r[STAGE A] Processing Video: [{bar}] {pct}% | Scanning frame data...") else: if log_fn: log_fn(line_str) process.wait() if process.returncode != 0: raise Exception(f"Subprocess OCR failed with exit code {process.returncode}") return True except Exception as e: if log_fn: log_fn(f"❌ Lỗi quét OCR: {e}") raise