Subir archivos — Convierte un archivo local en una URL pública para FFHub
Convierte un archivo local en una URL pública que FFHub pueda leer.
Los workers de FFHub se ejecutan en la nube y solo aceptan entradas que sean URLs públicas. Si tu archivo está en tu laptop, en tu teléfono o en un bucket privado, primero súbelo al almacenamiento de FFHub y pasa la URL devuelta a tu comando ffmpeg.
Cómo funciona la subida
Son dos pasos, y el archivo nunca pasa por nuestros servidores. Tu cliente obtiene una URL firmada de un solo uso y hace PUT directamente a R2.
- Firmar.
POST /v1/uploads/signdevuelve una URL prefirmada válida por 15 minutos. - PUT. Sube los bytes a esa URL con
curl,fetcho cualquier cliente HTTP.
Esto te permite subir archivos de hasta 5 GB sin que nuestros servidores intervengan en la transferencia de datos.
Paso 1 — Obtén una URL firmada
curl -X POST https://api.ffhub.io/v1/uploads/sign \
-H "Authorization: Bearer $FFHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"filename": "input.mp4",
"size": 12345678,
"content_type": "video/mp4"
}'
Respuesta:
{
"upload_url": "https://...r2.cloudflarestorage.com/...?X-Amz-Signature=...",
"public_url": "https://storage.ffhub.io/tmp/uploads/<user>/<rand>.mp4",
"key": "tmp/uploads/<user>/<rand>.mp4",
"content_type": "video/mp4",
"expires_at": "2026-05-12T05:30:00Z"
}
Paso 2 — Sube el archivo
curl -X PUT "$UPLOAD_URL" \
-H "Content-Type: video/mp4" \
--data-binary "@./input.mp4"
El encabezado Content-Type debe coincidir exactamente con el content_type que enviaste en el paso 1 — R2 rechaza la firma si no coincide.
Una vez que el PUT devuelva 200/204, el campo public_url del paso 1 ya estará disponible para lectura.
Ejemplo completo de principio a fin
FILE=./input.mp4
SIZE=$(stat -f%z "$FILE" 2>/dev/null || stat -c%s "$FILE")
# 1. Firmar
SIGNED=$(curl -s -X POST https://api.ffhub.io/v1/uploads/sign \
-H "Authorization: Bearer $FFHUB_API_KEY" \
-H "Content-Type: application/json" \
-d "{\"filename\":\"input.mp4\",\"size\":$SIZE,\"content_type\":\"video/mp4\"}")
UPLOAD_URL=$(echo "$SIGNED" | jq -r '.upload_url')
PUBLIC_URL=$(echo "$SIGNED" | jq -r '.public_url')
# 2. Subir directamente a R2
curl -X PUT "$UPLOAD_URL" \
-H "Content-Type: video/mp4" \
--data-binary "@$FILE"
# 3. Enviar una tarea usando public_url como entrada
curl -X POST https://api.ffhub.io/v1/tasks \
-H "Authorization: Bearer $FFHUB_API_KEY" \
-H "Content-Type: application/json" \
-d "{\"command\":\"-i $PUBLIC_URL -c:v libx264 -crf 28 output.mp4\"}"
El CLI hace todo este proceso automáticamente — consulta CLI.
Límites
- Tamaño máximo: 5 GB por subida (límite de single-PUT en R2)
- Validez de la URL firmada: 15 minutos a partir de
expires_at; vuelve a firmar si se vence - Tiempo de vida del archivo: 7 días, luego se elimina de R2
Si necesitas conservar los archivos más de 7 días, cópialos a tu propio bucket en cuanto la tarea finalice.
¿Ya tienes una URL pública?
Omite todo el flujo. La API de tareas acepta cualquier URL pública como entrada -i:
curl -X POST https://api.ffhub.io/v1/tasks \
-H "Authorization: Bearer $FFHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{"command":"-i https://example.com/clip.mp4 -c:v libx264 output.mp4"}'
Tu S3, tu CDN, nuestro almacenamiento — todos son equivalentes. Al módulo de tareas no le importa dónde vivan los bytes.