- 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
88 lines
2.8 KiB
Python
88 lines
2.8 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Genera video resumen usando ffmpeg directamente.
|
|
Más rápido y compatible que moviepy.
|
|
"""
|
|
import json
|
|
import argparse
|
|
import subprocess
|
|
import logging
|
|
|
|
logging.basicConfig(level=logging.INFO)
|
|
|
|
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...")
|
|
|
|
# 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)
|
|
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 clips:
|
|
print("No se pudo crear ningún clip")
|
|
return
|
|
|
|
# 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__":
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("--video", required=True, help="Video file")
|
|
parser.add_argument("--highlights", required=True, help="Highlights JSON")
|
|
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_ffmpeg(args.video, args.highlights, args.output, args.padding)
|