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:
renato97
2026-02-19 17:38:14 +00:00
parent c1c66a7d9a
commit 00180d0b1c
45 changed files with 10636 additions and 260 deletions

View File

@@ -1,55 +1,79 @@
#!/usr/bin/env python3
"""
Genera video resumen usando ffmpeg directamente.
Más rápido y compatible que moviepy.
"""
import json
import argparse
from moviepy.editor import VideoFileClip, concatenate_videoclips
import subprocess
import logging
logging.basicConfig(level=logging.INFO)
def create_summary(video_file, highlights_file, output_file, padding=5):
"""Crea video resumen con los highlights"""
def create_summary_ffmpeg(video_file, highlights_file, output_file, padding=5):
"""Crea video resumen usando ffmpeg"""
# Cargar highlights
with open(highlights_file, 'r') as f:
highlights = json.load(f)
if not highlights:
print("No hay highlights")
return
# Filtrar highlights con duración mínima
highlights = [(s, e) for s, e in highlights if e - s >= 5]
print(f"Creando video con {len(highlights)} highlights...")
clip = VideoFileClip(video_file)
duration = clip.duration
highlight_clips = []
# Obtener duración del video
result = subprocess.run(
["ffprobe", "-v", "error", "-show_entries", "format=duration",
"-of", "default=noprint_wrappers=1:nokey=1", video_file],
capture_output=True, text=True
)
duration = float(result.stdout.strip()) if result.stdout.strip() else 3600
# Crear lista de clips con padding
clips = []
for start, end in highlights:
start_pad = max(0, start - padding)
end_pad = min(duration, end + padding)
highlight_clip = clip.subclip(start_pad, end_pad)
highlight_clips.append(highlight_clip)
clips.append((start_pad, end_pad))
print(f" Clip: {start_pad:.1f}s - {end_pad:.1f}s (duración: {end_pad-start_pad:.1f}s)")
if not highlight_clips:
if not clips:
print("No se pudo crear ningún clip")
return
print(f"Exportando video ({len(highlight_clips)} clips, {sum(c.duration for c in highlight_clips):.1f}s total)...")
final_clip = concatenate_videoclips(highlight_clips, method="compose")
final_clip.write_videofile(
output_file,
codec='libx264',
audio_codec='aac',
fps=24,
verbose=False,
logger=None
)
# Crear archivo de concat para ffmpeg
concat_file = "concat_list.txt"
total_duration = 0
with open(concat_file, 'w') as f:
for start, end in clips:
clip_duration = end - start
total_duration += clip_duration
# Formato: file 'video.mp4', start, duration
f.write(f"file '{video_file}'\n")
f.write(f"inpoint {start}\n")
f.write(f"outpoint {end}\n")
print(f"Exportando video ({len(clips)} clips, {total_duration:.1f}s total)...")
# Usar ffmpeg con concat demuxer
cmd = [
"ffmpeg", "-f", "concat", "-safe", "0",
"-i", concat_file,
"-c", "copy", # Copiar streams sin recodificar (muy rápido)
"-y", output_file
]
subprocess.run(cmd, capture_output=True)
# Limpiar
subprocess.run(["rm", "-f", concat_file])
print(f"¡Listo! Video guardado en: {output_file}")
if __name__ == "__main__":
@@ -59,5 +83,5 @@ if __name__ == "__main__":
parser.add_argument("--output", required=True, help="Output video")
parser.add_argument("--padding", type=int, default=5, help="Padding seconds")
args = parser.parse_args()
create_summary(args.video, args.highlights, args.output, args.padding)
create_summary_ffmpeg(args.video, args.highlights, args.output, args.padding)