Files
twitch-highlight-detector/scene_detector.py
renato97 00180d0b1c Sistema completo de detección de highlights con VLM y análisis de gameplay
- Implementación de detector híbrido (Whisper + Chat + Audio + VLM)
- Sistema de detección de gameplay real vs hablando
- Scene detection con FFmpeg
- Soporte para RTX 3050 y RX 6800 XT
- Guía completa en 6800xt.md para próxima IA
- Scripts de filtrado visual y análisis de contexto
- Pipeline automatizado de generación de videos
2026-02-19 17:38:14 +00:00

172 lines
4.9 KiB
Python

#!/opt/vlm_env/bin/python3
"""
SCENE DETECTION + CLASSIFICATION (GPU Accelerated)
Detecta cambios de escena con FFmpeg (rápido) y clasifica cada una
Compatible con RX 6800 XT (16GB VRAM)
"""
import subprocess
import json
import re
from pathlib import Path
print("=" * 70)
print("🎬 SCENE DETECTOR + CLASSIFIER")
print("=" * 70)
print("Paso 1: Detectar cambios de escena con FFmpeg (rápido)")
print("Paso 2: Clasificar cada escena (gameplay vs hablando)")
print()
video_path = (
"/home/ren/proyectos/editor/twitch-highlight-detector/nuevo_stream_360p.mp4"
)
# PASO 1: Detectar cambios de escena (threshold 0.3 = cambios significativos)
print("🔍 Detectando cambios de escena...")
result = subprocess.run(
[
"ffmpeg",
"-i",
video_path,
"-vf",
"select=gt(scene\,0.3),showinfo",
"-f",
"null",
"-",
],
capture_output=True,
text=True,
)
# Extraer timestamps de cambios de escena
scene_changes = []
for line in result.stderr.split("\n"):
if "pts_time:" in line:
match = re.search(r"pts_time:(\d+\.\d+)", line)
if match:
ts = float(match.group(1))
if ts > 455: # Saltar intro
scene_changes.append(ts)
print(f"{len(scene_changes)} cambios de escena detectados")
# PASO 2: Analizar transcripción en cada escena
print("\n📊 Analizando contenido de cada escena...")
with open(
"/home/ren/proyectos/editor/twitch-highlight-detector/transcripcion_rage.json", "r"
) as f:
trans = json.load(f)
# Crear segmentos entre cambios de escena
segments = []
prev_ts = 455
for ts in sorted(scene_changes):
if ts - prev_ts > 30: # Mínimo 30 segundos
segments.append({"start": prev_ts, "end": ts, "duration": ts - prev_ts})
prev_ts = ts
# Agregar último segmento
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())
if duration - prev_ts > 30:
segments.append({"start": prev_ts, "end": duration, "duration": duration - prev_ts})
print(f"{len(segments)} segmentos para analizar")
# PASO 3: Clasificar cada segmento usando transcripción
print("\n🎯 Clasificando segmentos (gameplay vs hablando)...")
for seg in segments:
# Buscar transcripción en este rango
seg_text = []
rage_score = 0
for t in trans["segments"]:
if seg["start"] <= t["start"] <= seg["end"]:
seg_text.append(t["text"].lower())
# Calcular score de rage
if any(word in t["text"].lower() for word in ["puta", "mierda", "joder"]):
rage_score += 10
elif any(
word in t["text"].lower() for word in ["me mataron", "kill", "muere"]
):
rage_score += 8
elif any(word in t["text"].lower() for word in ["ulti", "flash", "gank"]):
rage_score += 5
full_text = " ".join(seg_text)
# Clasificar
if any(
word in full_text for word in ["seleccion", "champions", "ban", "pick", "elij"]
):
seg["type"] = "SELECCION"
seg["keep"] = False
elif any(
word in full_text for word in ["cuento", "historia", "ayer", "comida", "vida"]
):
seg["type"] = "HABLANDO"
seg["keep"] = False
elif rage_score >= 5 or any(
word in full_text for word in ["kill", "matan", "pelea", "fight"]
):
seg["type"] = "GAMEPLAY"
seg["keep"] = True
seg["rage_score"] = rage_score
else:
seg["type"] = "GAMEPLAY_NEUTRO"
seg["keep"] = True
seg["rage_score"] = rage_score
# Mostrar resultados
print("\n" + "=" * 70)
print("SEGMENTOS CLASIFICADOS")
print("=" * 70)
gameplay_segments = [s for s in segments if s["keep"]]
for i, seg in enumerate(segments, 1):
mins_s, secs_s = divmod(int(seg["start"]), 60)
mins_e, secs_e = divmod(int(seg["end"]), 60)
icon = "" if seg["keep"] else ""
print(
f"{icon} {i}. {mins_s:02d}:{secs_s:02d} - {mins_e:02d}:{secs_e:02d} "
f"({seg['duration'] // 60:.0f}m) [{seg['type']}]"
)
if seg.get("rage_score"):
print(f" Rage score: {seg['rage_score']}")
print(f"\n{'=' * 70}")
print(f"RESUMEN")
print(f"{'=' * 70}")
print(f"Total segmentos: {len(segments)}")
print(f"Gameplay útil: {len(gameplay_segments)}")
total_gameplay = sum(s["duration"] for s in gameplay_segments)
print(f"Tiempo gameplay: {total_gameplay // 60:.0f}m {total_gameplay % 60:.0f}s")
# Guardar gameplay útil
with open(
"/home/ren/proyectos/editor/twitch-highlight-detector/gameplay_scenes.json", "w"
) as f:
json.dump(gameplay_segments, f, indent=2)
print(f"\n💾 Guardado: gameplay_scenes.json")
print("\nAhora extrae highlights SOLO de estos rangos confirmados.")