Saltar al contenido principal
SocialCutter

IA y agentes

Procesa imágenes de Google Drive con SocialCutter

Vigila una carpeta de Drive, descarga la imagen nueva, procésala con SocialCutter y sube cada resultado a otra carpeta: OAuth, permisos y Python.

  • Google Drive
  • automatización
  • API de Drive
  • carpeta vigilada
  • Python
  • SocialCutter
  • recorte centrado

Un flujo de entrada y de salida

El caso se repite en casi todos los equipos: alguien deja el diseño en una carpeta de Drive y de ahí salen las versiones para cada red. SocialCutter no entra en Drive ni lo vigila: es un paso intermedio al que le das una imagen y una lista de destinos y te devuelve una URL por salida. Mover los ficheros es cosa de tu script.

El circuito tiene cuatro pasos:

  1. Detectar la imagen nueva en la carpeta de entrada.
  2. Descargar el binario.
  3. Procesarlo con SocialCutter.
  4. Subir cada resultado a la carpeta de salida.

Puedes montarlo con código propio (esta guía) o sin código, con el nodo Google Drive Trigger de n8n: Automatiza el recorte de imágenes con n8n.

Detectar la imagen nueva

La API de Drive (v3) ofrece tres vías:

Sondeo por carpeta

Es la más directa cuando solo te interesa una carpeta. Se consulta con files.list filtrando por la carpeta y ordenando por fecha:

q = "'<ID_CARPETA>' in parents and trashed = false"
fields = "files(id, name, mimeType, modifiedTime)"
orderBy = "modifiedTime desc"

Guarda el modifiedTime del último tratado y procesa solo lo nuevo: es sondeo, sin infraestructura.

El feed de cambios

changes.getStartPageToken() devuelve un token, y changes.list(pageToken=...) entrega solo lo que ha cambiado desde entonces. Es más barato que recorrer la carpeta entera en cada vuelta. Un detalle importante: el feed de cambios es de la cuenta o de la unidad compartida completa, no de una carpeta suelta. Si lo usas, filtra tú por parents.

Avisos en tiempo real

files.watch registra un canal que avisa a tu servidor cuando algo cambia, sin sondeos: necesita un endpoint HTTPS público y renovarse cada cierto tiempo. Opcional: el sondeo y el feed cubren la mayoría de los casos.

Descargar el binario

Con el fileId en la mano, la descarga es files.get_media. En Python, con MediaIoBaseDownload, el fichero queda en un BytesIO listo para reenviar. No hace falta hacerlo público ni firmar un enlace: el binario viaja de Drive a SocialCutter dentro de tu proceso.

Los ficheros de Google Docs, Sheets o Slides no tienen binario directo: expórtalos antes (files.export) a imagen. SocialCutter trabaja con raster, no con documentos.

Procesar con SocialCutter

El binario se envía por multipart al endpoint de subida, con la lista de destinos como campo de formulario:

  • Método: POST
  • URL: https://api.socialcutter.theboomer.dev/api/v1/images/process/upload
  • Cabecera: X-API-Key: sc_tu_clave
  • Campos: file con el binario y destinations con el JSON de la lista

La respuesta trae un array outputs con una entrada por destino y los campos platform, format, url, width, height y size_bytes. Los destinos salen del catálogo real: 6 plataformas y 13 destinos con medidas exactas, que tienes en Medidas de redes sociales: tamaños y proporciones.

Si la imagen ya tiene una URL accesible, la alternativa es POST /api/v1/images/process con source: { "type": "url", "value": "..." }. Con Drive suele ser menos cómodo porque obliga a firmar un enlace temporal.

Subir los resultados a otra carpeta

Cada URL de salida se descarga y se crea en la carpeta de destino con files.create, indicando parents y un media_body. Un patrón de nombre útil conserva el original y añade plataforma y formato:

original-instagram-post.webp
original-instagram-story.webp
original-linkedin-post.webp

Por defecto la salida es WebP (options.format); si la biblioteca de Drive prefiere JPG o PNG, fíjalo en la misma petición. Los criterios están en PNG, JPG o WebP: qué formato usar en cada red.

Requisitos de OAuth y de permisos

  • Scopes. Lectura de la carpeta de entrada con https://www.googleapis.com/auth/drive.readonly y escritura de la de salida. El scope drive.file solo alcanza ficheros que crea tu app o que el usuario elige con el selector de Drive; para escribir en una carpeta ya existente lo normal es el scope drive completo.
  • Cliente OAuth. Crea las credenciales en Google Cloud, configura la pantalla de consentimiento y usa access_type=offline y prompt=consent para obtener un token de refresco duradero. Guárdalo fuera del código.
  • Cuenta de servicio. Para procesos sin persona delante, crea una cuenta de servicio y comparte con su correo las dos carpetas. En Workspace puede requerir delegación en todo el dominio. En unidades compartidas añade supportsAllDrives=true e includeItemsFromAllDrives=true.
  • Límite de subida. 5 MB por fichero en SocialCutter; por encima responde 413.

Los nombres de scopes y de parámetros los fija Google; confírmalos en su documentación oficial: Guía de gestión de permisos de la API de Drive.

Snippet completo en Python

import io, json, os, requests
from google.oauth2.credentials import Credentials
from googleapiclient.discovery import build
from googleapiclient.http import MediaIoBaseDownload, MediaIoBaseUpload

SOURCE_FOLDER = "<ID_CARPETA_ENTRADA>"
DEST_FOLDER = "<ID_CARPETA_SALIDA>"
DESTINATIONS = [
    {"platform": "instagram", "format": "post"},
    {"platform": "instagram", "format": "story"},
    {"platform": "linkedin", "format": "post"},
]
SC_KEY = os.environ["SOCIALCUTTER_API_KEY"]

drive = build("drive", "v3",
              credentials=Credentials.from_authorized_user_file("token.json"))

files = drive.files().list(
    q=f"'{SOURCE_FOLDER}' in parents and trashed = false",
    orderBy="modifiedTime desc",
    fields="files(id, name)",
    pageSize=5,
).execute().get("files", [])

for f in files:
    buf = io.BytesIO()
    downloader = MediaIoBaseDownload(buf, drive.files().get_media(fileId=f["id"]))
    done = False
    while not done:
        _, done = downloader.next_chunk()

    r = requests.post(
        "https://api.socialcutter.theboomer.dev/api/v1/images/process/upload",
        headers={"X-API-Key": SC_KEY},
        files={"file": (f["name"], buf.getvalue(), "image/jpeg")},
        data={"destinations": json.dumps(DESTINATIONS)},
        timeout=90,
    )
    r.raise_for_status()

    for out in r.json()["outputs"]:
        img = requests.get(out["url"], timeout=90)
        img.raise_for_status()
        media = MediaIoBaseUpload(io.BytesIO(img.content),
                                  mimetype="image/webp", resumable=False)
        drive.files().create(
            body={"name": f"{f['name']}-{out['platform']}-{out['format']}.webp",
                  "parents": [DEST_FOLDER]},
            media_body=media,
            fields="id",
        ).execute()

Coste

  • 1 uso por destino (plataforma y formato) por imagen.
  • Destinos repetidos en la misma petición no se cobran dos veces.
  • Los procesamientos fallidos se devuelven.
  • Planes de 0, 3, 9 y 29 EUR, con API y servidor MCP incluidos.

Una imagen con los tres destinos del ejemplo consume 3 usos. Si llegan ráfagas a la carpeta, agrupa antes de llamar o usa POST /api/v1/images/batch.

Errores típicos

ErrorQué ocurreQué hacer
401 en SocialCutterLa clave falta o está revocadaRevisa la cabecera X-API-Key
413El fichero supera 5 MBReduce el maestro o divide el proceso
422Destinos mal formadosUsa platform y format del catálogo
429Cuota agotadaConsulta GET /api/v1/wallet
403 en DriveFalta scope o la cuenta no ve la carpetaComparte la carpeta o amplía el scope
invalid_grantToken de refresco caducado o revocadoVuelve a autorizar
Se reprocesa el mismo ficheroNo guardas la fecha del últimoPersiste el modifiedTime o usa el feed de cambios

Lo que SocialCutter no hace

El recorte es centrado y determinista: no hay detección de sujetos ni de rostros, ni recorte inteligente. No edita la imagen (no retoca color, no quita fondos, no compone texto), no publica en redes sociales y no acepta ficheros de más de 5 MB. Genera las versiones con las medidas exactas de cada destino y devuelve sus URLs: el intercambio con Drive y la publicación son de tu script.

Siguientes pasos

Preguntas frecuentes

¿Puedo vigilar una carpeta de Drive sin montar infraestructura?

Sí. Para una carpeta concreta, consulta la API de Drive con un filtro por carpeta ordenado por fecha. Si prefieres no codificar, el nodo Google Drive Trigger de n8n cubre el mismo caso sin servidor propio.

¿Qué permisos de Drive necesito?

Lectura para la carpeta de entrada (drive.readonly) y escritura para la carpeta de salida. El scope drive.file solo alcanza los ficheros que crea tu app o que el usuario elige a mano; para escribir en una carpeta ya existente, lo habitual es el scope drive completo.

¿Cómo llamo a SocialCutter si el fichero de Drive no tiene URL pública?

No hace falta URL pública. Descarga el binario con la API de Drive y súbelo por multipart a /api/v1/images/process/upload. El límite es 5 MB por fichero.

¿Vale una cuenta de servicio en lugar de un usuario?

Sí, para procesos sin persona delante. Crea la cuenta de servicio y comparte con su correo las dos carpetas. En Google Workspace puede hacer falta delegación en todo el dominio, y en unidades compartidas los parámetros supportsAllDrives e includeItemsFromAllDrives.

¿Cuánto cuesta cada imagen procesada?

1 uso por destino, es decir por cada combinación de plataforma y formato. Una imagen con tres destinos consume 3 usos. Los planes son 0, 3, 9 y 29 EUR e incluyen la API y el servidor MCP.