A task as complex like this (to my knowledge) can't be done with ffmpeg
alone and in one single call, but I'll add a oneline version below. Here's the script version:
#!/bin/bash
in=$1
dur=$2
totaldur=$(ffprobe -v -8 -show_entries format=duration -of flat large.mp4 | sed -r 's/.*"([0-9]+).*/\1/')
i=0
while (( i * dur < totaldur) )
do
ffmpeg -i $in -i ${in%%.*}.srt \
-ss $((i*dur)) -t $dur -c copy -sn ${in%%.*}-$((i+1)).${in#*.} \
-ss $((i*dur)) -t $dur -an -vn ${in%%.*}-$((i+1)).srt
((i++))
done
This script takes two arguments, the first one being the video's filename and the second being the duration in seconds, see the example run below. It first pipes the output of ffprobe
to sed
to get the video's total duration in seconds, this value is used to build a while
loop for the parts. Inside the loop ffmpeg
is called to create the parts, both the .mp4
and .srt
in one call.
Example run
$ tree # the directory contains large.mp4 and large.srt
.
├── large.mp4
└── large.srt
$ ffmpeg -i large.mp4 |& awk '/Duration/' # large.mp4 has a duration of 00:02:30.07
Duration: 00:02:30.07, start: 0.000000, bitrate: 1283 kb/s
$ /path/to/above/script large.mp4 60 # let's split it after every 60 seconds
$ tree
.
├── large-1.mp4
├── large-1.srt
├── large-2.mp4
├── large-2.srt
├── large-3.mp4
├── large-3.srt
├── large.mp4
└── large.srt
Oneline version
The first two variables hold the filename and the duration in seconds, adjust those two to your needs.
in=large.mp4;dur=60;i=0;while ((i*dur<$(ffprobe -v -8 -show_entries format=duration -of flat large.mp4|sed -r 's/.*"([0-9]+).*/\1/')));do ffmpeg -y -i $in -i ${in%%.*}.srt -ss $((i*dur)) -t $dur -c copy -sn ${in%%.*}-$((i+1)).${in#*.} -ss $((i*dur)) -t $dur -an -vn ${in%%.*}-$((i+1)).srt;((i++));done
Links
Here are some links I found on the way:
split
comes to mind.