Communitygithub.com

LiliLIN0324/imgseq-cover-video-skill

Construye un video de portada/teaser en mp4 a partir de una carpeta de imágenes fijas numeradas (01.jpg, 02.jpg, ... hasta 200 y más). Utilízalo cuando el usuario pida convertir una carpeta de imágenes numeradas en video, crear un carrete de imágenes o presentación, agregar transiciones suaves entre imágenes o exportar un video 'cover' desde jpgs en una carpeta, ignorando imágenes no numeradas como logo.jpg, discord.jpg o cover.mp4.

¿Qué es imgseq-cover-video-skill?

Este skill permite transformar una carpeta de imágenes fijas con nombres numéricos (p. ej., 01.jpg, 02.jpg, 200.jpg) en un vídeo de portada o teaser en formato mp4 con codec H.264. Escanea el directorio, selecciona solo archivos cuyo nombre base sea puramente numérico (ignorando logo.jpg, discord.jpg, cover.mp4, etc.), los ordena por valor entero (no lexicográfico) y los ensambla en un vídeo silencioso, ya sea con cortes directos o con transiciones suaves de encadenamiento (crossfade), que es la opción predeterminada. Soporta parámetros como duración por imagen (`--seconds`), duración de transición (`--transition-seconds`), fps, resolución (1920x1080 por defecto) y ajuste de recorte (`--fit pad` o `--fill`). Está pensado para plataformas que ejecutan scripts Python con ffmpeg, como Claude Code o Cursor, e incluye lógica robusta para evitar sobreescrituras, verificar el resultado y manejar restricciones de memoria y sistema operativo (Windows incluyendo DSH).

Compatible con~Claude Code~Codex CLI~Cursor
npx skills add LiliLIN0324/imgseq-cover-video-skill

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

叠帧 · Imágenes fijas numeradas → Vídeo de portada

Resumen

Escanea una carpeta, conserva solo los archivos cuyo nombre base es puramente un número (01.jpg, 200.jpg), reprodúcelos en orden numérico y codifica un mp4 H.264. Entre imágenes se aplica un corte directo (--transition none) o un encadenamiento suave (--transition fade, el valor predeterminado). Las imágenes no numeradas (logo, discord, …) y los vídeos existentes se ignoran.

Procedimiento

  1. Inspecciona la carpeta primero. Enumera los archivos y obtén las dimensiones de una imagen con ffprobe. Anota cuántas imágenes fijas numeradas existen y si las relaciones de aspecto son mixtas.
  2. Realiza una copia de seguridad de cualquier salida existente. Si <carpeta>/cover.mp4 ya existe, renómbralo a cover.prev-YYYYMMDD.mp4 antes de renderizar. Nunca sobrescribas silenciosamente una renderización anterior del usuario.
  3. Renderiza con el script incluido:
python "<directorio-del-skill>/scripts/imgseq2mp4.py" --dir "<carpeta>" --out cover.mp4

Valores predeterminados: 0.8 s por imagen con un encadenamiento suave fade de 0.2 s, 30 fps, 1920x1080, relleno con letterbox, CRF 18, sin audio, +faststart.

  1. Verifica, no asumas. Obtén la duración/cuadros, confirma que no haya cuadros negros y extrae el último cuadro para compararlo con la última imagen fuente:
ffprobe -v error -show_entries format=duration -show_entries stream=nb_frames -of default=nw=1 cover.mp4
ffmpeg -i cover.mp4 -vf blackdetect=d=0.05:pix_th=0.10 -an -f null -
ffmpeg -y -sseof -0.05 -i cover.mp4 -frames:v 1 frame_last.png

Cuando las transiciones están activadas, también toma un cuadro dentro de la primera ventana de transición y verifica que sea una mezcla (más cercana a la imagen 2 que un corte directo, pero aún mediblemente diferente de ambas fuentes).

  1. Informa el recuento de imágenes, las imágenes ignoradas, la duración total, la ruta de salida y el tamaño.

Ritmo

Longitud total = n × segundos − (n−1) × segundos_de_transición. El paso de cada imagen en pantalla es segundos − segundos_de_transición; ese paso, no --seconds, es lo que percibe el espectador.

Paso por imagenComando20 imgs44 imgs200 imgs
0.35 s--seconds 0.5 --transition-seconds 0.15~8 s~18 s~75 s
0.45 s--seconds 0.65 --transition-seconds 0.2~9 s~22 s~95 s
0.60 s (predeterminado)--seconds 0.8 --transition-seconds 0.2~12 s~27 s~120 s
0.80 s--seconds 1.0 --transition-seconds 0.2~16 s~34 s~150 s

Los cortes directos usan --transition none --seconds <paso>.

Muévete una fila a la vez cuando el usuario pida más rápido o más lento. Mantén --transition-seconds entre 0.15 y 0.2; una duración más larga comienza a leerse como una presentación en lugar de un encadenamiento suave.

Reglas

  • Solo encadenamiento suave. No uses transiciones de diapositiva, cortinilla ni otras transiciones push; fueron rechazadas como dirección.
  • Selecciona con la expresión regular ^\d+\.(jpe?g|png|webp)$ — el nombre del archivo debe ser solo dígitos. Esto es lo que excluye logo.jpg, discord.jpg, cover.jpg.
  • Ordena por valor entero, no lexicográficamente (2.jpg antes que 10.jpg, 99.jpg antes que 100.jpg). Los saltos en la numeración no son un problema; los números faltantes no son errores.
  • Usa --fit pad (predeterminado) para que todo el cuadro permanezca visible. Solo usa --fit fill cuando el usuario quiera explícitamente recortar de borde a borde.
  • La salida es silenciosa. No agregues música a menos que el usuario proporcione una pista.
  • Mantén los colores intactos. Los JPEG son de rango completo; si los codificas como H.264 de rango completo sin etiquetar, la mayoría de los reproductores decodifican como rango limitado y el resultado se ve más brillante y deslavado (+10 niveles). El script convierte a bt709 de rango limitado y lo etiqueta — no "simplifiques" esa cadena.
  • El script se niega a sobrescribir --out sin --force; resuelve haciendo una copia de seguridad, no forzando a ciegas.

Notas sobre la máquina

  • ffmpeg no está en el PATH. El script prefiere un ffmpeg.exe real (~/.dsh/tools/ffmpeg/**/ffmpeg.exe, luego copias bajo C:/ o D:/ffmpeg) antes que cualquier envoltorio .cmd, porque el envoltorio enruta a través de cmd.exe y limita la línea de comandos a ~8k caracteres. Sobrescribe con FFMPEG=/ruta/a/ffmpeg.
  • Esta compilación carece de -filter_complex_script; pasa el grafo xfade en línea mediante -filter_complex (el script ya lo hace).
  • Las transiciones se renderizan en grupos de --chunk (predeterminado 6) y luego se fusionan, por lo que hay como máximo 6 decodificadores abiertos a la vez. Una sola pasada xfade de 44 entradas agotó la RAM en una máquina de 16 GB (~2.4 GB libres) y falló con Cannot allocate memory; no eleves --chunk por encima de ~8 aquí. El agrupamiento es recursivo, por lo que 200 imágenes se fusionan en tres etapas sin OOM.
  • Los archivos de etapa intermedia se codifican con CRF 14 / veryfast y se descartan; solo la pasada final usa --crf / medium.
  • Los cuadros intermedios necesitan un directorio con permiso de escritura. Los resultados de tempfile.mkdtemp() pueden ser inaccesibles bajo entornos restringidos (observado en Windows + DSH: ffmpeg obtuvo Permission denied y os.listdir lanzó WinError 5). Por lo tanto, el script crea un directorio simple, verifica que sea escribible y recurre a $IMGSEQ_WORKDIR → temp del sistema → <directorio-de-salida>/.imgseq-work.

Recursos

  • scripts/imgseq2mp4.py — selección, ordenamiento numérico, renderizado con corte directo o encadenamiento suave, resumen amigable para verificación.

Skills relacionados