FFmpeg on Firebase Cloud Functions: Why It Breaks (and the Fix)

You're adding video processing to a Firebase app. You install a static FFmpeg binary, write a Cloud Function that triggers on upload, deploy it, and watch it die. The function times out, the binary bloats your deployment, and GCP bills you for memory you didn't actually need. This is one of the most common dead ends in the Firebase ecosystem.
Quick answer: Firebase Cloud Functions have a 60-second default timeout (540 seconds max in v2), 2 GB max memory, and no persistent filesystem. These constraints make FFmpeg transcoding unreliable or impossible for anything beyond trivial jobs. The fix is to call a cloud FFmpeg API like FFmpeg Micro from your Cloud Function instead of running the binary locally.
The Timeout Wall
Firebase Cloud Functions v1 default to a 60-second timeout. You can push that to 540 seconds (9 minutes) on v2 functions, and that's a hard cap you can't negotiate with Google.
Transcoding a 5-minute 1080p video to H.264 takes 8-15 minutes on the CPU allocation Cloud Functions gives you. That's not a pessimistic estimate. That's what happens on shared GCP infrastructure when you're running a compute-heavy encoder. A job that squeaks through at 8 minutes on one invocation might take 12 on the next because you don't control what else is running on the host.
For H.265 (HEVC) encoding, double those numbers. A 5-minute source video can easily run 20+ minutes. The 540-second ceiling doesn't come close.
Firebase Cloud Functions v2 timeout maxes out at 540 seconds. That's 9 minutes for a job that routinely takes 15.
The Memory and CPU Trap
Cloud Functions v2 gives you up to 32 GB of memory, but CPU allocation is tied to memory. At 2 GB memory, you get 1 vCPU. Want 2 vCPUs? You're paying for 4 GB of memory whether your function uses it or not.
FFmpeg encoding is CPU-bound, not memory-bound. A typical H.264 transcode uses 200-400 MB of RAM but wants every CPU cycle it can get. You end up over-provisioning memory just to get more CPU, and GCP bills you for every GB-second of that unused allocation.
The billing math gets ugly fast. A function configured for 8 GB memory (to get 2 vCPUs) running for 540 seconds costs roughly $0.0036 per invocation at current GCP pricing. Process 1,000 videos a day and you're looking at over $100/month just in Cloud Functions compute. And that's before your jobs time out and you have to handle retries.
Binary Bundling Problems
Getting FFmpeg into a Cloud Function is its own challenge. You have three options, and none of them are great.
Option 1: npm package. Packages like ffmpeg-static bundle a pre-compiled FFmpeg binary into node_modules. This adds 70-100 MB to your deployment package. Firebase deploys through Cloud Build, and large packages slow down every deploy. You're also trusting a third-party npm package to keep their binary builds current and free of vulnerabilities.
Option 2: Include the binary directly. You drop a statically compiled FFmpeg binary into your functions directory. Same size problem, plus you need to make sure the binary is compiled for the Cloud Functions runtime (Debian-based Linux, x86_64). Binaries compiled on macOS or Alpine won't work.
Option 3: Install at runtime. Some developers try downloading FFmpeg during cold starts. This adds 10-30 seconds to your cold start time and depends on external URLs being available. If the download server is slow or rate-limits you, your function fails before it even starts processing.
Cloud Functions has a maximum deployment size of 100 MB compressed (500 MB uncompressed) for source uploads. An FFmpeg binary plus its codecs can consume half that budget before you add your application code.
Cold Start Costs
Even when you get the binary bundled correctly, cold starts hurt. Cloud Functions need to load your entire deployment package into memory before your code runs. A function with a 70 MB FFmpeg binary in node_modules cold-starts in 5-10 seconds. A function with a few kilobytes of code calling an external API cold-starts in under a second.
If your video pipeline is event-driven, triggering on Cloud Storage uploads, users notice these cold starts. Someone uploads a video and expects processing to begin immediately. Instead, the first 8 seconds are just Cloud Functions unpacking your oversized deployment.
When Firebase Cloud Functions + FFmpeg Actually Works
For small, fast operations, Cloud Functions with FFmpeg is fine.
Extracting a single thumbnail frame from a video? Cloud Functions handles that in a couple seconds. Stripping the audio track from an MP4? Quick. Remuxing between container formats without re-encoding? No problem.
If your workload is limited to these lightweight tasks, a small FFmpeg binary with minimal codecs can work inside Cloud Functions. The trouble starts when you need actual transcoding.
The Fix: Call an API from Your Cloud Function
Instead of fighting Cloud Functions limits, keep your function small and offload the encoding. Your Cloud Function becomes a thin trigger layer. It receives the storage event, calls an API, and exits. No binary, no timeout pressure, no memory over-provisioning.
FFmpeg Micro is a cloud API that runs FFmpeg over HTTP. You send a POST with your inputs and encoding options, and get back processed video. No binary to bundle, no server to manage.
A complete Firebase Cloud Function using v2 onObjectFinalized that triggers when a video is uploaded to Cloud Storage and kicks off a transcode:
import { onObjectFinalized } from "firebase-functions/v2/storage";
import { defineSecret } from "firebase-functions/params";
import { getStorage } from "firebase-admin/storage";
import { initializeApp } from "firebase-admin/app";
import { getFirestore } from "firebase-admin/firestore";
initializeApp();
const ffmpegMicroKey = defineSecret("FFMPEG_MICRO_API_KEY");
export const processUploadedVideo = onObjectFinalized(
{
bucket: "my-app-videos",
secrets: [ffmpegMicroKey],
memory: "256MiB",
timeoutSeconds: 60,
},
async (event) => {
const { name, contentType } = event.data;
if (!contentType?.startsWith("video/")) {
return;
}
const bucket = getStorage().bucket(event.data.bucket);
const [signedUrl] = await bucket.file(name!).getSignedUrl({
action: "read",
expires: Date.now() + 60 * 60 * 1000,
});
const response = await fetch(
"https://api.ffmpeg-micro.com/v1/transcodes",
{
method: "POST",
headers: {
Authorization: `Bearer ${ffmpegMicroKey.value()}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
inputs: [{ url: signedUrl }],
outputFormat: "mp4",
preset: { quality: "high", resolution: "1080p" },
}),
}
);
const job = await response.json();
await getFirestore().collection("transcodeJobs").doc(job.id).set({
sourceFile: name,
jobId: job.id,
status: job.status,
createdAt: new Date(),
});
console.log(`Transcode job ${job.id} started for ${name}`);
}
);
This function is a few kilobytes. It deploys in seconds, cold-starts in under a second, and needs only 256 MB of memory. The actual encoding happens on FFmpeg Micro's infrastructure with no timeout ceiling to worry about.
You fire the request, get a job ID back, and store it in Firestore. To track completion, poll GET /v1/transcodes/{id} from a separate scheduled function or set up a webhook. The finished job gives you a download URL at GET /v1/transcodes/{id}/download.
If you need raw FFmpeg options instead of presets, swap the preset field for options:
body: JSON.stringify({
inputs: [{ url: signedUrl }],
outputFormat: "mp4",
options: [
{ option: "-c:v", argument: "libx264" },
{ option: "-crf", argument: "23" },
],
}),
For the same pattern applied to other serverless platforms, see FFmpeg on AWS Lambda and FFmpeg on Cloudflare Workers. If you're using Supabase alongside Firebase, check out our guide on auto-processing video uploads in Supabase Storage. Grab a free API key to try it.
FAQ
Can FFmpeg run inside Firebase Cloud Functions?
Yes, but with major limitations. You can bundle a static FFmpeg binary via npm packages like ffmpeg-static or include one directly in your deployment. It works for lightweight tasks like thumbnail extraction or audio stripping. For actual video transcoding, the 540-second max timeout, limited CPU, and deployment size constraints make it unreliable for anything beyond short clips.
What's the maximum timeout for Firebase Cloud Functions v2?
Firebase Cloud Functions v2 supports a maximum timeout of 540 seconds (9 minutes). V1 functions max out at 540 seconds as well, though the default is 60 seconds. Neither version supports the extended execution times that video transcoding typically requires.
How do I process video uploads in Firebase without hitting timeout limits?
Use your Cloud Function as a lightweight trigger that calls an external transcoding API. When a video is uploaded to Cloud Storage, the onObjectFinalized event fires your function, which sends the video URL to a service like FFmpeg Micro for processing. Your function finishes in under a second, and the encoding runs without any Firebase limits applying to it.
Why is my Firebase Cloud Function so slow to start when using FFmpeg?
Large deployment packages cause slow cold starts. An FFmpeg binary adds 70-100 MB to your function's deployment size. Cloud Functions must load the entire package into memory before your code runs, which means 5-10 second cold starts instead of sub-second. Removing the binary and calling an external API eliminates this overhead.
Can I use Firebase Extensions for video transcoding?
There's no official Firebase Extension for general-purpose FFmpeg transcoding. The "Resize Images" extension handles image processing but not video. For video, you either bundle FFmpeg yourself (with all the constraints covered above) or call an external API from a Cloud Function.
About Javid Jamae
Founder & CEO at FFmpeg Micro
Javid is a software engineer, author, and entrepreneur with over 25 years of professional software development experience across enterprise, startup, and consulting environments. He founded FFmpeg Micro to make video processing accessible to developers through a simple, automation-first REST API.
You might also like

FFmpeg on AWS Lambda: The Layer-Size and Timeout Problem
Why FFmpeg on AWS Lambda hits the 250MB layer limit, /tmp storage cap, and 15-minute timeout. Includes a working alternative using a managed FFmpeg API from your Lambda handler.

FFmpeg on Cloudflare Workers: Why It Fails (And the Fix)
FFmpeg can't run on Cloudflare Workers due to V8 isolate limits, bundle size caps, and WASM restrictions. The fix: call the FFmpeg Micro API from your Worker.

Auto-Process Video Uploads in Supabase Storage with FFmpeg Micro
Automate video compression and thumbnail extraction on Supabase Storage uploads using Edge Functions and the FFmpeg Micro API.
Ready to process videos at scale?
Start using FFmpeg Micro's simple API today. No infrastructure required.
Get Started Free