Que fait Marketing Studio Agent ?
Compétence par ara.so — Collection Marketing Skills.
Marketing Studio est un moteur de rendu vidéo piloté par agent pour Claude Code. Exécutez /marketing depuis votre dépôt produit pour générer une suite complète d'actifs de lancement : animation 3D du logo, démonstration produit capturée à l'écran, vidéo de lancement avec voix off/musique, clips sociaux par plateforme, et actifs OG. Tout le rendu s'effectue dans un dépôt moteur central utilisant Remotion, Blender, Playwright et ElevenLabs.
Installation
# Cloner le dépôt moteur
git clone https://github.com/ucsandman/marketing-studio.git
cd marketing-studio
# Installer les dépendances
cd studio && npm install && cd ..
# Configuration (optionnel : chemin Blender, clé API ElevenLabs)
cp .env.example .env
# Installer les compétences dans Claude Code
node scripts/install-skills.mjs
# Vérifier la chaîne d'outils
python launch.py --check
Le script d'installation copie les compétences dans ~/.claude/skills et les lie au chemin de votre dépôt moteur cloné.
Flux de travail principal
La commande /marketing
Depuis votre dépôt produit :
claude
> /marketing
Cela exécute le pipeline complet :
- Intégration de la marque – Dérive les tokens de marque de votre système de design (ou les demande)
- Animation du logo – Animation 3D Blender composée dans Remotion
- Démonstration produit – Playwright capture votre application en cours d'exécution avec des zooms de caméra
- Vidéo de lancement – Vidéo principale de 30 à 90 s combinant démo, logo et texte
- Piste audio – Voix off ElevenLabs et musique adaptées à la vidéo
- Clips sociaux – Découpage par plateforme (X, LinkedIn, TikTok)
- Actifs OG – Image statique, boucle animée, GIF pour README
Compétences individuelles
Exécutez n'importe quel actif de manière indépendante :
> /logo-reveal
> /product-demo
> /launch-video
> /audio-track
> /social-clip
> /og-assets
Configuration de la marque
Les marques sont définies dans brands/<id>.json :
{
"id": "myproduct",
"name": "MyProduct",
"tagline": "Ship faster, break less",
"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": "confiant, technique, sans fioritures",
"avoid": ["AI slop", "game-changer", "révolutionnaire"]
}
}
Enregistrez la marque dans 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(),
// ... toutes les 13 couleurs
}),
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);
}
Ajoutez un composant de logo dans 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>
);
};
Rendu manuel
Commandes Remotion
Rendre n'importe quelle composition directement :
cd studio
# Animation du logo
npx remotion render LogoReveal ../out/myproduct/logo.mp4 \
--props='{"brandId":"myproduct","cta":"Regardez le lancement"}'
# Démonstration produit
npx remotion render ProductDemo ../out/myproduct/demo.mp4 \
--props='{"brandId":"myproduct","captureVideo":"../assets/captures/demo.mp4"}'
# Vidéo de lancement
npx remotion render LaunchVideo ../out/myproduct/launch.mp4 \
--props='{"brandId":"myproduct","demoVideo":"../out/myproduct/demo.mp4","script":["Accroche","Problème","Solution"]}'
# Clip social
npx remotion render SocialClip ../out/myproduct/social-x.mp4 \
--props='{"brandId":"myproduct","platform":"x","feature":"Synchronisation en temps réel"}'
# OG animé
npx remotion render AnimatedOG ../out/myproduct/og.mp4 \
--props='{"brandId":"myproduct"}'
Scripts d'alimentation
Capturer une démonstration produit
cd feeders/capture
node capture.mjs \
--url http://localhost:3000 \
--output ../../assets/captures/demo.mp4 \
--brand myproduct \
--script zoom-dashboard,click-feature,pan-results
Rendre le logo Blender
cd feeders/blender
python render_logo.py \
--brand myproduct \
--output ../../assets/blender/logo-frames/ \
--style draw-on
Générer l'audio
cd feeders/audio
node generate.mjs \
--script "Expédiez votre produit en quelques jours, pas en mois" \
--voice-id "ELEVENLABS_VOICE_ID" \
--output ../../assets/audio/voiceover.mp3
node generate.mjs \
--type music \
--mood energetique \
--duration 60 \
--output ../../assets/audio/music.mp3
Définissez ELEVENLABS_API_KEY dans .env.
Constructeurs de props
Générez les props de rendu via les scripts constructeurs :
# Construire les props de la vidéo de lancement
node scripts/build-launch-props.mjs \
--brand myproduct \
--demo-video ./assets/captures/demo.mp4 \
--script "Ligne d'accroche" "Énoncé du problème" "Démonstration de la solution" \
--output ./props/launch-myproduct.json
# Construire les props du clip social
node scripts/build-social-props.mjs \
--brand myproduct \
--platform x \
--feature "Collaboration en temps réel" \
--output ./props/social-x-myproduct.json
Les fichiers de props sont au format JSON :
{
"brandId": "myproduct",
"demoVideo": "./assets/captures/demo.mp4",
"logoRevealVideo": "./out/myproduct/logo.mp4",
"script": [
{"type": "hook", "text": "Expédiez en jours, pas en mois", "duration": 3},
{"type": "problem", "text": "Les actifs marketing prennent des semaines", "duration": 4},
{"type": "solution", "text": "Une commande, une suite complète", "duration": 5}
],
"voiceover": "./assets/audio/voiceover.mp3",
"music": "./assets/audio/music.mp3"
}
Variables d'environnement
# .env
BLENDER_PATH=/Applications/Blender.app/Contents/MacOS/Blender
ELEVENLABS_API_KEY=your_api_key_here
COMFYUI_URL=http://localhost:8188
Toutes sont optionnelles ; les scripts d'alimentation fonctionnent de manière dégradée sans elles.
Vérification et tests
# Vérification complète de la chaîne d'outils
python launch.py --check
# Rendu de l'image 0 de chaque composition (test rapide)
node scripts/smoke.mjs
# Validation du schéma de marque
cd studio && npm test
# Lancement de Remotion Studio pour un aperçu interactif
python launch.py
Modèles clés
Reprise en cas d'échec
Le pipeline écrit un manifeste d'exécution dans .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"
}
}
Réexécuter /marketing reprend à partir de la dernière étape incomplète.
Mathématiques du zoom de caméra
Les captures de démonstration produit utilisent un easing mesuré pour des zooms professionnels :
// 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;
}
Règles de boucle parfaite
Les boucles OG animées doivent commencer et se terminer sur des images identiques :
// studio/src/compositions/AnimatedOG.tsx
export const AnimatedOG: React.FC<{brandId: string}> = ({brandId}) => {
const frame = useCurrentFrame();
const {durationInFrames} = useVideoConfig();
const brand = getBrand(brandId);
// Normalisation sur [0, 1) pour une boucle parfaite
const progress = (frame % durationInFrames) / durationInFrames;
const rotation = progress * 360;
return (
<AbsoluteFill style={{backgroundColor: brand.colors.background}}>
<div style={{transform: `rotate(${rotation}deg)`}}>
{/* logo */}
</div>
</AbsoluteFill>
);
};
Clips sociaux spécifiques à chaque plateforme
Rapports d'aspect et zones de sécurité par plateforme :
// 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}}>
{/* contenu */}
</AbsoluteFill>
);
};
Dépannage
Blender introuvable
Erreur : Exécutable Blender introuvable à /Applications/Blender.app
Définissez BLENDER_PATH dans .env ou ignorez les animations 3D du logo (le pipeline utilise un repli 2D).
Limite de débit ElevenLabs
Erreur : 429 Trop de requêtes
La génération audio est optionnelle. Le pipeline rend la vidéo sans voix off si l'API échoue.
Délai d'attente de capture Playwright
Erreur : La page ne s'est pas chargée dans les 30 s
Assurez-vous que votre serveur de développement est en cours d'exécution sur le bon port. Le script de capture attend l'état networkidle.
Erreur mémoire Remotion
Erreur : Mémoire insuffisante pour le tas JavaScript
Définissez la limite de mémoire Node :
export NODE_OPTIONS="--max-old-space-size=8192"
npx remotion render ...
Échec de validation du schéma de marque
Erreur : JSON de marque invalide
Exécutez cd studio && npm test pour voir les violations du schéma. Les 13 couleurs, les 3 polices et les règles vocales sont obligatoires.
Structure des fichiers
marketing-studio/
├── brands/ # tokens de marque par produit (JSON)
├── studio/ # projet Remotion (toutes les compositions)
│ ├── src/
│ │ ├── compositions/
│ │ │ ├── LogoReveal.tsx
│ │ │ ├── ProductDemo.tsx
│ │ │ ├── LaunchVideo.tsx
│ │ │ ├── SocialClip.tsx
│ │ │ └── AnimatedOG.tsx
│ │ ├── brands/ # composants de logo
│ │ └── lib/
│ │ ├── brand.ts
│ │ └── camera.ts
├── feeders/
│ ├── blender/ # scènes Blender sans tête
│ ├── capture/ # enregistreur Playwright
│ ├── audio/ # client ElevenLabs
│ └── comfy/ # client ComfyUI (optionnel)
├── skills/ # compétences 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/ # props de rendu générées (JSON)
├── assets/ # captures, audio, images Blender
├── out/ # vidéos rendues finales
└── examples/ # résultats réels de produits expédiés
Bonnes pratiques
- Exécutez le test rapide après les modifications de marque :
node scripts/smoke.mjsdétecte les erreurs de schéma avant les rendus complets - Utilisez les constructeurs de props : ne modifiez jamais manuellement le JSON des props ; utilisez
scripts/build-*-props.mjs - Filmez la démo en dernier dans le travail UI : exécutez
/polishet/frontend-verifyavant/product-demo - Ajoutez l'audio après le verrouillage de l'image : ne générez pas de voix off tant que le script de la vidéo de lancement n'est pas final
- Testez localement avant
/marketing: exécutez les compétences individuelles (/logo-reveal,/product-demo) pour déboguer les tokens de marque - Conservez le manifeste d'exécution : ne supprimez pas
.marketing-run.jsonpendant les exécutions actives (permet la reprise)
Compétences associées
/polish– Dernier passage qualité UI avant le tournage de la démo/frontend-verify– Vérification de route sans tête (erreurs console, requêtes échouées)/de-vibe– Supprime les artefacts d'IA avant l'expédition/launch– Génère des brouillons d'annonce par chaîne
Toutes les compétences associées s'installent avec scripts/install-skills.mjs.