You recorded a webinar or gameplay session and want clean chapters for each topic. The community’s go-to tool for slicing video on any platform is FFmpeg. If you have ever scrolled through threads comparing flags and timestamp formats, you are not alone.
Hi all, I need a clear explanation of how to split a video with ffmpeg. Could someone explain the simplest command to cut a single clip between two timestamps, and also how to split a file into equal segments, like 10 seconds each? I’d also appreciate tips on the differences between frame-accurate cuts and fast splitting without re-encoding, and any gotchas I should be aware of when it comes to audio tracks, subtitles, or output settings.
Thanks!
Great question! FFmpeg provides multiple ways to split video. The best method depends on whether you need fast, lossless cuts or frame-accurate results. Let’s check them out.
Fast and lossless when your cut points are near keyframes:
# Fast split - copy streams, may cut at nearest keyframe boundaries
ffmpeg -ss 12 -t 15 -i input.mp4 -c copy clip1.mp4
# Starts at 12s and outputs 15s (ends at ~27s)Code language: CSS (css)
For frame-accurate results, re-encode the video stream:
# Frame-accurate split - re-encodes video
ffmpeg -ss 12 -t 15 -i input.mp4 -c:v libx264 -crf 18 -preset veryfast -c:a copy clip1.mp4Code language: CSS (css)
- Tip: Using
-ssbefore-iis faster. Using-ssafter-ican be more accurate for stream copy, but is slower. - Prefer
-t(duration) instead of-toto avoid confusion about absolute vs relative end times.
Use the segment muxer. This is ideal for chunking content into fixed durations:
# Split into 10 second parts without re-encoding
ffmpeg -i input.mp4 -c copy -map 0 -f segment \
-segment_time 10 -reset_timestamps 1 parts_%03d.mp4Code language: CSS (css)
-reset_timestamps 1restarts timestamps at zero for each segment.- Segments will start on the nearest keyframe. If you need precise boundaries, re-encode and force keyframes periodically:
# Re-encode and force keyframes every 10s for clean boundaries
ffmpeg -i input.mp4 -c:v libx264 -crf 20 -preset fast -c:a copy \
-force_key_frames "expr:gte(t,n_forced*10)" \
-f segment -segment_time 10 -reset_timestamps 1 parts_%03d.mp4Code language: CSS (css)
If you have multiple chapters, loop through ranges and create clips:
# Bash example - ranges are start,duration per line
while IFS=, read -r start dur name; do
ffmpeg -ss "$start" -t "$dur" -i input.mp4 -c copy "$name".mp4
done < ranges.csv
# ranges.csv
# 12,15,intro
# 27,28,feature_demo
# 55,20,q_and_aCode language: PHP (php)
- Tracks: Use
-map 0to include all tracks, or select specific ones like-map 0:v:0 -map 0:a:1. - Subtitles: Not all containers handle stream copy for subtitles the same way. If you see errors, re-encode or drop them with
-sn. - Web delivery: For MP4 segments, add
-movflags +faststartto move the index to the front. - Codecs: If you re-encode, H.264 is a safe default. See H.264 best practices.
Once you upload your video, you can generate trimmed segments on the fly with URL parameters or SDKs. For example, to deliver a 15 second clip from 12s to 27s you can apply a trim transformation using start and end offsets, then create multiple derived assets for each chapter as needed.
// Node.js example - create derived clips using start/end offsets
import { v2 as cloudinary } from 'cloudinary';
cloudinary.uploader.explicit('videos/my_talk', {
resource_type: 'video',
eager: [
{ transformation: [{ so: 12, eo: 27 }], format: 'mp4' }, // intro
{ transformation: [{ so: 27, eo: 55 }], format: 'mp4' }, // demo
{ transformation: [{ so: 55, eo: 75 }], format: 'mp4' } // Q&A
],
eager_async: false
});Code language: JavaScript (javascript)
This approach offloads processing, gives you CDN delivery, and keeps your media assets organized with consistent naming. If you re-encode, Cloudinary can apply codec and bitrate defaults aligned with modern delivery profiles.
- Expect small boundary drift with
-c copysplits because cuts align to keyframes. - For precise cuts, re-encode and optionally force periodic keyframes.
- Always confirm timestamps with a sample render before batch processing.
- Single clip fast: ffmpeg:
-ss START -t DURATION -i in.mp4 -c copy out.mp4 - Equal chunks:
ffmpeg -i in.mp4 -c copy -f segment -segment_time 10 -reset_timestamps 1 parts_%03d.mp4 - Frame accurate: re-encode with
-c:v libx264and optional-force_key_frames. - Cloud delivery and automation: use Cloudinary trimming via URL or SDKs to generate chapter clips on demand.
Ready to streamline video processing and delivery in one place? Sign up for a free Cloudinary account and start transforming and delivering your videos at scale.