Tool · ffmpeg

Turn any clip into a YouTube Short with one ffmpeg command

Describe your clip, pick how to fill the 9:16 frame, and copy a command that outputs 1080×1920 H.264. Nothing is uploaded: this page only writes the command, you run it.

Your clip
Fill the 9:16 frame
Sound and text

Your command

Files: clip.mp4 in, short.mp4 out (plus music.mp3 / subs.srt if ticked). Rename yours or edit the names.

ffmpeg -hide_banner -y \
  -i clip.mp4 \
  -filter_complex "
[0:v]split=2[bgsrc][fgsrc];
[bgsrc]scale=1080:1920:force_original_aspect_ratio=increase,crop=1080:1920,boxblur=20:2[bg];
[fgsrc]scale=1080:1920:force_original_aspect_ratio=decrease:force_divisible_by=2[fg];
[bg][fg]overlay=(W-w)/2:(H-h)/2,setsar=1[v];
[0:a]loudnorm=I=-14:TP=-1.5:LRA=11[a]
" \
  -map "[v]" -map "[a]" \
  -c:v libx264 -preset medium -crf 18 -pix_fmt yuv420p \
  -c:a aac -b:a 192k -ar 48000 \
  -movflags +faststart short.mp4

What every line does

Updated with the command. Each numbered line is a piece of the command above and the reason for its numbers.

  1. -i clip.mp4

    Your clip: 1920×1080 at 30 fps, 45 s. Its own audio track is treated as the voice.

  2. [0:v]split=2[bgsrc][fgsrc]

    One decoded picture, two copies: one becomes the blurred background, the other the sharp foreground. A filter output can only be consumed once, which is why split is needed at all.

  3. [bgsrc]scale=…:increase,crop=1080:1920,boxblur=20:2[bg]

    The background: the same cover-and-crop as centre-crop mode (about 3413×1920, middle 1080×1920 kept), then boxblur with radius 20 applied twice (:2). Two passes of a box blur approximate a smooth Gaussian; one pass leaves visible blocky edges. Radius 20 is the vertical-video post's choice: shapes still read as colour, detail does not compete with the foreground. Higher radius costs more CPU on a 1080×1920 frame.

  4. [fgsrc]scale=1080:1920:force_original_aspect_ratio=decrease:force_divisible_by=2[fg]

    The foreground: shrunk until it FITS inside 1080×1920, so the whole original frame is kept. 1920×1080 becomes about 1080×607. force_divisible_by=2 rounds both sides to even numbers, because H.264 in yuv420p refuses odd dimensions.

  5. [bg][fg]overlay=(W-w)/2:(H-h)/2

    Centres the sharp copy on the blurred one. W and H are the background (1080×1920), w and h the foreground, so the offset is half the leftover space: about 657 px of blurred band above and below.

  6. setsar=1

    Marks the pixels as square. Without it a clip that had non-square pixels (common in DV, HDV and some broadcast footage) can still carry its old aspect flag and display squashed, even though the frame is 1080×1920.

  7. loudnorm=I=-14:TP=-1.5:LRA=11

    Evens out the loudness to −14 LUFS integrated, the playback level YouTube is widely measured to normalise to, with true peaks kept under −1.5 dBTP so AAC encoding does not clip. Honest limit: in this single-pass form loudnorm adjusts gain as it goes, so it lands near −14 rather than exactly on it, and very short clips have little to measure. For an exact figure, run it once with print_format=json and feed the measured_ values into a second pass.

  8. -c:v libx264 -preset medium -crf 18 -pix_fmt yuv420p

    H.264, the codec every Shorts, Reels and TikTok upload path accepts. CRF 18 is close to visually lossless, which matters because YouTube re-encodes whatever you send and you want to hand it clean pixels. yuv420p is the pixel format phones decode in hardware; without it some sources come out 4:4:4 and fail to play on many devices.

  9. -c:a aac -b:a 192k -ar 48000

    AAC at 192 kbps, 48 kHz. The -ar matters when loudnorm is on: that filter works at 192 kHz internally and would otherwise hand the encoder a 192 kHz stream.

  10. -movflags +faststart

    Moves the MP4 index to the front of the file so a preview can start playing before the whole file has downloaded. Costs one extra pass over the file at the end.

What has actually been run

The generator behind this page is one JavaScript module, and dankdev's test suite imports the same module and runs its output with ffmpeg 4.4.2 for eight cases, each on a synthetic 3-second clip (a test pattern plus a gated 220 Hz tone standing in for a voice): 1920×1080 centre crop; 1920×1080 blurred fill with ducked music; 3840×2160 letterbox; 1280×720 blurred fill with subtitles; a 29.97 fps clip; an already-vertical 1080×1920 clip; a clip with no sound; and a silent clip with music only.

For each one the test checks with ffprobe that the output is 1080×1920, has an audio stream and is about 3 seconds long (the 2-second music file has to loop to cover it). It also checks that the 29.97 fps clip stays at 30000/1001, that the subtitle render differs from the same frame without subtitles, and that in the ducked mix the music band measures at least 6 dB lower while the voice tone plays than in the gaps.

What it does not check: that loudnorm hits exactly −14 LUFS (a single pass on 3 seconds is no loudness test; what one pass and two passes measured), how the picture looks, or anything on YouTube's side. Your real footage, fonts and codecs are yours to try.

The posts behind the numbers

Sources

The ffmpeg documentation for every filter and option this page can put in a command: