ffmpegvideo-apiai-video

The fal.ai FFmpeg API merges clips. It can't burn captions.

·Javid Jamae·10 min read
The fal.ai FFmpeg API merges clips. It can't burn captions.

Three clips come back from Kling or Veo, none of them the same length, one of them a different resolution than the other two. Now you need a single 9:16 file with a music bed under it and captions burned in. fal ships an FFmpeg API in the same account you're already billing generations to, so doing the stitch there means one less vendor and one less key.

Quick answer: The fal ai ffmpeg api (fal-ai/ffmpeg-api) exposes two operations, compose and merge-videos, billed at $0.0002 per second, with width and height accepted between 512 and 2048 pixels. It's the right call when your clips are already generated on fal and the job is a straight stitch with a track laid under it. When the job needs an arbitrary filter graph, styled burned-in subtitles, loudness normalization, or HLS output, send it to a full FFmpeg surface like FFmpeg Micro as one API call instead.

What fal's FFmpeg API actually covers

fal's FFmpeg API is a two-operation assembly endpoint, not a general FFmpeg wrapper. Compose takes a track list of video and audio segments with timestamps and renders them into one file. Merge-videos concatenates a list of URLs. Both accept a target width and height between 512 and 2048 pixels, and both bill at $0.0002 per second.

That narrowness is a deliberate product decision, and it matches how most people arrive at the endpoint. They aren't searching for an FFmpeg API. They're in an n8n workflow that already calls fal for generation, and the merge step is the last thing standing between them and a finished video. n8n's own template gallery documents this pattern: template 13895, "Automated AI Long Video Creator," routes its merge through Fal.run's FFmpeg API, and templates 6918, 5916, and 11710 (the Kling 2.1 UGC extend-and-merge workflow) do the same. There's a thread on community.n8n.io, 188008, where a builder asks flat out for a fal endpoint that merges audio, video, and subtitles together.

That thread is the whole scoping question in one post. Merging audio and video is inside the operation surface. Burning subtitles onto the result, with a font, an outline, and a vertical position, is not.

The same three-clip stitch, written both ways

The job is concrete: three vertical clips at mixed resolutions, normalized to 1080x1920 at 30 fps, joined, a looping music bed at 25% volume, and an SRT burned in. In raw FFmpeg, that's one filter graph:

ffmpeg -i clip1.mp4 -i clip2.mp4 -i clip3.mp4 -stream_loop -1 -i bed.mp3 \
  -filter_complex "\
[0:v]scale=1080:1920:force_original_aspect_ratio=decrease,\
pad=1080:1920:(ow-iw)/2:(oh-ih)/2,setsar=1,fps=30[v0];\
[1:v]scale=1080:1920:force_original_aspect_ratio=decrease,\
pad=1080:1920:(ow-iw)/2:(oh-ih)/2,setsar=1,fps=30[v1];\
[2:v]scale=1080:1920:force_original_aspect_ratio=decrease,\
pad=1080:1920:(ow-iw)/2:(oh-ih)/2,setsar=1,fps=30[v2];\
[v0][v1][v2]concat=n=3:v=1:a=0[vcat];\
[vcat]subtitles=captions.srt:force_style='Fontsize=18,Outline=2,MarginV=120'[vout];\
[3:a]volume=0.25[bed]" \
  -map "[vout]" -map "[bed]" -shortest \
  -c:v libx264 -crf 20 -preset veryfast -pix_fmt yuv420p \
  -c:a aac -b:a 192k out.mp4

Every clause in that graph is load-bearing. Drop setsar=1 and clips with different sample aspect ratios refuse to concat. Drop fps=30 and a 24 fps generation joined to a 30 fps one produces timestamp drift you'll notice by the third cut. Drop -shortest and -stream_loop -1 runs the music forever. The longer version of why this graph looks the way it does is in FFmpeg Concat Different Resolutions: Normalize, Then Copy.

On fal, the compose endpoint handles the concat and the audio bed. You build a tracks array, set the output width and height, and submit. The subtitles filter has no equivalent in that request body, so the captions step has to happen somewhere else, either before the merge (burned into each clip individually, which means re-encoding three times and hoping the caption timings still line up after the join) or after it, on a second service.

FFmpeg Micro takes the graph itself. You submit the whole thing as one job and get a URL back:

curl -X POST https://api.ffmpeg-micro.com/v1/jobs \
  -H "Authorization: Bearer $FFMPEG_MICRO_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "inputs": [
      "https://cdn.example.com/clip1.mp4",
      "https://cdn.example.com/clip2.mp4",
      "https://cdn.example.com/clip3.mp4",
      "https://cdn.example.com/bed.mp3",
      "https://cdn.example.com/captions.srt"
    ],
    "command": "-stream_loop -1 -i {{3}} -filter_complex \"...\" -map \"[vout]\" -map \"[bed]\" -shortest -c:v libx264 -crf 20 -pix_fmt yuv420p out.mp4",
    "webhook": "https://your-n8n.example.com/webhook/render-done"
  }'
{ "id": "job_8f2c41", "status": "queued" }

No encoder to host, no worker to scale, no 30-second automation timeout to design around, and the webhook lands in n8n when the render finishes. The docs have the full request shape and the job lifecycle. If you'd rather see the graph render before you wire anything, the playground runs it in the browser.

The jobs fal's compose endpoint can't express

A two-operation surface covers assembly and stops there. Everything below is routine FFmpeg work that has no representation in a tracks array, which means it lands on a second service or on your own container regardless of how the merge went.

Jobfal FFmpeg APIFull FFmpeg surface
Concat clips, lay an audio bedYes (compose, merge-videos)Yes
Burn styled subtitles (`subtitles`, `drawtext`)NoYes
Loudness normalization (`loudnorm` to -14 LUFS)NoYes
Crossfade transitions (`xfade`)NoYes
Watermark or logo overlay with scalingNoYes
Ken Burns push-in on stills (`zoompan`)NoYes
Palette-optimized GIF, HLS ladder, two-pass VBRNoYes
Output above 2048px on either axisNoYes

The 2048-pixel ceiling matters more than it looks. A 4K master, a 2160-pixel-tall vertical export, or a 1440p YouTube upload all sit outside it. For social shorts at 1080x1920 you'll never touch the limit; for anything that has to survive a client's delivery spec, you will.

Loudness is the one that quietly breaks published work. AI-generated clips come back at wildly different levels, and stacking them next to a music bed without running loudnorm produces a video where the second cut is twice as loud as the first. That fix is a filter, not an assembly parameter, and the audio bed walkthrough covers the two-pass version.

Per-second model billing versus job pricing

fal's $0.0002 per second is priced like the generation models sitting next to it, which makes the arithmetic easy and the scaling linear. A 30-second short costs $0.006 to compose. A 10-minute long-form assembly costs $0.12. Run 500 shorts a month and the merge line on your invoice is $3.

The number itself is cheap. What it doesn't cover is the second vendor you now need for captions, loudness, and watermarks, because a per-operation price only tells you the cost of the operations that exist. Two pipelines, two keys, two sets of retry logic, and two places to look when a render comes back wrong is the real cost, and it doesn't show up on either bill.

FFmpeg Micro runs on a free tier to start and usage-based pricing after, with one job covering the entire graph rather than one line item per operation. The comparison worth making isn't cents per second against cents per second. It's how many services the finished video passed through.

When fal is genuinely the better call

If every clip in your pipeline is generated on fal and the assembly is a straight concat with a track underneath, use the merge endpoint. You're already authenticated, the outputs are already in fal's storage, and moving files to a second service to do something the first one can do is work for its own sake.

The line is the operation surface, not the vendor count. The moment a requirement appears that a tracks array can't describe, and burned captions is usually the first one, you've got a second service in the pipeline anyway. At that point picking the one with the full FFmpeg surface and letting it do the merge too is one pipeline instead of two.

The same logic applies in reverse. If you're self-hosting a container to get captions and paying fal for merges, you're running infrastructure to fill a gap. That tradeoff is worked through in The NCA Toolkit is free. Self-hosting it isn't cheap.

Common pitfalls when merging AI-generated clips

Most broken AI-video assemblies fail for the same handful of reasons, and none of them are the merge call itself. These are the ones worth checking before you debug anything else:

  1. Mismatched sample aspect ratio. Two clips at 1080x1920 can still refuse to concat if their SAR differs. Force setsar=1 on every input before joining.
  2. Variable frame rate output. Generation models emit VFR often enough that you should assume it. Force CFR with fps=30 in the filter chain, not with -r on the output, or your audio drifts a few frames per cut.
  3. Clamping to the 512-2048 window. Ask a compose endpoint for a 2160-pixel-tall output and you get an error, not a downscale. Decide your delivery resolution before you pick where the merge runs.
  4. Silent clips with an audio stream. Some models return a silent AAC track, some return no track at all. A concat filter with a=1 fails on the mixed case. Map audio explicitly instead.
  5. Captions timed against the wrong timeline. Burn subtitles after the concat, using timings measured on the joined file. Burning per-clip and then joining shifts every cue after the first cut.

Once those five are handled, the merge is boring, which is the goal. The end-to-end n8n clip workflow shows the whole chain wired with URLs and webhooks so nothing large moves through the automation runtime.

FAQ

What is the fal ai ffmpeg api?

The fal ai ffmpeg api is the fal-ai/ffmpeg-api model on fal, which exposes a compose endpoint for building a video from a timestamped track list and a merge-videos endpoint for concatenating a list of video URLs. Both bill at $0.0002 per second and accept output width and height between 512 and 2048 pixels.

Can fal's FFmpeg API burn subtitles onto a video?

fal's FFmpeg API has no subtitle-burning operation. Compose and merge-videos handle assembly and audio placement, so styled captions rendered with FFmpeg's subtitles or drawtext filters need a service that accepts an arbitrary filter graph, or your own FFmpeg build.

What's the best fal ai ffmpeg alternative for full FFmpeg operations?

Any hosted service that accepts a complete FFmpeg filter graph rather than a fixed set of operations works as a fal ai ffmpeg alternative. FFmpeg Micro takes the graph as a single job over REST, from n8n, Make, Zapier, or an MCP-connected AI agent, and returns a URL when the render completes.

Does fal compose handle clips at different resolutions?

fal's compose endpoint renders to a single target width and height, so mixed-resolution inputs are fitted to that canvas. What it doesn't give you is control over how, meaning you can't choose between padding with bars and cropping to fill, and you can't force a uniform SAR or frame rate before the join.

How much does merging three AI-generated clips cost?

Merging three clips into a 30-second video on fal costs about $0.006 at $0.0002 per second. The cost that matters more is the second service you add for captions, loudness normalization, or watermarks, since a merge-only endpoint prices only the merge.

If the video coming out of your generation step still needs captions, a normalized audio bed, or a watermark before it ships, that's one job on FFmpeg Micro instead of two vendors. See how the full FFmpeg surface compares to merge-only APIs, or run your first graph on the free tier: sign up free.

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.

Software EngineeringVideo ProcessingFFmpegCloud ArchitectureAPI DesignAutomation

Skip the command line

The Auto Captions blueprint transcribes your video and burns the captions in. You just review the transcript.

Run it (free)