Using a newer build of ffmpeg
, can achieve this by using ffprobe
and the ffmpeg
segment muxer
.
- Use
ffprobe
and awk to identify the keyframes as close as possible
to your desired chunk length.
ffprobe -show_frames -select_streams v:0 \
-print_format csv [SOURCE_VIDEO] 2>&1 |
grep -n frame,video,1 |
awk 'BEGIN { FS="," } { print $1 " " $5 }' |
sed 's/:frame//g' |
awk 'BEGIN { previous=0; frameIdx=0; size=0; }
{
split($2,time,".");
current=time[1];
if (current-previous >= [DURATION_IN_SECONDS]){
a[frameIdx]=$1; frameIdx++; size++; previous=current;
}
}
END {
str=a[0];
for(i=1;i<size;i++) { str = str "," a[i]; } print str;
}'
Where
- [SOURCE_VIDEO] = path to video you want to segment
- [DURATION_IN_SECONDS] = desired segment length in seconds
The output is comma-delimited string of keyframes.
- Use the keyframes output above as input to
ffmpeg
.
ffmpeg -i [SOURCE_VIDEO] -codec copy -map 0 -f segment \
-segment_frames [OUTPUT_OF_STEP_1] [SEGMENT_PREFIX] \
_%03d.[SOURCE_VIDEO_EXTENSION]
Where
- [SOURCE_VIDEO] = path to video you want to segment
- [OUTPUT_OF_STEP_1] = comma-delimited string of keyframes
- [SEGMENT_PREFIX] = name of segment output
- [SOURCE_VIDEO_EXTENSION] = extension of source video (e.g., mp4, mkv)