added diag script

This commit is contained in:
2026-01-12 10:53:06 -05:00
parent 0a6e9ed1d8
commit 7ad3715c52
4 changed files with 172 additions and 18 deletions
+95
View File
@@ -0,0 +1,95 @@
#!/usr/bin/env python3
import sys
import shutil
import subprocess
import torch
import os
def check_flatpak():
return os.path.exists("/.flatpak-info")
def run_cmd(cmd_list):
in_flatpak = check_flatpak()
if in_flatpak:
full_cmd = ["flatpak-spawn", "--host"] + cmd_list
else:
full_cmd = cmd_list
try:
result = subprocess.run(full_cmd, capture_output=True, text=True)
return result.returncode == 0, result.stdout.strip(), result.stderr.strip()
except FileNotFoundError:
return False, "", "Command not found"
except Exception as e:
return False, "", str(e)
def main():
print("========================================")
print(" AI Transcriber Diagnostic Tool")
print("========================================")
in_flatpak = check_flatpak()
print(f"Environment: {'Flatpak Sandbox' if in_flatpak else 'Native Host'}")
print("-" * 40)
# 1. GPU Check (PyTorch)
print("\n[1] GPU Availability (Internal PyTorch)")
if torch.cuda.is_available():
print(f"✅ GPU Detected: {torch.cuda.get_device_name(0)}")
print(f" VRAM: {torch.cuda.get_device_properties(0).total_memory / 1024**3:.2f} GB")
print(f" CUDA Version: {torch.version.cuda}")
else:
print("❌ GPU NOT Detected by PyTorch.")
print(" Whisper will run on CPU (Slow).")
# 2. Nvidia Driver Check (System)
print("\n[2] Nvidia Driver Check (System)")
ok, out, err = run_cmd(["nvidia-smi", "--query-gpu=name,driver_version", "--format=csv,noheader"])
if ok:
print(f"✅ Driver Active: {out}")
else:
print("❌ 'nvidia-smi' failed. Drivers might be missing or inaccessible.")
if err: print(f" Error: {err}")
# 3. FFmpeg Check
print("\n[3] FFmpeg Check")
ok, out, err = run_cmd(["ffmpeg", "-version"])
if ok:
version_line = out.split('\n')[0]
print(f"✅ FFmpeg Ready: {version_line}")
else:
print("❌ FFmpeg NOT found.")
print(" On Bazzite, install it with: 'brew install ffmpeg'")
# 4. FFprobe Check
print("\n[4] FFprobe Check (Required for duration checks)")
ok, out, err = run_cmd(["ffprobe", "-version"])
if ok:
version_line = out.split('\n')[0]
print(f"✅ FFprobe Ready: {version_line}")
else:
print("❌ FFprobe NOT found.")
# 5. Ollama Check
print("\n[5] Local LLM (Ollama)")
ok, out, err = run_cmd(["ollama", "--version"])
if ok:
print(f"✅ Ollama Installed: {out}")
# Check server
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(1)
result = sock.connect_ex(('127.0.0.1', 11434))
if result == 0:
print("✅ Ollama Server is RUNNING.")
else:
print("⚠️ Ollama Server is NOT running (Scripts will try to auto-start it).")
else:
print("❌ Ollama NOT found.")
print(" Run: ./ai_transcriber_v2/install_local_llm.sh")
print("\n========================================")
if __name__ == "__main__":
main()
@@ -1,6 +1,7 @@
import os import os
import subprocess import subprocess
import sys import sys
import json
from utils import verify_file_not_empty from utils import verify_file_not_empty
def run_ffmpeg(args): def run_ffmpeg(args):
@@ -20,6 +21,27 @@ def run_ffmpeg(args):
print("Error: 'ffmpeg' command not found. Please ensure it is installed on your host system.") print("Error: 'ffmpeg' command not found. Please ensure it is installed on your host system.")
return False return False
def get_video_duration(file_path):
"""
Gets video duration in seconds using ffprobe.
"""
in_flatpak = os.path.exists("/.flatpak-info")
cmd_base = ["flatpak-spawn", "--host"] if in_flatpak else []
cmd = cmd_base + [
"ffprobe",
"-v", "error",
"-show_entries", "format=duration",
"-of", "default=noprint_wrappers=1:nokey=1",
file_path
]
try:
result = subprocess.run(cmd, capture_output=True, text=True, check=True)
return float(result.stdout.strip())
except Exception:
return 0.0
def extract_audio(video_path, output_path=None): def extract_audio(video_path, output_path=None):
""" """
Extracts audio from a video file using ffmpeg. Extracts audio from a video file using ffmpeg.
@@ -58,10 +80,19 @@ def extract_audio(video_path, output_path=None):
def embed_subtitles(video_path, srt_path, output_path=None): def embed_subtitles(video_path, srt_path, output_path=None):
""" """
Embeds subtitles into the video file (Soft Subs) and sets them as primary. Embeds subtitles into the video file (Soft Subs) and sets them as primary.
Includes strict safety checks (Size & Duration) to prevent replacing videos with corrupted files.
""" """
if not os.path.exists(video_path) or not os.path.exists(srt_path): if not os.path.exists(video_path) or not os.path.exists(srt_path):
print("Error: Video or SRT file not found for embedding.") print("Error: Video or SRT file not found for embedding.")
return return False
# Capture original stats
original_size = os.path.getsize(video_path)
original_duration = get_video_duration(video_path)
if original_size == 0:
print("Error: Source video is 0 bytes.")
return False
if output_path is None: if output_path is None:
base, ext = os.path.splitext(video_path) base, ext = os.path.splitext(video_path)
@@ -91,8 +122,39 @@ def embed_subtitles(video_path, srt_path, output_path=None):
] ]
if run_ffmpeg(args): if run_ffmpeg(args):
if not verify_file_not_empty(output_path): # --- Safety Checks ---
raise Exception("FFmpeg succeeded but output video is empty.") if not os.path.exists(output_path):
print("Error: Output file was not created.")
return False
new_size = os.path.getsize(output_path)
new_duration = get_video_duration(output_path)
# 1. Zero Byte Check
if new_size == 0:
print("❌ CRITICAL: Output file is 0 bytes. Deleting corrupted output.")
os.remove(output_path)
raise Exception("Embedding failed: Output is empty.")
# 2. Significant Size Drop Check
if new_size < (original_size * 0.8):
print(f"❌ CRITICAL: Output file is significantly smaller than source!")
print(f" Original: {original_size/1024/1024:.2f} MB")
print(f" New: {new_size/1024/1024:.2f} MB")
os.remove(output_path)
raise Exception("Embedding failed: Suspicious file size reduction.")
# 3. Duration Mismatch Check (New)
if abs(original_duration - new_duration) > 1.0:
print(f"❌ CRITICAL: Duration mismatch detected!")
print(f" Original: {original_duration:.2f}s")
print(f" New: {new_duration:.2f}s")
print(" This indicates truncated video stream. Aborting.")
os.remove(output_path)
raise Exception("Embedding failed: Duration mismatch > 1s.")
print(f"Subtitles embedded successfully: {output_path}") print(f"Subtitles embedded successfully: {output_path}")
return True
else: else:
print("Error: Embedding failed.") print("Error: Embedding failed.")
return False
@@ -195,10 +195,9 @@ def process_file(file_path, args, source_lang=None, loaded_model=None, service_s
should_embed = False should_embed = False
if should_embed: if should_embed:
embed_subtitles(file_path, final_srt_path) success_embed = embed_subtitles(file_path, final_srt_path)
if args.delete_source: if success_embed and args.delete_source:
if args.embed:
base, ext = os.path.splitext(file_path) base, ext = os.path.splitext(file_path)
expected_output = f"{base}.subbed{ext}" expected_output = f"{base}.subbed{ext}"
@@ -210,8 +209,6 @@ def process_file(file_path, args, source_lang=None, loaded_model=None, service_s
tracker.logger.error(f"Error deleting source: {e}") tracker.logger.error(f"Error deleting source: {e}")
else: else:
tracker.logger.error(f"SAFETY ABORT: Output '{expected_output}' not found.") tracker.logger.error(f"SAFETY ABORT: Output '{expected_output}' not found.")
else:
tracker.logger.warning("SAFETY ABORT: Enable --embed to delete source.")
tracker.update_step(file_path, "step_embed", "done") tracker.update_step(file_path, "step_embed", "done")
# 5. Cleanup # 5. Cleanup