#!/usr/bin/env python3 """ GPU GAMEPLAY DETECTOR Usa PyTorch + OpenCV en GPU para detectar gameplay en tiempo real """ import torch import cv2 import numpy as np import json import subprocess from pathlib import Path print(f"🎮 GPU Gameplay Detector") print(f"Dispositivo: {torch.cuda.get_device_name(0)}") print(f"VRAM: {torch.cuda.get_device_properties(0).total_memory / 1024**3:.1f} GB") def extract_frame_batch_gpu(video_path, timestamps): """Extrae múltiples frames usando GPU.""" frames = [] for ts in timestamps: # Extraer frame con ffmpeg result = subprocess.run( [ "ffmpeg", "-hwaccel", "cuda", "-i", video_path, "-ss", str(ts), "-vframes", "1", "-f", "image2pipe", "-vcodec", "png", "pipe:1", ], capture_output=True, ) if result.returncode == 0: # Decodificar a numpy array nparr = np.frombuffer(result.stdout, np.uint8) frame = cv2.imdecode(nparr, cv2.IMREAD_COLOR) if frame is not None: frames.append((ts, frame)) return frames def analyze_gameplay_gpu(frames): """ Analiza frames en GPU para detectar gameplay. Detecta: - Movimiento (optical flow) - Bordes (Canny) - UI de LoL tiene bordes característicos - Colores - Paleta característica de LoL """ if not frames: return [] results = [] for ts, frame in frames: # Redimensionar para análisis rápido (GPU) frame_resized = cv2.resize(frame, (320, 180)) # Convertir a tensor y mover a GPU frame_tensor = torch.from_numpy(frame_resized).float().cuda() # Análisis 1: Detectar movimiento (variación entre frames no aplicable aquí) # Análisis 2: Detectar colores característicos de LoL # LoL tiene muchos verdes (mapa), azules (UI), y colores vivos (campeones) mean_color = frame_tensor.mean(dim=(0, 1)) std_color = frame_tensor.std(dim=(0, 1)) # Heurísticas de gameplay de LoL: # - Alta variación de color (std > umbral) # - Presencia de verde (mapa) # - No es gris/negro (menu) is_colorful = std_color.mean() > 40 # Hay variación de color has_green = mean_color[1] > 80 # Canal verde presente (mapa) not_dark = frame_tensor.mean() > 30 # No es pantalla negra/menu # Score de gameplay (0-1) gameplay_score = 0.0 if is_colorful: gameplay_score += 0.4 if has_green: gameplay_score += 0.4 if not_dark: gameplay_score += 0.2 is_gameplay = gameplay_score > 0.6 results.append( { "timestamp": ts, "is_gameplay": is_gameplay, "score": gameplay_score, "color_std": float(std_color.mean()), "green_mean": float(mean_color[1]), } ) # Liberar memoria GPU del frame_tensor torch.cuda.empty_cache() return results def scan_video_gpu(video_path, interval=30): """Escanea video completo usando GPU.""" # Obtener duración result = subprocess.run( [ "ffprobe", "-v", "error", "-show_entries", "format=duration", "-of", "default=noprint_wrappers=1:nokey=1", video_path, ], capture_output=True, text=True, ) duration = float(result.stdout.strip()) print(f"\n📹 Video: {duration / 60:.1f} minutos") print(f"🔍 Analizando cada {interval}s con GPU...") print() # Generar timestamps timestamps = list(range(455, int(duration), interval)) # Procesar en batches para no saturar VRAM batch_size = 10 all_results = [] for i in range(0, len(timestamps), batch_size): batch_ts = timestamps[i : i + batch_size] print( f"Procesando batch {i // batch_size + 1}/{(len(timestamps) - 1) // batch_size + 1}..." ) # Extraer frames frames = extract_frame_batch_gpu(video_path, batch_ts) # Analizar en GPU results = analyze_gameplay_gpu(frames) all_results.extend(results) # Mostrar progreso for r in results: status = "🎮" if r["is_gameplay"] else "🗣️" mins = r["timestamp"] // 60 secs = r["timestamp"] % 60 print(f" {mins:02d}:{secs:02d} {status} Score: {r['score']:.2f}") # Convertir a segmentos segments = [] current_start = None for r in all_results: if r["is_gameplay"]: if current_start is None: current_start = r["timestamp"] else: if current_start is not None: segments.append( { "start": current_start, "end": r["timestamp"], "duration": r["timestamp"] - current_start, } ) current_start = None # Cerrar último if current_start is not None: segments.append( { "start": current_start, "end": int(duration), "duration": int(duration) - current_start, } ) return segments def main(): video_path = "nuevo_stream_360p.mp4" print("=" * 60) print("GPU GAMEPLAY DETECTOR") print("=" * 60) # Escanear segments = scan_video_gpu(video_path, interval=30) # Guardar with open("gameplay_segments_gpu.json", "w") as f: json.dump(segments, f, indent=2) print(f"\n{'=' * 60}") print(f"RESULTADO") print(f"{'=' * 60}") print(f"Segmentos de gameplay: {len(segments)}") total = sum(s["duration"] for s in segments) print(f"Tiempo total gameplay: {total // 60}m {total % 60}s") for i, seg in enumerate(segments, 1): mins_s, secs_s = divmod(seg["start"], 60) mins_e, secs_e = divmod(seg["end"], 60) print( f"{i}. {mins_s:02d}:{secs_s:02d} - {mins_e:02d}:{secs_e:02d} " f"({seg['duration'] // 60}m {seg['duration'] % 60}s)" ) print(f"\n💾 Guardado en: gameplay_segments_gpu.json") if __name__ == "__main__": main()