# 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.
- URL: https://socialcutter.theboomer.dev/guias/google-drive/
- Idioma: es
- Familia: ia
- Actualizado: 2026-09-24
- Palabras clave: 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](/guias/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](/guias/medidas-redes-sociales/).

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](/guias/formatos-redes-sociales/).

## 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](https://developers.google.com/drive/api/guides/manage-sharing).

## Snippet completo en Python

```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](/guias/medidas-redes-sociales/)
- Los caminos reales de automatización: [Automatizar imágenes para redes sociales](/guias/automatizar-imagenes-redes-sociales/)
- Código: [Automatiza SocialCutter con Python](/guias/python/)
- No-code: [Automatiza el recorte de imágenes con n8n](/guias/n8n/)
- Documentación de la API: https://docs.socialcutter.theboomer.dev