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
This commit is contained in:
213
rage_detector.py
Normal file
213
rage_detector.py
Normal file
@@ -0,0 +1,213 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
RAGE & FAIL DETECTOR
|
||||
Prioriza momentos de muerte, rage, insultos y fails.
|
||||
"""
|
||||
|
||||
import json
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def detect_rage_highlights(
|
||||
transcription_file, chat_file, skip_intro=455, max_duration=8237
|
||||
):
|
||||
"""Detecta momentos de rage, muerte y fails."""
|
||||
|
||||
print("=" * 60)
|
||||
print("RAGE & FAIL DETECTOR")
|
||||
print("=" * 60)
|
||||
|
||||
# Cargar transcripción
|
||||
with open(transcription_file, "r") as f:
|
||||
trans = json.load(f)
|
||||
|
||||
# Cargar chat
|
||||
with open(chat_file, "r") as f:
|
||||
chat_data = json.load(f)
|
||||
|
||||
# Diccionario de rage completo
|
||||
rage_patterns = {
|
||||
"extreme_rage": [
|
||||
r"\bputa\b",
|
||||
r"\bmadre\b",
|
||||
r"\bretrasad\w*",
|
||||
r"\bimbecil\b",
|
||||
r"\bestupid\w*",
|
||||
r"\bidiota\b",
|
||||
r"\bmierda\b",
|
||||
r"\bbasura\b",
|
||||
r"\binutil\b",
|
||||
r"\bmongol\w*",
|
||||
r"\bcancer\b",
|
||||
r"\bmaricon\b",
|
||||
],
|
||||
"death": [
|
||||
r"\bme mataron\b",
|
||||
r"\bme mori\b",
|
||||
r"\bmuerto\b",
|
||||
r"\bme matan\b",
|
||||
r"\bmatenme\b",
|
||||
r"\bfeed\w*",
|
||||
r"\bfeeding\b",
|
||||
r"\bme destrozaron\b",
|
||||
r"\bme comieron\b",
|
||||
r"\bme cargaron\b",
|
||||
],
|
||||
"fail": [
|
||||
r"\bla cague\b",
|
||||
r"\bla lie\b",
|
||||
r"\berror\b",
|
||||
r"\bfail\b",
|
||||
r"\bperdon\b",
|
||||
r"\bperdón\b",
|
||||
r"\blo siento\b",
|
||||
r"\bmala mia\b",
|
||||
r"\bfalle\b",
|
||||
r"\bfall[eé]\b",
|
||||
r"\bno puede ser\b",
|
||||
r"\bcomo\?\b",
|
||||
],
|
||||
"team_rage": [
|
||||
r"\bequipo\b.*\b(mierda|basura|malos)\b",
|
||||
r"\bteam\b.*\b(trash|bad)\b",
|
||||
r"\breport\w*",
|
||||
r"\btroll\w*",
|
||||
r"\binting\b",
|
||||
r"\bjugadores\b.*\bmalos\b",
|
||||
],
|
||||
"frustration": [
|
||||
r"\b(nooo|noo|no no no)\b",
|
||||
r"\bpor que\b",
|
||||
r"\bporque\b",
|
||||
r"\ben serio\b",
|
||||
r"\bno me jodas\b",
|
||||
r"\bque (haces|hace)\b",
|
||||
r"\bomg\b",
|
||||
r"\bdios\b",
|
||||
r"\bhostia\b",
|
||||
r"\bjoder\b",
|
||||
],
|
||||
}
|
||||
|
||||
# Analizar cada segmento
|
||||
rage_moments = []
|
||||
|
||||
for seg in trans.get("segments", []):
|
||||
if seg["start"] < skip_intro:
|
||||
continue
|
||||
|
||||
text = seg["text"].lower()
|
||||
score = 0
|
||||
reasons = []
|
||||
|
||||
for category, patterns in rage_patterns.items():
|
||||
for pattern in patterns:
|
||||
if re.search(pattern, text, re.IGNORECASE):
|
||||
if category == "extreme_rage":
|
||||
score += 15
|
||||
if "EXTREME" not in reasons:
|
||||
reasons.append("EXTREME")
|
||||
elif category == "death":
|
||||
score += 12
|
||||
if "DEATH" not in reasons:
|
||||
reasons.append("DEATH")
|
||||
elif category == "team_rage":
|
||||
score += 10
|
||||
if "TEAM_RAGE" not in reasons:
|
||||
reasons.append("TEAM_RAGE")
|
||||
elif category == "fail":
|
||||
score += 8
|
||||
if "FAIL" not in reasons:
|
||||
reasons.append("FAIL")
|
||||
else:
|
||||
score += 5
|
||||
if "FRUSTRATION" not in reasons:
|
||||
reasons.append("FRUSTRATION")
|
||||
break
|
||||
|
||||
if score >= 5: # Mínimo score significativo
|
||||
rage_moments.append(
|
||||
{
|
||||
"start": seg["start"],
|
||||
"end": seg["end"],
|
||||
"score": score,
|
||||
"text": seg["text"][:70],
|
||||
"reasons": reasons,
|
||||
}
|
||||
)
|
||||
|
||||
print(f"\nMomentos de rage detectados: {len(rage_moments)}")
|
||||
|
||||
# Ordenar por score
|
||||
rage_moments.sort(key=lambda x: -x["score"])
|
||||
|
||||
# Crear clips extendidos
|
||||
clips = []
|
||||
for moment in rage_moments[:25]: # Top 25
|
||||
start = max(skip_intro, int(moment["start"]) - 10)
|
||||
end = min(max_duration, int(moment["end"]) + 20)
|
||||
|
||||
if end - start >= 12:
|
||||
clips.append(
|
||||
{
|
||||
"start": start,
|
||||
"end": end,
|
||||
"score": moment["score"],
|
||||
"reasons": moment["reasons"],
|
||||
"text": moment["text"],
|
||||
}
|
||||
)
|
||||
|
||||
# Eliminar solapamientos
|
||||
clips.sort(key=lambda x: x["start"])
|
||||
filtered = []
|
||||
|
||||
for clip in clips:
|
||||
if not filtered:
|
||||
filtered.append(clip)
|
||||
else:
|
||||
last = filtered[-1]
|
||||
if clip["start"] <= last["end"] + 3:
|
||||
# Fusionar
|
||||
last["end"] = max(last["end"], clip["end"])
|
||||
last["score"] = max(last["score"], clip["score"])
|
||||
last["reasons"] = list(set(last["reasons"] + clip["reasons"]))
|
||||
else:
|
||||
filtered.append(clip)
|
||||
|
||||
# Tomar top 15
|
||||
filtered.sort(key=lambda x: -x["score"])
|
||||
final = filtered[:15]
|
||||
final.sort(key=lambda x: x["start"])
|
||||
|
||||
print(f"\nClips sin solapar: {len(final)}")
|
||||
print(f"\nTop momentos RAGE:")
|
||||
for i, clip in enumerate(final, 1):
|
||||
mins = int(clip["start"]) // 60
|
||||
secs = int(clip["start"]) % 60
|
||||
dur = clip["end"] - clip["start"]
|
||||
print(
|
||||
f"{i:2d}. {mins:02d}:{secs:02d} - {dur}s [Score: {clip['score']:2d}] "
|
||||
f"{'/'.join(clip['reasons'])}"
|
||||
)
|
||||
|
||||
total_dur = sum(c["end"] - c["start"] for c in final)
|
||||
print(
|
||||
f"\nTotal: {len(final)} clips, {total_dur}s ({total_dur // 60}m {total_dur % 60}s)"
|
||||
)
|
||||
|
||||
return [[c["start"], c["end"]] for c in final]
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
|
||||
highlights = detect_rage_highlights(
|
||||
"transcripcion_medium.json", "elxokas_chat.json"
|
||||
)
|
||||
|
||||
with open("HIGHLIGHTS_RAGE.json", "w") as f:
|
||||
json.dump(highlights, f)
|
||||
|
||||
print(f"\nGuardado en HIGHLIGHTS_RAGE.json")
|
||||
Reference in New Issue
Block a user