Automation and APIs for video creators
Video format and codec for short clips: an ffmpeg guide
Short clips are small files, but they get re-encoded by every platform they touch. Your job is to hand each platform a clean, predictable master so its encoder has the best possible input. This guide covers the decisions that matter and the ffmpeg commands that implement them.
Every platform number below is taken from an official page, linked where it appears. All ffmpeg commands were run against ffmpeg 8.1 with libx264, libx265 and libsvtav1.
Container vs codec
A file like clip.mp4 has two layers. The container (MP4, MOV, WebM, MKV) holds streams, timestamps and an index. The codecs describe how each stream is compressed: H.264, HEVC or AV1 for video, AAC or Opus for audio. Platforms specify both, and a file can be rejected or reprocessed badly when either is off.
For short clips, MP4 is the safe default. It is listed by YouTube, Instagram and TikTok in the pages cited below, and every browser plays H.264 in MP4.
Put the index at the front
MP4 files store their index in a box called moov. By default ffmpeg writes it at the end. -movflags +faststart runs a second pass that moves it to the beginning (the ffmpeg formats documentation describes this option), so a player or an upload processor can start reading immediately. YouTube's recommended upload encoding settings ask for exactly this: MP4, no edit lists, moov atom at the front. Meta's Reels specs say the same.
You can confirm the box order with ffprobe:
ffprobe -v trace clip.mp4 2>&1 | grep -m2 -oE "type:'(moov|mdat)'"
# type:'moov' <- index first: good
# type:'mdat'
Codecs: H.264, HEVC and AV1
| Codec | ffmpeg encoder | Strength | Watch out for |
|---|---|---|---|
| H.264 (AVC) | libx264 | Plays everywhere, recommended by YouTube for uploads, accepted by Instagram and TikTok | Larger files than newer codecs at similar quality |
| HEVC (H.265) | libx265 | Smaller files at similar quality, accepted by Instagram Reels and TikTok's API | Slower to encode; Apple players expect the hvc1 tag |
| AV1 | libsvtav1 | Efficient, royalty free, good for your own web delivery | Not listed as an upload codec on the platform pages cited here |
The practical answer for upload masters is H.264. Use HEVC when file size matters and the destination lists it. Use AV1 for clips you serve from your own site to browsers that support it, or for archives, and keep an H.264 version for everything else.
What the platforms document
YouTube
The YouTube upload encoding page recommends H.264 with progressive scan, High Profile, 2 consecutive B-frames, a closed GOP of half the frame rate, CABAC, variable bitrate and 4:2:0 chroma subsampling. Audio should be AAC-LC (Opus and Eclipsa Audio are also listed) at 48 kHz. For SDR 1080p it recommends 8 Mbps at 24, 25 or 30 fps and 12 Mbps at 48, 50 or 60 fps. Frame rate should match the recording, and interlaced footage should be deinterlaced first.
For Shorts, YouTube Help says square or vertical videos up to three minutes count as Shorts. The bitrate table above is written for standard 1080p; a 1080x1920 vertical clip has the same pixel count, so it is a reasonable guide, but that is our inference, not a YouTube statement.
Instagram Reels
Meta's IG User Media reference lists these Reel specs for API publishing: MOV or MP4 with no edit lists and moov at the front; HEVC or H.264, progressive, closed GOP, 4:2:0; 23 to 60 FPS; at most 1920 horizontal pixels; aspect ratio between 0.01:1 and 10:1 with 9:16 recommended; video VBR at most 25 Mbps; AAC audio at up to 48 kHz, mono or stereo, 128 kbps; 3 seconds to 15 minutes; up to 300 MB.
TikTok
The Content Posting API media transfer guide accepts MP4 (recommended), WebM and MOV, with H.264 (recommended), H.265, VP8 or VP9; 23 to 60 FPS; 360 to 4096 pixels in each dimension; up to 4 GB; and up to 10 minutes through the upload endpoint. These are API limits; the app itself may differ.
Aspect ratio and resolution
Vertical 9:16 at 1080x1920 fits all three platforms above. Square (1:1) still counts as a Short on YouTube. Horizontal 16:9 is the default for regular YouTube videos and most website embeds.
From a 16:9 source you have two honest options. Crop, which fills the frame but loses the edges:
ffmpeg -i source.mp4 -vf "crop=ih*9/16:ih,scale=1080:1920" \
-c:v libx264 -crf 20 -pix_fmt yuv420p -c:a aac -b:a 128k clip-crop.mp4
Or fit the full frame over a blurred copy of itself, which keeps everything visible:
ffmpeg -i source.mp4 -filter_complex \
"[0:v]split=2[bg][fg];\
[bg]scale=1080:1920:force_original_aspect_ratio=increase,crop=1080:1920,boxblur=20:2[b];\
[fg]scale=1080:-2[f];\
[b][f]overlay=(W-w)/2:(H-h)/2,format=yuv420p[v]" \
-map "[v]" -map 0:a -c:v libx264 -crf 20 -c:a aac -b:a 128k \
-movflags +faststart clip-fit.mp4
scale=1080:-2 keeps the aspect ratio and rounds the height to an even number, which 4:2:0 encoding requires. For tracking crops that follow a speaker, see the reframing section in how an automated clip pipeline works.
Frame rate
Keep the source frame rate unless you have a reason to change it. Phone recordings are often variable frame rate, which can drift after cutting. Normalize to a constant rate during the final encode:
ffmpeg -i phone.mp4 -vf fps=30 -c:v libx264 -crf 20 -pix_fmt yuv420p \
-c:a aac -b:a 128k -movflags +faststart clip-30fps.mp4
Pick 30 for 30 or 29.97 sources and 60 for 60 or 59.94 sources. Converting 30 to 60 only duplicates frames and doubles the work for the platform's encoder.
Bitrate: CRF vs capped VBR
For masters you control quality with CRF (constant rate factor): lower values mean higher quality and larger files. When a destination publishes a maximum bitrate, add a cap with -maxrate and -bufsize. This command follows YouTube's H.264 recommendations for a 30 fps vertical clip, including High Profile, 2 B-frames and a closed GOP of 15 frames (half of 30):
ffmpeg -i clip-master.mov \
-c:v libx264 -preset slow -crf 19 -maxrate 12M -bufsize 24M \
-profile:v high -pix_fmt yuv420p -g 15 -bf 2 \
-c:a aac -b:a 128k -ar 48000 -ac 2 \
-movflags +faststart clip-upload.mp4
If you need a predictable file size instead, use two pass encoding with a target bitrate:
ffmpeg -y -i clip-master.mov -c:v libx264 -preset slow -b:v 6M -pass 1 -an -f null /dev/null
ffmpeg -i clip-master.mov -c:v libx264 -preset slow -b:v 6M -pass 2 \
-c:a aac -b:a 128k -movflags +faststart clip-2pass.mp4
On Windows, replace /dev/null with NUL.
HEVC and AV1 versions
# HEVC, tagged hvc1 so Apple players recognize it
ffmpeg -i clip-upload.mp4 -c:v libx265 -preset medium -crf 24 -tag:v hvc1 \
-pix_fmt yuv420p -c:a copy -movflags +faststart clip-hevc.mp4
# AV1 with SVT-AV1, for your own web delivery
ffmpeg -i clip-upload.mp4 -c:v libsvtav1 -preset 8 -crf 32 -g 60 \
-pix_fmt yuv420p -c:a copy -movflags +faststart clip-av1.mp4
CRF scales differ between encoders, so a value that looks good with x264 is not equivalent in x265 or SVT-AV1. Compare by eye on your own footage, at the size people will actually watch.
Audio
AAC-LC at 48 kHz stereo is the common ground: YouTube recommends it, Meta lists AAC at up to 48 kHz and 128 kbps for Reels. In ffmpeg, the native aac encoder with -b:a 128k -ar 48000 -ac 2 covers it.
Loudness consistency matters more on short clips than on long videos, because viewers swipe between them. You can normalize with the loudnorm filter; pick one integrated loudness target for all your clips and keep it consistent. None of the platform pages cited here publish a target, so we do not state one.
ffmpeg -i clip-upload.mp4 -c:v copy \
-af loudnorm=I=-16:TP=-1.5:LRA=11 -c:a aac -b:a 128k -ar 48000 clip-norm.mp4
Validate before you upload
ffprobe -v error -select_streams v:0 \
-show_entries stream=codec_name,profile,pix_fmt,width,height,avg_frame_rate,bit_rate \
-of default=noprint_wrappers=1 clip-upload.mp4
- Container MP4, moov before mdat.
- Video H.264 High,
yuv420p, progressive, constant frame rate. - Resolution 1080x1920 for vertical; width at most 1920 for Reels.
- Frame rate between 23 and 60 for Instagram and TikTok, matching the source.
- Audio AAC, 48 kHz, stereo, 128 kbps.
- Duration within the destination's limit (YouTube Shorts up to three minutes).
Automate this check in your publishing scheduler so a bad file fails before it spends upload quota.
If you would rather skip the encoding work
Hosted clipping tools make these choices for you. ViceForge, for example, accepts MP4, MOV, AVI and WebM uploads and exports clips as Vertical (9:16), Horizontal (16:9) or Standard (4:3), with 4K export on its Creator Elite plan. Plan details are on the ViceForge pricing page.