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/.

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é)

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)

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"

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

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

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:

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

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:

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

#!/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

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

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

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

Compartir este artículo

Preguntas frecuentes

¿Qué es un SOP de carruseles para TikTok con IA?
Un SOP es un sistema paso a paso para crear carruseles de 3 slides en TikTok usando inteligencia artificial. En este caso, combina Claude Haiku para generar el contenido y GPT Image 2 para renderizar las imágenes. Con este proceso podés producir carruseles optimizados para retener la atención del usuario.
¿Por qué los carruseles de TikTok tienen que tener 3 slides?
Porque 3 slides te dan una completion rate cercana al 100%. Cada slide adicional que agregás reduce exponencialmente la probabilidad de que el usuario llegue al final, así que menos es más.
¿Qué herramientas necesito para hacer carruseles con IA?
Necesitás una API Key de Anthropic para usar Claude Haiku y una API Key de OpenAI para GPT Image 2. También tenés que armar las plantillas de prompt fijas en código Python para mantener la consistencia del diseño.
¿Cómo hago para mantener la misma cara en los slides de un carrusel?
Usás GPT Image 2 en modo image-edit. Eso te permite mantener la continuidad facial entre el slide 1 y el slide 2, algo que no se logra si generás cada imagen de cero.

Te puede interesar