¿Qué hace Marketing Studio Agent?
Habilidad de ara.so — Colección de habilidades de Marketing.
Marketing Studio es un motor de renderizado de video impulsado por agente para Claude Code. Ejecuta /marketing desde tu repositorio de producto para generar un conjunto completo de activos de lanzamiento: presentación 3D del logo, demo del producto capturada en pantalla, video de lanzamiento principal con locución/música, clips sociales por plataforma y activos OG. Toda la renderización ocurre en un repositorio de motor central usando Remotion, Blender, Playwright y ElevenLabs.
Instalación
# Clonar el repositorio del motor
git clone https://github.com/ucsandman/marketing-studio.git
cd marketing-studio
# Instalar dependencias
cd studio && npm install && cd ..
# Configurar (opcional: ruta de Blender, clave API de ElevenLabs)
cp .env.example .env
# Instalar habilidades en Claude Code
node scripts/install-skills.mjs
# Verificar herramientas
python launch.py --check
El script de instalación copia las habilidades a ~/.claude/skills y las vincula a la ruta de tu motor clonado.
Flujo de trabajo principal
El comando /marketing
Desde tu repositorio de producto:
claude
> /marketing
Esto ejecuta el pipeline completo:
- Incorporación de marca – Deriva tokens de marca de tu sistema de diseño (o los solicita)
- Presentación del logo – Animación 3D en Blender compuesta en Remotion
- Demo del producto – Playwright captura tu aplicación en ejecución con zooms de cámara
- Video de lanzamiento – Video principal de 30 a 90 segundos que combina demo, logo y texto
- Pista de audio – Locución de ElevenLabs y música sincronizada con el video
- Clips sociales – Cortes específicos para cada plataforma (X, LinkedIn, TikTok)
- Activos OG – Imagen estática, bucle animado, GIF para README
Habilidades individuales
Ejecuta cualquier tipo de activo de forma independiente:
> /logo-reveal
> /product-demo
> /launch-video
> /audio-track
> /social-clip
> /og-assets
Configuración de marca
Las marcas se definen en brands/<id>.json:
{
"id": "myproduct",
"name": "MyProduct",
"tagline": "Envía más rápido, rompe menos",
"colors": {
"primary": "#3b82f6",
"secondary": "#8b5cf6",
"accent": "#f59e0b",
"background": "#000000",
"foreground": "#ffffff",
"muted": "#6b7280",
"success": "#10b981",
"warning": "#f59e0b",
"error": "#ef4444",
"text": "#f9fafb",
"textMuted": "#9ca3af",
"border": "#374151",
"surface": "#111827"
},
"fonts": {
"heading": "Inter",
"body": "Inter",
"mono": "JetBrains Mono"
},
"voice": {
"tone": "seguro, técnico, sin rodeos",
"avoid": ["AI slop", "game-changer", "revolutionary"]
}
}
Registra la marca en studio/src/lib/brand.ts:
import { z } from 'zod';
export const BrandSchema = z.object({
id: z.string(),
name: z.string(),
tagline: z.string(),
colors: z.object({
primary: z.string(),
secondary: z.string(),
accent: z.string(),
// ... los 13 colores
}),
fonts: z.object({
heading: z.string(),
body: z.string(),
mono: z.string(),
}),
voice: z.object({
tone: z.string(),
avoid: z.array(z.string()),
}),
});
export type Brand = z.infer<typeof BrandSchema>;
export function getBrand(brandId: string): Brand {
const brandData = require(`../../brands/${brandId}.json`);
return BrandSchema.parse(brandData);
}
Agrega un componente de marca gráfica en studio/src/brands/<id>Mark.tsx:
import React from 'react';
export const MyProductMark: React.FC<{
size?: number;
color?: string;
}> = ({ size = 100, color = '#3b82f6' }) => {
return (
<svg width={size} height={size} viewBox="0 0 100 100">
<circle cx="50" cy="50" r="40" fill={color} />
</svg>
);
};
Renderización manual
Comandos de Remotion
Renderiza cualquier composición directamente:
cd studio
# Presentación de logo
npx remotion render LogoReveal ../out/myproduct/logo.mp4 \
--props='{"brandId":"myproduct","cta":"Mira el lanzamiento"}'
# Demo de producto
npx remotion render ProductDemo ../out/myproduct/demo.mp4 \
--props='{"brandId":"myproduct","captureVideo":"../assets/captures/demo.mp4"}'
# Video de lanzamiento
npx remotion render LaunchVideo ../out/myproduct/launch.mp4 \
--props='{"brandId":"myproduct","demoVideo":"../out/myproduct/demo.mp4","script":["Hook","Problema","Solución"]}'
# Clip social
npx remotion render SocialClip ../out/myproduct/social-x.mp4 \
--props='{"brandId":"myproduct","platform":"x","feature":"Sincronización en tiempo real"}'
# OG animado
npx remotion render AnimatedOG ../out/myproduct/og.mp4 \
--props='{"brandId":"myproduct"}'
Scripts auxiliares
Capturar demo de producto
cd feeders/capture
node capture.mjs \
--url http://localhost:3000 \
--output ../../assets/captures/demo.mp4 \
--brand myproduct \
--script zoom-dashboard,click-feature,pan-results
Renderizar logo en Blender
cd feeders/blender
python render_logo.py \
--brand myproduct \
--output ../../assets/blender/logo-frames/ \
--style draw-on
Generar audio
cd feeders/audio
node generate.mjs \
--script "Envía tu producto en días, no en meses" \
--voice-id "ELEVENLABS_VOICE_ID" \
--output ../../assets/audio/voiceover.mp3
node generate.mjs \
--type music \
--mood energetic \
--duration 60 \
--output ../../assets/audio/music.mp3
Establece ELEVENLABS_API_KEY en .env.
Constructores de propiedades
Genera propiedades de renderizado a través de scripts constructores:
# Construir propiedades de video de lanzamiento
node scripts/build-launch-props.mjs \
--brand myproduct \
--demo-video ./assets/captures/demo.mp4 \
--script "Frase gancho" "Planteamiento del problema" "Demostración de la solución" \
--output ./props/launch-myproduct.json
# Construir propiedades de clip social
node scripts/build-social-props.mjs \
--brand myproduct \
--platform x \
--feature "Colaboración en tiempo real" \
--output ./props/social-x-myproduct.json
Los archivos de propiedades son JSON:
{
"brandId": "myproduct",
"demoVideo": "./assets/captures/demo.mp4",
"logoRevealVideo": "./out/myproduct/logo.mp4",
"script": [
{"type": "hook", "text": "Envía en días, no en meses", "duration": 3},
{"type": "problem", "text": "Los activos de marketing toman semanas", "duration": 4},
{"type": "solution", "text": "Un comando, conjunto completo", "duration": 5}
],
"voiceover": "./assets/audio/voiceover.mp3",
"music": "./assets/audio/music.mp3"
}
Variables de entorno
# .env
BLENDER_PATH=/Applications/Blender.app/Contents/MacOS/Blender
ELEVENLABS_API_KEY=tu_api_key_aqui
COMFYUI_URL=http://localhost:8188
Todas son opcionales; los scripts auxiliares se degradan correctamente sin ellas.
Verificación y pruebas
# Verificación completa de herramientas
python launch.py --check
# Renderizar fotograma 0 de cada composición (prueba rápida)
node scripts/smoke.mjs
# Validación de esquema de marca
cd studio && npm test
# Iniciar Remotion Studio para vista previa interactiva
python launch.py
Patrones clave
Reanudación en caso de fallo
El pipeline escribe un manifiesto de ejecución en .marketing-run.json:
{
"brand": "myproduct",
"timestamp": "2026-07-10T12:00:00Z",
"completed": ["logo-reveal", "product-demo"],
"current": "launch-video",
"props": {
"logoRevealVideo": "./out/myproduct/logo.mp4",
"demoVideo": "./out/myproduct/demo.mp4"
}
}
Volver a ejecutar /marketing reanuda desde el último paso incompleto.
Matemáticas de zoom de cámara
Las capturas de demo del producto utilizan una suavidad medida para zooms profesionales:
// studio/src/lib/camera.ts
export function calculateZoom(
frame: number,
duration: number,
startScale: number = 1,
endScale: number = 1.2
): number {
const progress = frame / duration;
const eased = 1 - Math.pow(1 - progress, 3); // cubic ease-out
return startScale + (endScale - startScale) * eased;
}
Reglas de bucle sin interrupciones
Los OG animados deben comenzar y terminar en fotogramas idénticos:
// studio/src/compositions/AnimatedOG.tsx
export const AnimatedOG: React.FC<{brandId: string}> = ({brandId}) => {
const frame = useCurrentFrame();
const {durationInFrames} = useVideoConfig();
const brand = getBrand(brandId);
// Normalizar a [0, 1) para bucle sin interrupciones
const progress = (frame % durationInFrames) / durationInFrames;
const rotation = progress * 360;
return (
<AbsoluteFill style={{backgroundColor: brand.colors.background}}>
<div style={{transform: `rotate(${rotation}deg)`}}>
{/* marca gráfica */}
</div>
</AbsoluteFill>
);
};
Clips sociales específicos por plataforma
Relaciones de aspecto y zonas seguras por plataforma:
// studio/src/compositions/SocialClip.tsx
const PLATFORM_SPECS = {
x: { width: 1280, height: 720, safeZone: 0.1 },
linkedin: { width: 1280, height: 720, safeZone: 0.1 },
tiktok: { width: 1080, height: 1920, safeZone: 0.15 },
instagram: { width: 1080, height: 1920, safeZone: 0.12 },
};
export const SocialClip: React.FC<{
brandId: string;
platform: keyof typeof PLATFORM_SPECS;
feature: string;
}> = ({brandId, platform, feature}) => {
const spec = PLATFORM_SPECS[platform];
const safeWidth = spec.width * (1 - 2 * spec.safeZone);
return (
<AbsoluteFill style={{width: spec.width, height: spec.height}}>
{/* contenido */}
</AbsoluteFill>
);
};
Solución de problemas
Blender no encontrado
Error: No se encontró el ejecutable de Blender en /Applications/Blender.app
Establece BLENDER_PATH en .env o salta las presentaciones 3D del logo (el pipeline recurre a 2D).
Límite de velocidad de ElevenLabs
Error: 429 Demasiadas solicitudes
La generación de audio es opcional. El pipeline renderiza el video sin locución si la API falla.
Tiempo de espera de captura de Playwright
Error: La página no cargó en 30 segundos
Asegúrate de que tu servidor de desarrollo se esté ejecutando en el puerto correcto. El script de captura espera el estado networkidle.
Error de memoria de Remotion
Error: Memoria insuficiente en el heap de JavaScript
Establece el límite de memoria de Node:
export NODE_OPTIONS="--max-old-space-size=8192"
npx remotion render ...
Error de validación de esquema de marca
Error: JSON de marca no válido
Ejecuta cd studio && npm test para ver las violaciones del esquema. Se requieren los 13 colores, 3 fuentes y reglas de voz.
Estructura de archivos
marketing-studio/
├── brands/ # tokens de marca por producto (JSON)
├── studio/ # proyecto Remotion (todas las composiciones)
│ ├── src/
│ │ ├── compositions/
│ │ │ ├── LogoReveal.tsx
│ │ │ ├── ProductDemo.tsx
│ │ │ ├── LaunchVideo.tsx
│ │ │ ├── SocialClip.tsx
│ │ │ └── AnimatedOG.tsx
│ │ ├── brands/ # componentes de marca gráfica
│ │ └── lib/
│ │ ├── brand.ts
│ │ └── camera.ts
├── feeders/
│ ├── blender/ # escenas headless de Blender
│ ├── capture/ # grabador Playwright
│ ├── audio/ # cliente ElevenLabs
│ └── comfy/ # cliente ComfyUI (opcional)
├── skills/ # habilidades de Claude Code
│ ├── marketing.md
│ ├── logo-reveal.md
│ ├── product-demo.md
│ └── ...
├── scripts/
│ ├── install-skills.mjs
│ ├── build-launch-props.mjs
│ ├── build-social-props.mjs
│ └── smoke.mjs
├── props/ # propiedades de render generadas (JSON)
├── assets/ # capturas, audio, fotogramas de Blender
├── out/ # videos finales renderizados
└── examples/ # salidas reales de productos enviados
Buenas prácticas
- Ejecuta la prueba rápida después de cambios en la marca:
node scripts/smoke.mjsdetecta errores de esquema antes de renderizados completos - Usa los constructores de propiedades: Nunca edites manualmente el JSON de propiedades; usa
scripts/build-*-props.mjs - Graba la demo al final del trabajo de UI: Ejecuta
/polishy/frontend-verifyantes de/product-demo - Ajusta el audio después del bloqueo de imagen: No generes la locución hasta que el guion del video de lanzamiento esté finalizado
- Prueba localmente antes de
/marketing: Ejecuta habilidades individuales (/logo-reveal,/product-demo) para depurar los tokens de marca - Mantén el manifiesto de ejecución: No elimines
.marketing-run.jsondurante ejecuciones activas (permite la reanudación)
Habilidades relacionadas
/polish– Último ajuste de calidad de UI antes de filmar la demo/frontend-verify– Verificación de rutas headless (errores de consola, solicitudes fallidas)/de-vibe– Elimina huellas de IA antes de enviar/launch– Genera borradores de anuncios por canal
Todas las habilidades complementarias se instalan con scripts/install-skills.mjs.