-
Notifications
You must be signed in to change notification settings - Fork 5
Description
Hi @emosheeep,
I’ve been analyzing CapCut export files compared to videos generated via FFmpeg (NVENC) and noticed something interesting:
CapCut-exported videos — even with similar bitrate and resolution — upload to YouTube significantly faster than our FFmpeg outputs of the same duration and size.
For example:
CapCut export: 60 min, ~15 Mbps average, uploads in ~8 min
Our FFmpeg output: 60 min, ~15 Mbps (CBR_HQ, H.264 NVENC), uploads in ~25 min
When checking with MediaInfo, both files look similar in codec profile and bitrate.
But it seems CapCut might be doing something specific during muxing or metadata placement that helps YouTube’s processing (possibly “moov atom” optimization, GOP structure, or some proprietary flag).
Could you perhaps share any insight into how CapCut handles the final encode or if your tool has ever revealed additional mux parameters?
Here’s an example of the FFmpeg command we currently use:
def build_ffmpeg_cmd_filtergraph(files: List[Path], target_seconds: int, out_path: Path, cfg: JobConfig) -> List[str]:
w, h = VERT_W, VERT_H
vb_m = int(getattr(cfg, "bitrate_mbps", 15) or 15)
vb_m = max(12, min(22, vb_m))
vb = f"{vb_m}M"
if getattr(cfg, "youtube_mode", True):
# smiren burst za predvidljiv CBR (brži YT processing)
maxrate = f"{int(vb_m * 1.25)}M"
bufsize = f"{vb_m * 2}M"
else:
maxrate = f"{vb_m * 3}M"
bufsize = f"{vb_m * 2}M"
cmd = [cfg.ffmpeg_path, "-hide_banner", "-y", "-loglevel", "info", *IN_OPTS]
for f in files:
cmd += ["-i", str(f)]
# --- video chain (GPU/CPU auto) ---
# VIDEO chain: GPU scale (cover) -> CPU crop (center) -> SAR
if USE_CUDA:
vchain = (
"hwupload_cuda,"
f"scale_cuda={VERT_W}:{VERT_H}:force_original_aspect_ratio=increase,"
"hwdownload,format=yuv420p,"
f"crop={VERT_W}:{VERT_H}:x=(in_w-out_w)/2:y=(in_h-out_h)/2,"
"setsar=1:1,setpts=PTS-STARTPTS"
)
else:
vchain = (
f"scale={VERT_W}:{VERT_H}:force_original_aspect_ratio=increase,"
f"crop={VERT_W}:{VERT_H}:x=(in_w-out_w)/2:y=(in_h-out_h)/2,"
"format=yuv420p,setsar=1:1,setpts=PTS-STARTPTS"
)
# --- audio chain (48 kHz za YT) ---
achain = (
"aformat=sample_fmts=fltp:sample_rates=48000:channel_layouts=stereo,"
"aresample=48000:async=1:min_comp=0.001:first_pts=0,asetpts=PTS-STARTPTS"
)
# --- build all filter chains ---
chains = []
for i in range(len(files)):
chains.append(f"[{i}:v]{vchain}[v{i}]")
chains.append(f"[{i}:a]{achain}[a{i}]")
concat_inputs = "".join(f"[v{i}][a{i}]" for i in range(len(files)))
concat = f"{concat_inputs}concat=n={len(files)}:v=1:a=1[v][a]"
post = "[v]fps=30[vf];[a]anull[af]"
filter_complex = ";".join(chains + [concat, post])
# --- final command ---
cmd += [
"-filter_complex", filter_complex,
"-map", "[vf]", "-map", "[af]",
"-t", str(target_seconds),
"-fps_mode", "cfr",
"-vsync", "cfr",
"-max_muxing_queue_size", "4096",
"-colorspace", "bt709", "-color_primaries", "bt709", "-color_trc", "bt709", "-color_range", "tv",
"-c:v", "h264_nvenc",
"-preset", "p2",
"-rc", "cbr",
"-b:v", vb,
"-maxrate", maxrate,
"-bufsize", bufsize,
"-g", "60",
"-bf", "2",
"-forced-idr", "1",
"-sc_threshold", "0",
"-spatial-aq", "1", "-aq-strength", "8",
"-profile:v", "main",
"-level", "5.0",
"-tag:v", "avc1",
"-bsf:v", "h264_metadata=aud=insert",
"-c:a", "aac",
"-ar", "44100",
"-b:a", "192k",
# Progressive MP4 sa moov napred → YouTube-friendly
"-movflags", "+faststart",
"-use_editlist", "0",
"-brand", "mp42",
"-write_tmcd", "0",
"-map_metadata", "-1",
"-map_chapters", "-1",
"-avoid_negative_ts", "make_zero",
"-muxpreload", "0",
"-muxdelay", "0",
"-video_track_timescale", "30000",
"-dn",
str(out_path)
]
return cmd
We’re trying to replicate CapCut’s export structure to improve upload speed and processing time on YouTube.
Any insights, tips, or references would be greatly appreciated!
Thanks a lot for your time and great work on this project 🙌
— Marko