Communitygithub.com

add-intro-outro

Agrega las cortinillas de introducción y cierre de una marca a un video terminado (con estabilización vid.stab opcional para grabaciones de mano), eligiendo el par 16:9 o 9:16 según la orientación del video, con un fundido corto de la intro al video y del video al outro. También crea una versión 16:9 de un video vertical con fondo desenfocado.

¿Qué es add-intro-outro?

Este skill automatiza la incorporación de cortinillas de marca (intro y outro) a videos finales, normalizando formatos y aplicando fundidos cruzados tanto de video como de audio. Soporta videos en orientación horizontal (16:9) y vertical (9:16), con detección automática de orientación mediante ffprobe para manejar correctamente la rotación de videos de teléfonos. Además, incluye la opción de estabilización vid.stab para grabaciones de mano y puede generar una versión 16:9 de un video vertical con fondo desenfocado y oscurecido, ideal para YouTube. Está diseñado para ejecutarse en Modal debido al alto costo computacional del re-encode completo, y utiliza preferencias configurables para las URLs de las cortinillas y la duración del fundido. Las cortinillas deben ser proporcionadas por el usuario (el plugin no incluye activos de marca) y pueden generarse con un script Pillow más un jingle, que se encuentra mediante el tag 'logo', 'sting' o 'intro'.

Compatible con✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/danielrosehill/Remote-Video-Editing/tree/HEAD/skills/add-intro-outro

Preguntar en tu IA favorita

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

Documentación

Agregar la introducción y el cierre

Las cortinillas son MP4 cortos con su propio jingle, un par por orientación, listados en las preferencias. Este skill normaliza todo a un formato, une la introducción, el video y el cierre con fundidos cruzados cortos (video y audio), y renderiza el resultado.

Preferencias

remote-video-editing/preferences.json (orden de búsqueda como en clean-voice-sidon):

ClaveSignificado
stings{"intro_16x9": url, "outro_16x9": url, "intro_9x16": url, "outro_9x16": url}; URLs o rutas locales
sting_fade_sDuración del fundido cruzado, por defecto 0.5
render_notesDónde ejecutar codificaciones largas (por ejemplo, un servidor en lugar de una laptop). Síguelas.

Si stings no está configurado, pide los archivos. El plugin no incluye ningún activo de marca.

Orientación

Lee la orientación mostrada, no el tamaño codificado: los teléfonos almacenan video vertical como 1920x1080 con una etiqueta de rotación. Verifica con ffprobe -v error -select_streams v:0 -show_entries stream=width,height:stream_side_data=rotation -of compact IN. Una rotación de 90 o -90 intercambia ancho y alto. ffmpeg aplica la rotación automáticamente al decodificar.

  • Video vertical (9:16): usa intro_9x16 / outro_9x16, lienzo 1080x1920.
  • Horizontal: usa el par 16:9, lienzo 1920x1080.
  • Corte 16:9 de un video vertical (para el feed principal de YouTube): lienzo 1920x1080, el video escalado a 1080 de alto en el centro, sobre una copia desenfocada, oscurecida y ampliada de sí mismo; usa las cortinillas 16:9. La cadena [v1] a continuación se convierte en:
    [1:v]fps=30,split[a][b];
    [a]scale=1920:1080:force_original_aspect_ratio=increase,crop=1920:1080,scale=480:270,boxblur=20:2,scale=1920:1080,eq=brightness=-0.06:saturation=0.9[bg];
    [b]scale=-2:1080[fg];[bg][fg]overlay=(W-w)/2:0,setsar=1,format=yuv420p[v1]
    
    Pruébalo en un corte de 8 segundos (-ss 60 -t 8) y muestra un fotograma antes de renderizar todo.

Renderizar

W:H es el lienzo, F el fundido (0.5), DI la duración de la introducción, DV la duración del video (ffprobe format=duration). Desplazamientos: primer fundido en DI-F; segundo en DI+DV-2*F.

ffmpeg -y -i intro.mp4 -i main.mp4 -i outro.mp4 -filter_complex "
 [0:v]fps=30,scale=W:H,setsar=1,format=yuv420p[v0];
 [1:v]fps=30,scale=W:H:force_original_aspect_ratio=decrease,pad=W:H:(ow-iw)/2:(oh-ih)/2,setsar=1,format=yuv420p[v1];
 [2:v]fps=30,scale=W:H,setsar=1,format=yuv420p[v2];
 [0:a]aresample=48000,aformat=channel_layouts=stereo[a0];
 [1:a]aresample=48000,aformat=channel_layouts=stereo[a1];
 [2:a]aresample=48000,aformat=channel_layouts=stereo[a2];
 [v0][v1]xfade=transition=fade:duration=F:offset=DI-F[v01];
 [v01][v2]xfade=transition=fade:duration=F:offset=DI+DV-2*F[v];
 [a0][a1]acrossfade=d=F[a01];[a01][a2]acrossfade=d=F[a]" \
 -map "[v]" -map "[a]" -c:v libx264 -preset medium -crf 20 -maxrate 10M -bufsize 20M -c:a aac -b:a 192k -movflags +faststart out.mp4
  • Varios clips fuente: únelos primero (el mismo patrón de filtro, o el demuxer concat si comparten códec), luego trata el resultado como main.mp4.
  • Esto es un re-encode completo: minutos de todos los núcleos para un video de 10 minutos en 1080p. Ejecútalo en Modal, no localmente ni en un servidor doméstico: coloca los argumentos después de las entradas (desde -filter_complex hasta +faststart) uno por línea en render.args, luego $MODAL run "${CLAUDE_PLUGIN_ROOT}/scripts/ffmpeg_modal.py" --inputs intro.mp4,main.mp4,outro.mp4 --args-file render.args --out out.mp4 (modal_command y run_notes de las preferencias indican dónde se ejecuta Modal). Une varios clips en el mismo grafo (filtro concat) en lugar de hacer una pasada separada. Elimina la carpeta del trabajo en el volumen video-editing-work después.
  • xfade necesita que ambas entradas estén en la misma base de tiempo: pon fps=30,settb=1/30 en cada rama de video (incluyendo después de un concat), o ffmpeg falla con "First input link main timebase (1/30) do not match".
  • Tasa de bits: mantén el límite (-crf 20 -maxrate 10M -bufsize 20M). CRF 18 simple en material de teléfono ruidoso resultó en 24 Mbps, unos 2 GB para 11 minutos (2026-11-13). YouTube vuelve a codificar de todos modos y sugiere 8-12 Mbps para subidas en 1080p.
  • Verifica: la duración de salida es aproximadamente DI + DV + DO - 2*F, y revisa los fotogramas en DI-F/2 (mitad del fundido), la mitad y el final.

Material de mano: estabilizar en el mismo render

Los videos de teléfono tomados a mano se benefician de una estabilización ligera (el usuario, 2026-11-13, después de la primera actualización del fin de semana de Hebrish salió sin ella). Usa vid.stab de ffmpeg (libvidstab; Debian's ffmpeg, que la imagen de Modal instala, lo tiene; verifica con ffmpeg -filters | grep vidstab). Dos pasadas, ambas en Modal:

  1. Detectar (rápido, solo análisis, escribe un archivo de transformaciones), por clip fuente: ffmpeg -i main.mp4 -vf vidstabdetect=shakiness=5:accuracy=15:result=main.trf -f null - Ejecútalo como su propio trabajo de ffmpeg_modal.py (args -vf / vidstabdetect=...:result=/work/<job>/main.trf / -f / null, salida -), o agrega un paso de detección al script. El .trf debe estar junto a la entrada en el volumen.
  2. Transformar dentro del render principal, lo primero en la rama de video de ese clip, antes de la gradación y el escalado: vidstabtransform=input=main.trf:smoothing=20:zoom=2:optzoom=0,unsharp=5:5:0.4 smoothing alrededor de 15-30 (fotogramas) mantiene el movimiento natural; un zoom=2 fijo (porcentaje) oculta los bordes móviles sin el bombeo que causa optzoom=1 en un rostro parlante. La ligera nitidez compensa la suavidad del remuestreo.

Pruébalo en un corte de 8 segundos primero y compara una imagen fija y un clip corto con el usuario antes del render completo. Si falta libvidstab, deshake es un fallback de una pasada (más débil). No se necesitan estabilizadores de IA para esto.

Crear cortinillas

Las cortinillas en uso se renderizaron a partir de los SVG de la marca con un pequeño script de Pillow más un jingle generado. Encuéntralo con find-script (etiquetas logo, sting, intro), y no regeneres el logo con un modelo de video: los modelos de video distorsionan las formas de las letras.

Skills relacionados