SOP: Sistema de Carruseles TikTok de 3 Slides con AI

Cómo replicar el pipeline de generación de contenido que usa Adrià Martinez para producir 5 carruseles virales en 5 minutos.

2026-05-28

Tabla de Contenidos

  1. [Prerrequisitos](#prerrequisitos)
  2. [Paso 1 — Entender la restricción de 3 slides (la matemática de la completion rate)](#paso-1--entender-la-restricción-de-3-slides-la-matemática-de-la-completion-rate)
  3. [Paso 2 — Crear las plantillas de prompt (bloquearlas en código)](#paso-2--crear-las-plantillas-de-prompt-bloquearlas-en-código)
  4. [Paso 3 — Generación de variables de contenido (Claude Haiku, salida JSON)](#paso-3--generación-de-variables-de-contenido-claude-haiku-salida-json)
  5. [Paso 4 — Pipeline de renderizado (GPT Image 2, paralelo, image-edit)](#paso-4--pipeline-de-renderizado-gpt-image-2-paralelo-image-edit)
  6. [Paso 5 — Workflow de generación en batch (5 carruseles en 5 minutos)](#paso-5--workflow-de-generación-en-batch-5-carruseles-en-5-minutos)
  7. [Paso 6 — Revisión manual y publicación (texto overlay de TikTok, tests A/B)](#paso-6--revisión-manual-y-publicación-texto-overlay-de-tiktok-tests-ab)
  8. [Plan de Mantenimiento](#plan-de-mantenimiento)
  9. [Tabla de Troubleshooting](#tabla-de-troubleshooting)

Prerrequisitos

Antes de ejecutar este SOP, verificá que tengas todo lo siguiente:

RecursoDetalle
API Key de AnthropicCon acceso a Claude Haiku (claude-3-haiku-20240307 o superior).
API Key de OpenAICon acceso a GPT Image 2 y endpoint de image-edit.
Entorno Python 3.10+Con librerías anthropic, openai, requests, pillow, python-dotenv.
Variables de entornoANTHROPIC_API_KEY y OPENAI_API_KEY configuradas en .env.
Assets baseImagen de fondo para el template de Slide 2 (piel limpia), fuente tipográfica para overlays, ícono de DM y racha.
Cuenta TikTokCuenta configurada con acceso a Creator Tools para publicar carruseles de imágenes.
Directorio de trabajoEstructura de carpetas: ./prompts/, ./output/, ./assets/, ./logs/.

`bash mkdir -p prompts output assets logs `

Paso 1 — Entender la restricción de 3 slides (la matemática de la completion rate)

### El secreto del formato

El sistema de Adrià Martinez se basa en un principio simple pero poderoso: 3 slides = completion rate cercana al 100%. Cada slide adicional que agregás reduce exponencialmente la probabilidad de que el usuario llegue al final, que es donde está tu call-to-action (CTA).

  • 1 slide: El usuario ni se entera de que es un carrusel.
  • 3 slides: Suficiente para contar una historia completa sin perder a nadie en el camino.
  • 5+ slides: Abandono masivo. La gente swipes 2 o 3 veces y se va.

### El arco narrativo: breakup-glowup

Los 3 slides siguen una estructura fija e inalterable:

  • Slide 1 — "El antes" (dolor): Persona llorando con acné visible. Texto emocional que genera identificación inmediata. Función: hook.
  • Slide 2 — "El después" (glow-up): La misma persona con piel perfecta, radiante. Función: payoff visual.
  • Slide 3 — "La conversión" (lockscreen): Captura de pantalla estilo lockscreen con un DM recibido + racha de Snapchat/TikTok. Overlay con CTA: "Mandame MD para saber cómo lo hice". Función: conversión.

### Por qué la completion rate es todo

TikTok prioriza contenido que la gente ve completo. Si tu completion rate es alta (90%+), el algoritmo te recompensa con más impresiones. Con solo 3 slides, prácticamente garantizás que todo el que entra, llega al CTA del Slide 3.

> Regla de oro: Jamás agregues un cuarto slide. El sistema está calibrado para exactamente 3. Rompés esa regla, rompés la completion rate, y rompés el funnel.

Paso 2 — Crear las plantillas de prompt (bloquearlas en código)

### Por qué las plantillas van en código, no en prompts dinámicos

Adrià descubrió que pasarle toda la lógica de diseño a un LLM genera inconsistencia. La solución: plantillas fijas en código Python. Lo único que varía entre carruseles son las variables de contenido que se inyectan en esas plantillas (generadas en el Paso 3).

Esto garantiza que los 5 carruseles del batch mantengan exactamente la misma calidad visual y estructura narrativa, cambiando solo el concepto/historia.

### Template A: Slide 1 — "El antes" (dolor/acné)

`python SLIDE1_PROMPT = """ A photorealistic image of a {gender} in their early 20s, crying softly, close-up selfie angle. Their face has visible {acne_severity} acne: {acne_description}. The lighting is harsh bathroom fluorescent, casting unflattering shadows. The expression conveys genuine emotional pain and insecurity. Raw, unfiltered, no makeup. Tears visible on cheeks. The background is a messy bathroom mirror with water spots. Aspect ratio 9:16 vertical, phone selfie style. Generate ONLY the image — no text overlays. """ `

### Template B: Slide 2 — "El después" (glow-up)

`python SLIDE2_PROMPT = """ A photorealistic image of the SAME person from the previous image — same facial structure, same hair color ({hair_color}), same eye color ({eye_color}), same face shape ({face_shape}). But now their skin is absolutely flawless, glowing, glass-skin effect. Confident expression, soft smile, looking directly at the camera. Golden hour natural lighting, warm tones. The person looks radiant, happy, and transformed. Studio-quality portrait, 9:16 vertical. Generate ONLY the image — no text overlays. IMPORTANT: This must look like the same person, just with clear skin and better lighting/mood. """ `

### Template C: Slide 3 — "Lockscreen con CTA"

`python SLIDE3_PROMPT = """ A smartphone lockscreen screenshot, 9:16 vertical. The lockscreen shows: - Time display at the top: {time_display} - A direct message notification from Instagram: "{dm_text}" - A Snapchat streak notification showing {streak_days} day streak - The background is a subtle gradient in {bg_color} - The overall vibe is mysterious and intriguing — making viewers curious about what the DM conversation contains. Generate ONLY the lockscreen image — no real UI elements that would be detected as fake. """ `

### Código del motor de templates

`python from dataclasses import dataclass from typing import Dict

@dataclass class CarouselVariables: """Variables inyectables generadas por Claude Haiku.""" gender: str acne_severity: str acne_description: str hair_color: str eye_color: str face_shape: str time_display: str dm_text: str streak_days: int bg_color: str hook_text: str # Para overlay manual en TikTok

class PromptTemplates: """Plantillas fijas. Lo único que cambia son las variables."""

SLIDE1 = SLIDE1_PROMPT # Template fijo arriba SLIDE2 = SLIDE2_PROMPT SLIDE3 = SLIDE3_PROMPT

@classmethod def render_slide1(cls, vars: CarouselVariables) -> str: return cls.SLIDE1.format( gender=vars.gender, acne_severity=vars.acne_severity, acne_description=vars.acne_description, )

@classmethod def render_slide2(cls, vars: CarouselVariables) -> str: return cls.SLIDE2.format( hair_color=vars.hair_color, eye_color=vars.eye_color, face_shape=vars.face_shape, )

@classmethod def render_slide3(cls, vars: CarouselVariables) -> str: return cls.SLIDE3.format( time_display=vars.time_display, dm_text=vars.dm_text, streak_days=vars.streak_days, bg_color=vars.bg_color, ) `

> Principio clave: Las plantillas son código sagrado. Se versionan, se testean, y solo se modifican con aprobación después de un test A/B que demuestre mejor rendimiento.

Paso 3 — Generación de variables de contenido (Claude Haiku, salida JSON)

### Por qué Claude Haiku

  • Velocidad: Haiku es el modelo más rápido de Anthropic. Necesitamos generar variables para 5 carruseles en segundos.
  • Costo: Fracción de centavo por request.
  • Calidad: Suficiente para generar conceptos creativos variados sin desviarse del formato.

### El prompt generador

`python import anthropic import json from templates import CarouselVariables

GENERATOR_PROMPT = """You are a TikTok carousel content strategist specializing in viral skincare transformation content.

Generate {count} unique carousel concepts for a "breakup-glowup" style TikTok carousel. Each concept must be unique — different gender, different story, different vibe. Avoid repetition.

Return ONLY a JSON array of objects with these fields: - gender: "male" or "female" - acne_severity: "mild", "moderate", or "severe" - acne_description: detailed visual description of acne (5-10 words) - hair_color: natural hair color - eye_color: natural eye color - face_shape: "oval", "round", "square", or "heart" - time_display: a realistic phone time like "9:41 PM" - dm_text: a mysterious Instagram DM preview (under 30 chars) - streak_days: a streak number between 50 and 300 - bg_color: a CSS gradient color name like "purple", "midnight-blue", "sunset-orange" - hook_text: the text overlay for the first slide (max 40 chars), emotional and clickbaity, in the style of "POV: te dejó por fea y ahora no para de llamarte"

Make each carousel feel like a completely different person's story. Vary the tone: some sad, some angry, some triumphant.

Example output format: [{"gender": "female", "acne_severity": "severe", ...}]

CRITICAL: Return valid JSON array only. No explanation, no markdown."""

def generate_variables(client: anthropic.Anthropic, count: int = 5) -> list[CarouselVariables]: """Genera variables para N carruseles usando Claude Haiku."""

message = client.messages.create( model="claude-3-haiku-20240307", max_tokens=2000, temperature=0.9, # Alta creatividad para variedad messages=[{ "role": "user", "content": GENERATOR_PROMPT.format(count=count) }] )

raw_json = message.content[0].text data = json.loads(raw_json)

return [CarouselVariables(item) for item in data] `

### Validación post-generación

Siempre ejecutá estas verificaciones sobre el JSON generado:

`python def validate_variables(variables: list[CarouselVariables]) -> bool: """Asegura que las variables generadas sean válidas e inyectables."""

seen = set() for v in variables: # Check de unicidad (no queremos 5 carruseles iguales) fingerprint = f"{v.gender}|{v.acne_severity}|{v.hair_color}|{v.eye_color}" if fingerprint in seen: raise ValueError(f"Duplicate concept detected: {fingerprint}") seen.add(fingerprint)

# Validar rangos assert v.streak_days >= 50 and v.streak_days <= 300 assert len(v.hook_text) <= 40 assert len(v.dm_text) <= 30

return True `

Paso 4 — Pipeline de renderizado (GPT Image 2, paralelo, image-edit)

### Por qué GPT Image 2

GPT Image 2 genera imágenes fotorrealistas de altísima calidad y, crucialmente, soporta image-edit para mantener continuidad facial entre slides. Sin image-edit, el Slide 2 parecería una persona diferente al Slide 1, lo cual rompe la ilusión del "antes y después" y destruye la narrativa.

### Flujo de renderizado por carrusel

Para cada uno de los 5 carruseles:

  1. Slide 1gpt-image-2 con el prompt renderizado del Template A.
  2. Slide 2gpt-image-2 con image-edit, usando la imagen del Slide 1 como base. Esto mantiene la misma estructura facial pero con piel limpia.
  3. Slide 3gpt-image-2 con el prompt renderizado del Template C (lockscreen, no necesita continuidad facial).

### Código del pipeline

`python import asyncio from openai import AsyncOpenAI import base64 from pathlib import Path from templates import PromptTemplates, CarouselVariables

client = AsyncOpenAI()

async def render_slide1(vars: CarouselVariables, output_dir: Path) -> Path: """Renderiza Slide 1: imagen base del 'antes'."""

prompt = PromptTemplates.render_slide1(vars)

response = await client.images.generate( model="gpt-image-2", prompt=prompt, size="1080x1920", # 9:16 vertical quality="hd", n=1, )

# Guardar imagen image_path = output_dir / "slide1.png" # response.data[0].url para descargar, o response.data[0].b64_json # ... lógica de descarga ...

return image_path

async def render_slide2(vars: CarouselVariables, slide1_path: Path, output_dir: Path) -> Path: """Renderiza Slide 2 usando image-edit sobre Slide 1 para continuidad facial."""

prompt = PromptTemplates.render_slide2(vars)

with open(slide1_path, "rb") as f: image_data = base64.b64encode(f.read()).decode("utf-8")

response = await client.images.edit( model="gpt-image-2", image=image_data, # Imagen base para mantener identidad prompt=prompt, # Instrucciones de transformación size="1080x1920", n=1, )

image_path = output_dir / "slide2.png" # ... lógica de descarga ...

return image_path

async def render_slide3(vars: CarouselVariables, output_dir: Path) -> Path: """Renderiza Slide 3: lockscreen con CTA."""

prompt = PromptTemplates.render_slide3(vars)

response = await client.images.generate( model="gpt-image-2", prompt=prompt, size="1080x1920", quality="hd", n=1, )

image_path = output_dir / "slide3.png" # ... lógica de descarga ...

return image_path

async def render_carousel(vars: CarouselVariables, carousel_id: int, base_dir: Path) -> dict: """Renderiza un carrusel completo de 3 slides."""

output_dir = base_dir / f"carousel_{carousel_id:02d}" output_dir.mkdir(parents=True, exist_ok=True)

# Slide 1 primero slide1 = await render_slide1(vars, output_dir)

# Slide 2 y 3 se pueden paralelizar slide2, slide3 = await asyncio.gather( render_slide2(vars, slide1, output_dir), render_slide3(vars, output_dir), )

return { "id": carousel_id, "variables": vars, "slides": [slide1, slide2, slide3], } `

### Paralelización: 15 imágenes simultáneas

La verdadera potencia está en disparar los 5 carruseles completos en paralelo:

`python async def render_batch(variables: list[CarouselVariables], base_dir: Path) -> list[dict]: """Renderiza 5 carruseles = 15 imágenes en paralelo."""

tasks = [ render_carousel(vars, i, base_dir) for i, vars in enumerate(variables) ]

results = await asyncio.gather(*tasks) return results `

Esto ejecuta los 5 carruseles simultáneamente. Dentro de cada carrusel, el Slide 1 es secuencial (porque el Slide 2 depende de él vía image-edit), pero los Slides 2 y 3 se disparan en paralelo una vez que el Slide 1 está listo. El resultado: 15 imágenes generadas en el tiempo que toma generar ~2 imágenes secuenciales.

Paso 5 — Workflow de generación en batch (5 carruseles en 5 minutos)

### Script principal: main.py

`python #!/usr/bin/env python3 """ Sistema de generación de carruseles TikTok — 3 slides. Basado en el método de Adrià Martinez. Genera 5 carruseles completos en aproximadamente 5 minutos. """

import asyncio import time import anthropic from openai import AsyncOpenAI from pathlib import Path from datetime import datetime import json import logging

from templates import PromptTemplates, CarouselVariables from generator import generate_variables, validate_variables from renderer import render_batch

logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s") logger = logging.getLogger("tiktok-carousel")

def step_generate_variables(count: int = 5) -> list[CarouselVariables]: logger.info(f"Paso 3: Generando {count} conceptos con Claude Haiku...")

client = anthropic.Anthropic() variables = generate_variables(client, count=count) validate_variables(variables)

logger.info(f"✓ {len(variables)} conceptos generados y validados") return variables

async def step_render_batch(variables: list[CarouselVariables], batch_id: str) -> dict: logger.info(f"Paso 4: Renderizando {len(variables)} carruseles en paralelo...")

output_dir = Path(f"output/{batch_id}") output_dir.mkdir(parents=True, exist_ok=True)

results = await render_batch(variables, output_dir)

logger.info(f"✓ {len(results)} carruseles renderizados") return {"batch_id": batch_id, "results": results, "output_dir": str(output_dir)}

async def main(): start = time.time() batch_id = datetime.now().strftime("%Y%m%d_%H%M%S")

logger.info(f"=== INICIO BATCH {batch_id} ===")

# Paso 3: Variables variables = step_generate_variables(count=5)

# Paso 4: Renderizado batch_result = await step_render_batch(variables, batch_id)

# Guardar metadata metadata = { "batch_id": batch_id, "timestamp": datetime.now().isoformat(), "carousels": [ { "id": r["id"], "variables": vars(r["variables"]), "slides": [str(s) for s in r["slides"]], } for r in batch_result["results"] ], }

with open(f"output/{batch_id}/metadata.json", "w") as f: json.dump(metadata, f, indent=2, default=str)

elapsed = time.time() - start logger.info(f"=== BATCH COMPLETO en {elapsed:.1f}s ===") logger.info(f"Output: output/{batch_id}/") logger.info(f"Próximo paso: Revisión manual (Paso 6)")

if __name__ == "__main__": asyncio.run(main()) `

### Ejecución

`bash python3 main.py `

### Resultado esperado

` 20260528_143022 [INFO] === INICIO BATCH 20260528_143022 === 20260528_143022 [INFO] Paso 3: Generando 5 conceptos con Claude Haiku... 20260528_143025 [INFO] ✓ 5 conceptos generados y validados 20260528_143025 [INFO] Paso 4: Renderizando 5 carruseles en paralelo... 20260528_143520 [INFO] ✓ 5 carruseles renderizados 20260528_143520 [INFO] === BATCH COMPLETO en 298.3s === 20260528_143520 [INFO] Output: output/20260528_143022/ `

Estructura resultante:

` output/20260528_143022/ ├── carousel_01/ │ ├── slide1.png ← "El antes" │ ├── slide2.png ← "El después" (image-edit) │ └── slide3.png ← Lockscreen + CTA ├── carousel_02/ │ └── ... ├── ... ├── carousel_05/ │ └── ... └── metadata.json `

Paso 6 — Revisión manual y publicación (texto overlay de TikTok, tests A/B)

### La intervención humana no es opcional

El sistema genera imágenes crudas. Antes de publicar, siempre hacés:

### 6.1 Revisión de calidad visual

Para cada uno de los 5 carruseles, verificá visualmente:

  • Slide 1 vs Slide 2: ¿Parece la misma persona? Si el image-edit falló (cambio de raza, género, o estructura facial), descartá ese carrusel.
  • Calidad de imagen: Sin artefactos obvios de AI (dedos deformes, texto ilegible, fondos imposibles).
  • Slide 3 (lockscreen): ¿El DM es creíble? ¿La racha tiene sentido? ¿No se ven elementos de UI real?

### 6.2 Agregar texto overlay en TikTok

Las imágenes generadas no incluyen texto. El texto overlay se agrega dentro de TikTok al momento de crear la publicación:

  • Slide 1: Pegar hook_text de las variables generadas. Ej: "POV: te ghosteó por tu acne y ahora llora en mis DMs"
  • Slide 2: Sin texto o texto sutil: "3 meses después"
  • Slide 3: CTA explícito: "Mandame MD para saber cómo"

> Tip de Adrià: El texto overlay en TikTok se indexa para búsqueda. Usá keywords relevantes en el hook del Slide 1: "acne", "glow up", "skincare", "transformación".

### 6.3 Música y sincronización

  • Seleccioná un sonido trending en TikTok (no copyright, idealmente de la biblioteca de TikTok).
  • El carrusel avanza automáticamente, pero configurá cada slide para mostrarse 2–3 segundos.

### 6.4 Publicación escalonada y tests A/B

No publiques los 5 carruseles de golpe:

` Día 1 (8:00 PM): Carrusel 1 y Carrusel 2 Día 2 (8:00 PM): Carrusel 3 y Carrusel 4 Día 3 (8:00 PM): Carrusel 5 (el mejor performer se republica) `

Test A/B: Variá ligeramente los hooks entre carruseles para identificar qué formato de texto genera más engagement:

  • Variante A: Hook emocional: "POV: lloraba por mi acne todos los días"
  • Variante B: Hook agresivo: "Me dijo que era fea. Ahora mira."
  • Variante C: Hook misterioso: "Nadie sabe cómo pasé de esto a esto"

Registrá métricas (vistas, completion rate, shares, DMs recibidos) y alimentá esa data de vuelta al generador de variables para mejorar futuros batches.

### 6.5 Tracking de resultados

`python TRACKING_FIELDS = [ "carousel_id", "hook_variant", # A, B, o C "publish_date", "views_24h", "completion_rate", # % que llegó al Slide 3 "shares", "dms_received", # Cuántos MDs generó el CTA "notes", # Observaciones cualitativas ] `

Plan de Mantenimiento

FrecuenciaAcciónResponsable
DiarioRevisar métricas de los carruseles publicados: completion rate y DMs recibidos.Content Manager
SemanalRotar templates de prompt si detectás fatiga creativa (mismos conceptos recurrentes). Actualizar hook_text con frases trending.Prompt Engineer
QuincenalTest A/B de nuevas variantes de hook. Comparar contra baseline y actualizar el generador si hay mejora >15%.Growth Team
MensualRevisar costos de API (Anthropic + OpenAI). Ajustar count y calidad si es necesario. Actualizar modelo de Haiku a la versión más reciente si Anthropic lanza nueva.Tech Lead
TrimestralAuditoría completa del pipeline: ¿sigue funcionando image-edit? ¿GPT Image 2 tiene nuevo modelo? ¿Cambió el algoritmo de TikTok? Revisar y ajustar.Tech Lead + Content Manager
ante caída de APITener un fallback manual documentado: prompts de Midjourney/DALL-E equivalentes para generar imágenes si OpenAI está down.Todo el equipo

Tabla de Troubleshooting

SíntomaCausa probableSolución
Slide 2 no se parece al Slide 1image-edit de GPT Image 2 perdió la identidad facial. Prompt demasiado agresivo en la transformación.Reducí la intensidad de las instrucciones en SLIDE2_PROMPT. Agregá constraints explícitos: "mantén exactamente la misma estructura ósea, nariz, y forma de ojos". Si persiste, descartá ese carrusel y regenerá.
Claude Haiku devuelve JSON inválidoTemperature muy alta (0.9) o prompt ambiguo.Bajá temperature a 0.7. Agregá al prompt: "Return ONLY the JSON array. If you include any other text, the system will crash." Implementá un retry con json.loads en try/except.
Timeout en renderizado paraleloOpenAI rate-limiting 15 requests simultáneos.Bajá la concurrencia: usá asyncio.Semaphore(3) para limitar a 3 requests simultáneos. Agregá exponential backoff en el cliente OpenAI.
Completion rate < 80% en algún carruselHook del Slide 1 no enganchó, o las imágenes no generan curiosidad suficiente para swipar al Slide 3.Analizá el hook_text de ese carrusel vs los que sí funcionaron. ¿Es muy largo? ¿Poco emocional? Ajustá el generador para evitar ese patrón. Testeá con otro hook en el mismo carrusel (republicar).
0 DMs recibidos (CTA no convierte)Slide 3 es débil. El lockscreen no genera intriga o el DM text es poco creíble.Revisá el dm_text generado para ese carrusel. Debe ser específico y misterioso: "Tengo que contarte algo..." funciona mejor que "Hola".
GPT Image 2 rechaza el prompt (safety filter)La descripción de "crying" o sufrimiento emocional dispara filtros de contenido.Suavizá SLIDE1_PROMPT: cambiá "crying" por "looking sad/upset" y "emotional pain" por "looking vulnerable".
Costo mensual se disparaDemasiados batches o calidad hd innecesaria.Reducí frecuencia de batches. Probá con quality="standard" para Slide 2 y 3 (el Slide 1 es el más importante visualmente).
5 carruseles tardan más de 10 minutosRate-limiting, latencia de red, o modelo sobrecargado.Implementá caché de variables (no regenerar conceptos si el batch falla a la mitad). Usá asyncio.Semaphore como arriba. Considerá horarios de baja demanda para correr batches.

Resumen del Pipeline

` ┌─────────────────────────────────────────────────────┐ │ PIPELINE COMPLETO │ ├─────────────────────────────────────────────────────┤ │ │ │ Paso 3: Claude Haiku │ │ ┌──────────┐ JSON con variables ┌───────────┐ │ │ │ Generator │ ─────────────────────▶ │ Validator │ │ │ └──────────┘ 5 conceptos únicos └───────────┘ │ │ │ │ Paso 4: GPT Image 2 (PARALELO) │ │ ┌──────────────────────────────────────────────┐ │ │ │ Carrusel 1 │ Carrusel 2 │ Carrusel 3 ...│ │ │ │ S1→S2→S3 │ S1→S2→S3 │ S1→S2→S3 │ │ │ │ (image-edit)│ (image-edit)│ (image-edit) │ │ │ └──────────────────────────────────────────────┘ │ │ ▼ 15 imágenes en ~5 min │ │ │ │ Paso 6: Revisión Manual │ │ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │ │ │ Revisar │──▶│ Overlays │──▶│ Publicar │ │ │ │ calidad │ │ TikTok │ │ escalonado │ │ │ └──────────┘ └──────────┘ └──────────────┘ │ │ │ └─────────────────────────────────────────────────────┘ `

Apéndice A: Checklist Pre-Publicación

Antes de publicar cada carrusel, verificá:

  • [ ] Las 3 imágenes están en 1080×1920 (9:16 vertical).
  • [ ] Slide 1 y Slide 2 muestran claramente a la misma persona.
  • [ ] Slide 3 tiene un CTA visible y creíble.
  • [ ] El texto overlay está corregido (sin errores de tipeo).
  • [ ] La música seleccionada es trending y libre de copyright.
  • [ ] El hook del Slide 1 contiene keywords indexables.
  • [ ] Estás publicando en el horario pico de tu audiencia (típicamente 19:00–21:00).
  • [ ] Tenés el tracking sheet abierto para registrar métricas.

Apéndice B: Variables de Entorno Requeridas

`bash ANTHROPIC_API_KEY=sk-ant-xxxxxxxxxxxxxxxx OPENAI_API_KEY=sk-proj-xxxxxxxxxxxxxxxx TIKTOK_CREATOR_EMAIL=tuemail@example.com OUTPUT_DIR=./output LOG_LEVEL=INFO MAX_CONCURRENT_RENDERS=5 `

Documento generado como parte del sistema ADMP-20260528-002. Output ID: OUT-20260528-004.

— Ariel Di Stefano