ffmpeg on Netlify Functions

ffmpeg on Netlify Functions: too big to bundle, hosted for you instead.

Netlify Functions run on AWS Lambda, so ffmpeg blows the bundle limit and the default timeout. Hand the job to Fotovid: one request out, a ready result URL back — well under any timeout.

// netlify/functions/watermark.mts
export default async (req: Request) => {
  const { videoUrl, logoUrl } = await req.json();

  const res = await fetch("https://api.fotovid.co/v1/video/watermark", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${Netlify.env.get("FOTOVID_API_KEY")}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      source_url: videoUrl,
      params: { type: "image", watermark_image_url: logoUrl, position: "bottom-right" },
    }),
  });

  const { url } = await res.json();
  return Response.json({ url });
};

Why ffmpeg on Netlify keeps failing

Netlify Functions execute on AWS Lambda, and that's exactly where ffmpeg runs into walls. A static ffmpeg binary is far too big for the ~50MB zipped / 250MB unzipped bundle limit, so the deploy either fails or the binary silently doesn't ship. Even when you squeeze it in, the default 10s function timeout kills any real transcode — background functions buy you 26s, which still isn't enough for most video work. It's the classic 'works on my laptop, times out in prod' trap.

  • ffmpeg binary + libs exceed the Lambda 250MB unzipped bundle limit
  • 10s default timeout (26s background) kills real transcodes mid-run
  • Cold starts and layer wrangling add latency and packaging pain
  • Local success doesn't reproduce in the deployed function

Ways teams try to run ffmpeg on Netlify

Before Fotovid these were the options — each one is work you'd rather not own.

OptionWhat it costs youVerdict
Bundle ffmpeg into your Netlify functionExceeds the 250MB bundle and hits the 10s function timeout
Self-host a container or VMAlways-on cost plus patching, scaling, and monitoring
Run a job queue + workerNew infra: a queue, workers, retries, dead-letter handling
Transcode in the browser (WASM)Slow, memory-hungry, and crashes on mobile
Call the Fotovid APIOne HTTPS request; nothing to run, package, or scale
How it works

Your first call in three steps

  1. 1
    Grab a free API key

    Sign up and create a key. You authenticate with an Authorization: Bearer p6_<key_id>:<secret> header — no binaries, no Lambda layers, nothing to bundle into your Netlify Function.

  2. 2
    POST your video to the watermark endpoint

    From inside your Netlify Function, call POST /v1/video/watermark on https://api.fotovid.co. Send the standard envelope: a source_url pointing to your input video plus a params object — set type to image, text, or combo, then pick a position like bottom-right, plus opacity, scale, and padding. Fotovid does the ffmpeg work off-platform, so your function just makes one fast HTTPS request instead of shelling out to a binary it can't ship.

  3. 3
    Use the hosted result URL

    The response is flat JSON with an id, type, url, and expires_at. The url points to the finished, Fotovid-hosted video. Return it to your client or store your own copy — since results are hosted temporarily, download and re-persist it wherever you keep assets.

Frequently asked questions

Ship it with one API call

Grab a free key and make your first call in under five minutes.