- 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
180 lines
5.2 KiB
Python
180 lines
5.2 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
SMART GAME DETECTOR
|
|
Combina análisis de transcripción + reglas temporales para detectar gameplay real.
|
|
"""
|
|
|
|
import json
|
|
import re
|
|
import numpy as np
|
|
|
|
|
|
def detect_games_smart(trans_file):
|
|
"""Detecta juegos considerando patrones de League of Legends."""
|
|
|
|
with open(trans_file, "r") as f:
|
|
trans = json.load(f)
|
|
|
|
print("=" * 60)
|
|
print("SMART GAME DETECTOR")
|
|
print("=" * 60)
|
|
|
|
# Buscar inicios de juego
|
|
game_starts = []
|
|
|
|
for i, seg in enumerate(trans["segments"]):
|
|
text = seg["text"].lower()
|
|
|
|
# Inicio típico de partida LoL
|
|
if any(
|
|
phrase in text
|
|
for phrase in [
|
|
"bienvenidos",
|
|
"invocadores",
|
|
"welcome",
|
|
"empezamos",
|
|
"vamos allá",
|
|
"arrancamos",
|
|
]
|
|
):
|
|
if seg["start"] > 120: # Después de intro
|
|
game_starts.append(seg["start"])
|
|
print(
|
|
f"Posible inicio de juego en {seg['start'] // 60}m {seg['start'] % 60:.0f}s: {text[:50]}..."
|
|
)
|
|
|
|
# También buscar por cambios de personaje/campeón
|
|
champ_mentions = {}
|
|
for seg in trans["segments"]:
|
|
text = seg["text"].lower()
|
|
# Buscar menciones de campeones
|
|
champs = [
|
|
"warwick",
|
|
"diana",
|
|
"mundo",
|
|
"yasuo",
|
|
"zed",
|
|
"lee sin",
|
|
"jhin",
|
|
"lucian",
|
|
]
|
|
for champ in champs:
|
|
if champ in text:
|
|
if champ not in champ_mentions:
|
|
champ_mentions[champ] = []
|
|
champ_mentions[champ].append(seg["start"])
|
|
|
|
print(f"\nMenciones de campeones:")
|
|
for champ, times in champ_mentions.items():
|
|
if (
|
|
len(times) > 5
|
|
): # Mencionado varias veces = probablemente jugando ese campeón
|
|
first = min(times)
|
|
last = max(times)
|
|
print(
|
|
f" {champ}: {len(times)} veces, desde {first // 60}m hasta {last // 60}m"
|
|
)
|
|
|
|
return game_starts, champ_mentions
|
|
|
|
|
|
def extract_best_moments(trans_file, min_timestamp=455):
|
|
"""Extrae los mejores momentos considerando contexto."""
|
|
|
|
with open(trans_file, "r") as f:
|
|
trans = json.load(f)
|
|
|
|
# Dividir en bloques de 30 minutos (aprox duración de partida LoL)
|
|
block_size = 30 * 60 # 30 minutos
|
|
duration = trans["segments"][-1]["end"]
|
|
|
|
print(f"\nAnalizando {duration / 60:.0f} minutos en bloques de 30 min...")
|
|
|
|
all_moments = []
|
|
|
|
for block_start in range(int(min_timestamp), int(duration), block_size):
|
|
block_end = min(block_start + block_size, int(duration))
|
|
|
|
# Buscar mejor momento en este bloque
|
|
best_moment = None
|
|
best_score = 0
|
|
|
|
for seg in trans["segments"]:
|
|
if seg["start"] < block_start or seg["end"] > block_end:
|
|
continue
|
|
|
|
text = seg["text"].lower()
|
|
score = 0
|
|
reasons = []
|
|
|
|
# Rage
|
|
if re.search(r"\bputa\w*", text):
|
|
score += 10
|
|
reasons.append("RAGE")
|
|
elif re.search(r"\bmierda\b", text):
|
|
score += 7
|
|
reasons.append("RAGE")
|
|
|
|
# Acción de juego
|
|
if any(
|
|
word in text
|
|
for word in ["me mataron", "me mori", "kill", "mate", "muere"]
|
|
):
|
|
score += 8
|
|
reasons.append("KILL")
|
|
|
|
if any(word in text for word in ["ulti", "flash", "teamfight", "pelea"]):
|
|
score += 5
|
|
reasons.append("SKILL")
|
|
|
|
# Frustración
|
|
if any(word in text for word in ["joder", "hostia", "no puede ser"]):
|
|
score += 4
|
|
reasons.append("FRUSTRATION")
|
|
|
|
if score > best_score:
|
|
best_score = score
|
|
best_moment = {
|
|
"time": seg["start"],
|
|
"score": score,
|
|
"text": seg["text"][:60],
|
|
"reasons": reasons,
|
|
"block": block_start,
|
|
}
|
|
|
|
if best_moment and best_score >= 8:
|
|
all_moments.append(best_moment)
|
|
mins = int(best_moment["time"]) // 60
|
|
secs = int(best_moment["time"]) % 60
|
|
print(
|
|
f" Bloque {len(all_moments)}: {mins:02d}:{secs:02d} [Score {best_score}] {'/'.join(reasons)}"
|
|
)
|
|
|
|
return all_moments
|
|
|
|
|
|
if __name__ == "__main__":
|
|
# Detectar estructura
|
|
game_starts, champs = detect_games_smart("transcripcion_rage.json")
|
|
|
|
# Extraer mejores momentos
|
|
moments = extract_best_moments("transcripcion_rage.json")
|
|
|
|
print(f"\nTotal momentos encontrados: {len(moments)}")
|
|
|
|
# Crear clips
|
|
clips = []
|
|
for m in moments[:8]: # Máximo 8
|
|
start = max(455, int(m["time"]) - 12)
|
|
end = min(8237, int(m["time"]) + 20)
|
|
clips.append([start, end])
|
|
|
|
# Guardar
|
|
with open("highlights_smart.json", "w") as f:
|
|
json.dump(clips, f)
|
|
|
|
print(f"\nClips guardados: {len(clips)}")
|
|
for i, (s, e) in enumerate(clips, 1):
|
|
mins, secs = divmod(s, 60)
|
|
print(f"{i}. {mins:02d}:{secs:02d} - {e - s}s")
|