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:
- Detectar la imagen nueva en la carpeta de entrada.
- Descargar el binario.
- Procesarlo con SocialCutter.
- 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:
filecon el binario ydestinationscon 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.readonlyy escritura de la de salida. El scopedrive.filesolo 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 scopedrivecompleto. - Cliente OAuth. Crea las credenciales en Google Cloud, configura la pantalla de consentimiento y usa
access_type=offlineyprompt=consentpara 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=trueeincludeItemsFromAllDrives=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
| Error | Qué ocurre | Qué hacer |
|---|---|---|
| 401 en SocialCutter | La clave falta o está revocada | Revisa la cabecera X-API-Key |
| 413 | El fichero supera 5 MB | Reduce el maestro o divide el proceso |
| 422 | Destinos mal formados | Usa platform y format del catálogo |
| 429 | Cuota agotada | Consulta GET /api/v1/wallet |
| 403 en Drive | Falta scope o la cuenta no ve la carpeta | Comparte la carpeta o amplía el scope |
| invalid_grant | Token de refresco caducado o revocado | Vuelve a autorizar |
| Se reprocesa el mismo fichero | No guardas la fecha del último | Persiste 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
- Tamaños y proporciones: Medidas de redes sociales: tamaños y proporciones
- Los caminos reales de automatización: Automatizar imágenes para redes sociales
- Código: Automatiza SocialCutter con Python
- No-code: Automatiza el recorte de imágenes con n8n
- Documentación de la API: https://docs.socialcutter.theboomer.dev
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.