FFmpeg jobs on Deno

Run FFmpeg on Supabase Edge

This is the whole integration. One HTTP request offloads the command and returns right away, so your Edge Function stays inside the Deno sandbox limits.

FFmpeg API guide Updated June 2026
// supabase/functions/transcode/index.ts
import { createClient } from "npm:@rendobar/sdk";
Deno.serve(async (req) => {
const { videoUrl } = await req.json();
const rb = createClient({ apiKey: Deno.env.get("RENDOBAR_API_KEY")! });
// Offload the command, return right away.
const job = await rb.jobs.create({
type: "raw.ffmpeg",
params: { command: `ffmpeg -i ${videoUrl} -vn -c:a libmp3lame audio.mp3` },
});
return Response.json({ jobId: job.id });
});

Why the local approach breaks

You can't spawn FFmpeg inside a Supabase Edge Function. They run on the Supabase Edge Runtime, a Deno-compatible V8 isolate with no shell. Deno.Command is blocked on the hosted runtime, and there's no native ffmpeg binary to call.

ffmpeg.wasm doesn't rescue it either. The core is tens of megabytes of WebAssembly, and a real transcode runs past the function's 256 MB memory ceiling and its CPU limit. The offload version is the snippet at the top of this page.

Spawn with Deno.Command Blocked on the edge
// supabase/functions/transcode/index.ts
Deno.serve(async (req) => {
const { videoUrl } = await req.json();
// Deno can spawn subprocesses locally, but the hosted Supabase
// Edge Runtime blocks Deno.Command and ships no ffmpeg binary.
// In production this throws before a frame is decoded.
const cmd = new Deno.Command("ffmpeg", {
args: ["-i", videoUrl, "-vn", "-c:a", "libmp3lame", "out.mp3"],
});
await cmd.output(); // never runs on the edge
return new Response("never gets here");
});

What happens after you submit

  1. 01

    Submit the command

    Your Edge Function calls rb.jobs.create with type "raw.ffmpeg" and your command string. It's one HTTPS request, so the function returns before the video is processed and stays inside the wall-clock and CPU limits.

  2. 02

    A sandboxed container runs it

    Rendobar runs the exact FFmpeg command in an isolated container built for media work. Full codecs, no 256 MB memory ceiling, none of the Edge Runtime limits.

  3. 03

    The result is stored, a URL comes back

    When the command finishes, the output is stored and the job result carries its URL. Read it from the webhook, then drop it into Supabase Storage or stream it to your user.

  4. 04

    A webhook fires

    Rendobar POSTs the finished job to the endpoint you registered. Your function never had to wait, so it stays well under the execution limit.

Or fire it straight from your database

You don't have to call it from a function at all. A Postgres trigger can submit the job the moment a file lands in Storage, using pg_net. The result URL comes back on your webhook, ready to write into the row.

-- Fire the Edge Function the moment a file lands in Storage
create function notify_transcode() returns trigger
language plpgsql as $$
begin
perform net.http_post(
url := 'https://<project>.supabase.co/functions/v1/transcode',
body := json_build_object('videoUrl', new.name)::text,
headers := '{"Authorization": "Bearer <anon-key>"}'::jsonb
);
return new;
end;
$$;
create trigger on_storage_upload
after insert on storage.objects
for each row execute function notify_transcode();

Ways to run FFmpeg on Supabase Edge, compared

ApproachWorks on the edge?Why
Deno.Command to spawn ffmpeg NoSubprocess is blocked on the hosted runtime
ffmpeg.wasm in the function NoTens of MB, CPU and memory limited
Install a native binary NoNo shell or package install on the edge
Rendobar API (offload) YesOne fetch, fits the sandbox

Frequently asked questions

Why can't I run FFmpeg in a Supabase Edge Function?

Edge Functions run on the Supabase Edge Runtime, a Deno-compatible V8 isolate. There's no shell, Deno.Command is blocked on the hosted runtime, and there's no native ffmpeg binary to call. Offloading the command keeps the function inside those limits.

What about ffmpeg.wasm in the function?

Rendobar skips it for you. The ffmpeg.wasm core is tens of megabytes, and a real transcode blows past the Edge Function's 256 MB memory ceiling and its CPU limit before it finishes.

Can I trigger a job from a Postgres change or a file upload?

Yes. Any path that makes an HTTPS request can submit a job. A database webhook or a Postgres trigger using pg_net can fire your Edge Function on a row change, and hooking it to inserts on storage.objects starts a job the moment a file uploads.

How do I get the output back?

Register a webhook endpoint once (rb.webhooks.create) and Rendobar POSTs each finished job to it. You can also poll GET /jobs/{id}, subscribe with the realtime SDK, or drop the result into Supabase Storage.

What does it cost?

Jobs are billed by compute time. Every account begins with $5 in free credits and no credit card, so you can run a real transcode before paying anything.

The call is a plain HTTPS request, so the same offload runs from every serverless host. Pick your runtime and follow the guide.

Ship FFmpeg on Supabase today

$5 free on signup. No credit card. No subprocess needed.