ccvideo — Vídeos promocionales de producto al estilo Claude
Estás produciendo un vídeo promocional corto (20–45 s, 1920×1080 @ 30 fps) en el lenguaje visual de los vídeos de lanzamiento de Claude de Anthropic: un lienzo terracota cálido, una única ventana de terminal macOS ejecutando una sesión de Claude Code, texto que se escribe y fluye en pantalla, breves movimientos de cámara entre encuadres fijos, tarjetas de título con serifa.
Requisitos previos
- Debe existir un proyecto Remotion. Si no, crea uno:
npx create-video@latest --yes --blank --no-tailwind .luegonpm i. - Paquetes (instala con
npx remotion add <pkg>para que las versiones coincidan):@remotion/google-fonts,@remotion/transitions,zod(declara zod explícitamente — la librería lo importa directamente; no confíes en que sea una dependencia transitiva). - La biblioteca de componentes debe existir en
src/ccvideo/. Si no es así, copia todos los archivos del directoriotemplates/de este skill ensrc/ccvideo/. No reescribas estos componentes desde cero. - Las herramientas de captura/verificación deben existir en
scripts/en la raíz del proyecto. Si no es así, copia el directorioscripts/de este skill (incluyendoscripts/lib/) allí. Todos los scripts resuelvencaptures/con respecto al desde el que los ejecutes, así que ejecútalos siempre desde la raíz del proyecto.
Verdad fundamental (reglas de contenido no negociables)
El contenido del vídeo nunca se escribe a mano en los componentes de escena. Cada hecho mostrado — números, rutas, endpoints, salida de comandos, recuentos de líneas — debe provenir de una captura de algo que realmente se ejecutó:
- Cada vídeo tiene un directorio
captures/<nombre>/que contiene los artefactos en bruto (respuestas de API, eventos de sesión extraídos) más unprops.jsonconstruido a partir de ellos de forma determinista.props.jsones la única fuente de verdad que la composición renderiza. - Captura primero. Antes de hacer el vídeo, ejecuta la herramienta real:
node scripts/capture-xapi-cli.mjs— datos en vivo de X a través de la CLI xapi (npx xapi-to, clave en~/.xapi/config.json; el skillxapien.agents/skills/xapi/documenta todas sus capacidades).node scripts/capture-x-user.mjs— variante oficial de la API de X (necesitaX_BEARER_TOKEN;--sampleescribe datos de marcador de posición conraw-meta.jsonmarcadosample: true— nunca publiques una captura de muestra).node scripts/transcript-to-props.mjs <session.jsonl> --prompt-match <str> --out captures/<nombre>— reproduce un turno de sesión real de Claude Code (las transcripciones viven en~/.claude/projects/<slug-proyecto>/*.jsonl).- ¿Nueva fuente de datos? Escribe un nuevo script de captura siguiendo el mismo patrón:
obtener la realidad → guardar en bruto → construir props mediante un constructor
determinista compartido en
scripts/lib/.
- Verifica antes de publicar:
node scripts/verify-props.mjs captures/<nombre>reconstruye props a partir de los artefactos en bruto y falla ante cualquier edición manual. Corrige volviendo a capturar, nunca editandoprops.json. - Límite de reproducción honesta: el ritmo es una actuación (velocidad de escritura, tiempo
de spinner), pero la capacidad debe ser real — el vídeo solo puede mostrar lo que la
ejecución capturada realmente hizo. Esto se extiende al cromo: los hechos del encabezado de sesión
(versión de Claude Code, directorio de trabajo) provienen de la captura (
claude --version, directorio de trabajo real) o se omite el encabezado; el contador de tokens del spinner renderiza solo cuando la captura proporciona un valorthinkingTokensreal (de lo contrario solo segundos). Las capturas de muestra fallanverify-propsdirectamente (--allow-sampleexiste solo para pruebas de tubería). - Las capturas buscan ser seguras para commit, con defensa en profundidad — no una garantía:
transcript-to-propspersiste solo las entradas que el vídeo realmente usa (las líneas mostradas de los eventos seleccionados + recuentos, una salida de comando truncada, las líneas de viñetas del resumen), limpia cadenas con forma de secreto (claves de API, tokens Bearer, credenciales en URL, campos de contraseña en entorno/JSON, claves privadas), y reescribe tanto las rutas de inicio normales como las aplanadas por slug a~— todo antes de que se construyan las props, por lo que las props, el vídeo y el raw archivado ven contenido redactado idéntico. Las listas de patrones nunca pueden ser completas: siempre revisa una captura antes de hacer commit, y trata cualquier advertencia de redacción como una señal de alto.
Flujo de trabajo
- Captura primero (consulta Verdad fundamental): produce
captures/<nombre>/props.jsona partir de una ejecución real. - Hoja de ritmos a partir de la captura. El texto de presentación (títulos de tarjeta, palabra de pensamiento) vive en las constantes/banderas del script de captura — elige el prompt, el beat de código, la salida de la ejecución, las viñetas del resumen. Apunta a el arco clásico: código → creado → ejecutado+salida → resumen.
- Componer: registra un
<Composition>ensrc/Root.tsxusandoGroundedVideodesrc/ccvideoconschema={groundedVideoSchema},defaultPropsimportado delprops.jsonde la captura, ycalculateMetadataderivando la duración mediantegroundedVideoDuration— las duraciones siguen el contenido automáticamente. Trabajo de escena personalizado más allá del arco estándar: construye con los primitivos de la biblioteca, mismas reglas. - Verifica con fotogramas fijos antes de declarar terminado. Renderiza un fotograma fijo por beat:
npx remotion still <CompId> --frame=<n> --scale=0.5 out.pngy míralos. Comprueba: nada recortado por la ventana de terminal (una advertencia de desbordamiento[ccvideo]en la salida de render significa recortar beats), el ritmo se siente sin prisa, los colores coinciden con la paleta. - Ejecuta
node scripts/verify-props.mjs captures/<nombre>, luego previsualiza connpx remotion studio --no-open; render final connpx remotion render <CompId> out/<CompId>.mp4(añade--props=captures/<nombre>/props.jsonpara renderizar una captura diferente sin tocar el código; añade--scale=2para un master 4K como las demos oficiales — las composiciones se mantienen en 1920×1080 @ 30 fps en el código).
Dos temas
Elige por producto, ambos comparten el terracota de marca #D97656/#D97757:
- Terracota (por defecto) — lienzo cálido, sesión REPL de Claude Code. Para
historias de agentes/flujo de trabajo de IA. Componentes:
GroundedVideo/DataSession. - Oscuro (la gramática de demo CLI
ant) — lienzo casi negro#0B0B0B, terminal negro cálido#181716separado solo por un borde sutil, prompt de shell▶ ~/dir >(flecha#8B92C9, chevron#5FA97B), serifa crema#D6D4CF. La estructura está dividida en capítulos: tarjeta con marca de agua pixel-logo → [tarjeta intersticial (kicker mono + divisor fino + claim serifa) → beat de shell fresco (escribe comando real, salida real aparece gradualmente, prompt inactivo vuelve)] por capítulo → outro con marca de agua. Para productos CLI/herramientas de desarrollador. Componentes:DarkVideo/ShellBeat/InterstitialCard/WordmarkCard, paletadarkentheme.ts, esquemadarkVideoSchema(construido a partir de capturas como el tema claro — p.ej.props-dark.jsonescrito porcapture-xapi-cli.mjs, verificado porverify-props.mjs).
El aspecto (reglas de estilo no negociables)
- Lienzo
#CC7D5D, terminal#2B2C36, barra de título#3A3634. Texto del cuerpo#E3E4EB, atenuado#9899A1, comentarios#6C6E6A, números de línea#83848C. Acentos: lila#B8B9F2(rutas, código en línea, cadenas), verde azulado#85BEC5(palabras clave), dorado#F2C43D(flechas de estado). Todo definido ensrc/ccvideo/theme.ts— importa, nunca codifiques. - Fuentes: JetBrains Mono para todo lo del terminal, Source Serif 4 para tarjetas
de título. Cargadas en
theme.tsmediante@remotion/google-fonts, con Noto Sans SC ya añadido como fallback CJK para ambas pilas — los prompts en chino se renderizan sin problemas. - Ventana de terminal 1560×950 centrada (985 cuando se muestra un
headerde sesión; tema oscuro 1860×1010), radio 14 px, sombra suave profunda, tres semáforos, texto de barra de título mono que refleja la tarea, p.ej.dev — · Implement X — claude — 106×31. - La sesión de Claude Code debe verse real: fila de entrada
>encima de una barra de estado dorada⏵⏵ auto mode on (shift+tab to cycle) · esc to interrupt(ambas siempre visibles, fijadas en la parte inferior); un spinner✻ Cogitating…en una ranura de altura fija justo encima de la fila de entrada; viñetas de resultado de herramienta●; un bloque de código numerado que termina en… +N lines (ctrl+o to expand); un resumen en negritaWhat it doescon viñetas-. - Cámara: nunca zoom sostenido o paneo en escenas de terminal — la escala fraccionaria lenta
hace que el texto mono pequeño se desplace y nade visiblemente. El único movimiento de cámara
permitido es
<CutZoom>: movimientos breves y fuertemente easing (~0.6 s) entre encuadres fijos — acercamiento a contenido denso, mantener, alejarse para el remate. El texto puede estar a media escala solo durante un movimiento rápido deliberado, nunca durante segundos. Mantén el mismooriginen el alejamiento que en el acercamiento para que no se lea como un deslizamiento lateral.DataSessionaplica esto automáticamente alrededor del beatrun.<SlowZoom>sigue siendo solo para tarjetas de título. - Cromo de autenticidad de sesión (todo impulsado por esquema, todo opcional):
header(logo de píxeles +Claude Code vX+ línea modelo/directorio de trabajo, siempre visible),windowTitleIdle→ intercambiowindowTitleal enviar prompt, eco de prompt como un bloque resaltado, spinner con contadores en vivo(Ns · ↓ N tokens)y una línea⎿ Tip:opcional, barra de estado que ganaesc to interruptsolo mientras trabaja. Tipos de beat adicionales:answer(bloque de prosa rica),alert(fila resaltada en rojo), los beatstoolpueden llevar líneas hijas⎿. - Sin deriva de transcripción. El texto del terminal solo puede aparecer gradualmente en su lugar: sin animaciones de entrada posicional dentro de la ventana, y nunca montar/desmontar un elemento que refluya las líneas debajo de él — las filas transitorias (spinners, progreso) viven en ranuras de altura fija para que su desaparición no desplace nada.
- Tarjetas de título: titular serifa en casi negro
#1F1508sobre el terracota, subtítulo mono al 68 % de opacidad, entrada con fundido ascendente. Titular ≥ 132 px, subtítulo ≥ 52 px a 1920 de ancho.
API de componentes (src/ccvideo)
Capa impulsada por datos (preferida para vídeos completos):
<GroundedVideo {...props}>— tarjeta de introducción → sesión → tarjeta de cierre, completamente a partir de un valorgroundedVideoSchema(unprops.jsonde captura).<DataSession {...props.session}>— renderiza cualquier valorsessionSchema: encabezado opcional, escritura de prompt, spinner, luegobeats(unión discriminada:code,tool,run,summary,answer,alert). Aplica el cut-zoom del beat de ejecución automáticamente; advierte en tiempo de render si el contenido se desbordará.sessionTiming(props, fps)/groundedVideoDuration(props, fps)— derivación de tiempo pura; úsalo encalculateMetadata.<Rich segments>— renderiza segmentos JSON{t: 'plain'|'kw'|'code'| 'comment'|'dim'|'bold', s}; el puente desde props.json al texto con estilo.
Primitivas de presentación:
<TerminalWindow title width? height? variant?>— ventana en el lienzo (variant="dark"para el tema oscuro). Los hijos son una columna flex; dale a la transcripciónflex: 1para que<InputBox>+<StatusBar>se fijen en la parte inferior.<TypeText text from cps? cursor?>/<Cursor>— máquina de escribir, 35–45 cps.<InputBox typedText? from? cps?>— fila>; sintypedText= cursor parpadeante.<StatusBar mode? hint?>.<Thinking from? until? word? stats? tokens? tip?>— spinner;statsmuestra en vivo(Ns)— más↓ N tokenssolo cuandotokenstiene un recuento capturado real;tipañade una línea⎿ Tip:. Ponlo en una ranura de altura fija entre la transcripción y la entrada;untillo desvanece en su lugar.<Line from?>— una fila de salida, fundido de entrada de 8 fotogramas (solo opacidad).<ToolLine from>— fila de viñeta●.<CodeBlock from lines stagger? startLineNo? expandNote?>— líneas numeradas.- Spans de token:
<K>palabra clave,<C>código/ruta,<Cm>comentario,<Dim>,<B>. <SessionHeader version modelLine>,<PromptEcho>,<AlertLine from?>,<ToolChild from?>— cromo de sesión (consulta las reglas de estilo).<CutZoom cuts={[{from, scale?, origin?, ease?}]}>— movimientos breves con easing entre encuadres fijos; el único movimiento de cámara permitido en escenas de terminal.<SlowZoom from? to?>— solo tarjetas de título, nunca alrededor de un terminal.<TitleCard title subtitle? titleSize?>.
Toda la animación está impulsada por fotogramas (useCurrentFrame + interpolate, limitado,
en línea en style). Nunca uses transition/animation de CSS.