Build a user upload pipeline

“Darkroom” (a photo/video app like VSCO) accepts uploads from users and needs to produce optimized versions for display, download, and streaming.

A typical pipeline for each upload:

  1. Convert video to web-ready MP4
  2. Generate a thumbnail
  3. Create a low-res preview

API — three tasks per upload

Video conversion:

ittybit video \
  -i https://darkroom-app.com/uploads/clip.mov \
  --width 1920 \
  --format mp4 \
  --quality high \
  --cloud
const task = {
  input: "https://darkroom-app.com/uploads/clip.mov",
  kind: "video",
  options: {
    width: 1920,
    format: "mp4",
    quality: "high",
  },
};

const res = await fetch("https://api.ittybit.com/tasks", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.ITTYBIT_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify(task),
});
const data = await res.json();
import requests

task = {
    "input": "https://darkroom-app.com/uploads/clip.mov",
    "kind": "video",
    "options": {
        "width": 1920,
        "format": "mp4",
        "quality": "high",
    },
}

res = requests.post(
    "https://api.ittybit.com/tasks",
    headers={"Authorization": f"Bearer {api_key}"},
    json=task,
)
data = res.json()
TASK='{
  "input": "https://darkroom-app.com/uploads/clip.mov",
  "kind": "video",
  "options": {
    "width": 1920,
    "format": "mp4",
    "quality": "high"
  }
}'

curl -X POST https://api.ittybit.com/tasks \
  -H "Authorization: Bearer $ITTYBIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d "$TASK"

Thumbnail:

{"input": "https://darkroom-app.com/uploads/clip.mov", "kind": "image", "options": {"start": 2, "width": 640, "format": "webp"}}

Preview:

{"input": "https://darkroom-app.com/uploads/clip.mov", "kind": "video", "options": {"width": 480, "quality": "low", "format": "mp4"}}

Fire all three in parallel. Each returns a task ID you can poll or receive via webhook.

CLI

ittybit video \
  -i clip.mov \
  -o clip-hd.mp4 \
  --width 1920 \
  --quality high

ittybit image \
  -i clip.mov \
  -o clip-thumb.webp \
  --start 2 \
  --width 640

ittybit video \
  -i clip.mov \
  -o clip-preview.mp4 \
  --width 480 \
  --quality low

For image uploads

Same pattern, different kinds:

ittybit image \
  -i photo.png \
  -o photo-full.webp \
  --width 1920 \
  --quality high

ittybit image \
  -i photo.png \
  -o photo-thumb.webp \
  --width 320 \
  --quality medium

With S3 storage

Read from your upload bucket, write processed files back:

ittybit video \
  -i s3://uploads/clip.mov \
  -o s3://processed/clip-hd.mp4 \
  --width 1920 \
  --format mp4 \
  --quality high \
  --cloud
const task = {
  input: "s3://uploads/clip.mov",
  kind: "video",
  options: {
    width: 1920,
    format: "mp4",
    quality: "high",
  },
  output: "s3://processed/clip-hd.mp4",
};

const res = await fetch("https://api.ittybit.com/tasks", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.ITTYBIT_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify(task),
});
const data = await res.json();
import requests

task = {
    "input": "s3://uploads/clip.mov",
    "kind": "video",
    "options": {
        "width": 1920,
        "format": "mp4",
        "quality": "high",
    },
    "output": "s3://processed/clip-hd.mp4",
}

res = requests.post(
    "https://api.ittybit.com/tasks",
    headers={"Authorization": f"Bearer {api_key}"},
    json=task,
)
data = res.json()
TASK='{
  "input": "s3://uploads/clip.mov",
  "kind": "video",
  "options": {
    "width": 1920,
    "format": "mp4",
    "quality": "high"
  },
  "output": "s3://processed/clip-hd.mp4"
}'

curl -X POST https://api.ittybit.com/tasks \
  -H "Authorization: Bearer $ITTYBIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d "$TASK"