#!/usr/bin/env python3 """ DETECTOR DE MUERTES - SOLO OCR EN KDA ===================================== Metodología pura: 1. Escanear el video cada 2 segundos 2. Extraer SOLO la zona del KDA (esquina superior izquierda) 3. Usar Tesseract OCR para leer el número de deaths 4. Detectar CUANDO cambia (0→1, 1→2, 2→3, etc.) 5. Generar highlights de esos momentos exactos Zona KDA: x=0, y=0, w=300, h=130 (1080p) """ import cv2 import numpy as np import pytesseract import subprocess import os from datetime import timedelta import re VIDEO_PATH = "stream_2699641307_1080p60.mp4" OUTPUT_DIR = "highlights_muertes" def format_time(seconds): return str(timedelta(seconds=int(seconds))) def extract_kda_frame(timestamp): """Extrae SOLO la zona del KDA""" temp = f"/tmp/kda_{int(timestamp)}.png" cmd = [ "ffmpeg", "-y", "-ss", str(timestamp), "-i", VIDEO_PATH, "-vframes", "1", "-vf", "crop=300:130:0:0,scale=600:260,eq=contrast=1.5:brightness=0.2", temp, ] subprocess.run(cmd, capture_output=True, timeout=15) return temp if os.path.exists(temp) else None def read_deaths_ocr(image_path): """Lee el número de deaths con OCR optimizado""" if not os.path.exists(image_path): return None img = cv2.imread(image_path) if img is None: return None # Preprocesamiento agresivo para OCR gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # Aumentar mucho contraste clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8, 8)) enhanced = clahe.apply(gray) # Threshold _, thresh = cv2.threshold(enhanced, 180, 255, cv2.THRESH_BINARY) # OCR - buscar solo números y / config = r"--oem 3 --psm 6 -c tessedit_char_whitelist=0123456789/" text = pytesseract.image_to_string(thresh, config=config) # Buscar formato X/Y/Z matches = re.findall(r"(\d+)/(\d+)/(\d+)", text) if matches: return int(matches[0][1]) # Return deaths (middle number) return None def scan_for_deaths(): """Escanea el video buscando cambios en el KDA""" print("=" * 60) print("ESCANEANDO VIDEO CON OCR") print("=" * 60) print("Buscando: 0→1, 1→2, 2→3, etc.") print("") # Rango del juego 1 (después de 17:29 = 1049s) # Primera muerte confirmada en 41:06 = 2466s start_time = 2460 # Un poco antes end_time = 2800 # Hasta donde sabemos que hay más muertes step = 3 # Cada 3 segundos deaths_found = [] last_deaths = 0 print(f"Escaneando desde {format_time(start_time)} hasta {format_time(end_time)}") print("-" * 60) for ts in range(start_time, end_time, step): frame = extract_kda_frame(ts) if not frame: continue deaths = read_deaths_ocr(frame) # Mostrar progreso cada 30s if ts % 30 == 0: print(f" [{format_time(ts)}] Deaths: {deaths if deaths else '?'}") if deaths and deaths > last_deaths: print(f" 💀 MUERTE DETECTADA: {format_time(ts)} - KDA: 0/{deaths}") deaths_found.append( {"numero": len(deaths_found) + 1, "timestamp": ts, "deaths": deaths} ) last_deaths = deaths # Limpiar if os.path.exists(frame): os.remove(frame) return deaths_found def extract_clip(timestamp, numero, deaths_count): """Extrae clip de una muerte""" os.makedirs(OUTPUT_DIR, exist_ok=True) start = max(0, timestamp - 8) duration = 18 # 8s antes + 10s después output = f"{OUTPUT_DIR}/muerte_{numero:02d}_KDA_0_{deaths_count}_{timestamp}s.mp4" cmd = [ "ffmpeg", "-y", "-ss", str(start), "-t", str(duration), "-i", VIDEO_PATH, "-c:v", "h264_nvenc", "-preset", "fast", "-cq", "23", "-r", "60", "-c:a", "copy", output, ] subprocess.run(cmd, capture_output=True, timeout=120) return output if os.path.exists(output) else None def main(): print("\nDETECTOR OCR - SOLO MUERTES REALES\n") # Escanear deaths = scan_for_deaths() if not deaths: print("No se encontraron muertes") return print("") print(f"✓ Total muertes encontradas: {len(deaths)}") print("") # Extraer clips print("=" * 60) print("EXTRAYENDO CLIPS") print("=" * 60) clips = [] for d in deaths: print( f"Muerte #{d['numero']} - KDA 0/{d['deaths']} - {format_time(d['timestamp'])}" ) clip = extract_clip(d["timestamp"], d["numero"], d["deaths"]) if clip: size = os.path.getsize(clip) / (1024 * 1024) print(f" ✓ {size:.1f}MB") clips.append(clip) print("") print(f"✓ {len(clips)} clips generados en {OUTPUT_DIR}/") if __name__ == "__main__": main()