You could easily do that with FFMpeg if you are ok with the program. Here's the official documentation and the Wiki.
For instance, I have a following video SampleVideo_1280x720_30mb_srt.mp4
(the source), which I added a few subtitles to. Let's probe the file:
$> ffmpeg -hide_banner SampleVideo_1280x720_30mb_srt.mp4
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'SampleVideo_1280x720_30mb_srt.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf60.20.100
Duration: 00:02:50.86, start: 0.000000, bitrate: 1474 kb/s
Stream #0:0[0x1](und): Video: h264 (Main) (avc1 / 0x31637661), yuv420p(progressive), 1280x720 [SAR 1:1 DAR 16:9], 1086 kb/s, 25 fps, 25 tbr, 12800 tbn (default)
Metadata:
handler_name : VideoHandler
vendor_id : [0][0][0][0]
Stream #0:1[0x2](und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, 5.1, fltp, 383 kb/s (default)
Metadata:
handler_name : SoundHandler
vendor_id : [0][0][0][0]
Stream #0:2[0x3](eng): Subtitle: mov_text (tx3g / 0x67337874), 0 kb/s (default)
Metadata:
handler_name : SubtitleHandler
Stream #0:3[0x4](ger): Subtitle: mov_text (tx3g / 0x67337874), 0 kb/s
Metadata:
handler_name : SubtitleHandler
Stream #0:4[0x5](fre): Subtitle: mov_text (tx3g / 0x67337874), 0 kb/s
Metadata:
handler_name : SubtitleHandler
It's 02:50
long with 5 streams: video, audio, and 3 subtitles in EN, DE, and FR. FFMpeg can cut/trim videos including all streams. The following command extracts 30 secs after the first minute including all streams: audio, video, and subtitles:
(Note metadata info are excluded from the following outputs)
$> ffmpeg -ss 00:01:00 -t 00:00:30 -i SampleVideo_1280x720_30mb_srt.mp4 -map 0 -c copy output.mp4
-ss
and -t
depict beginning of the time and duration. -map 0
instructs on including ALL streams from the input 0, that is the first input file. Here's the output from ffprobe
:
$> ffprobe -hide_banner output.mp4
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'output.mp4':
Duration: 00:00:30.01, start: 0.000000, bitrate: 1806 kb/s
Stream #0:0[0x1](und): Video: h264 (Main) (avc1 / 0x31637661), yuv420p(progressive), 1280x720 [SAR 1:1 DAR 16:9], 1213 kb/s, 25 fps, 25 tbr, 12800 tbn (default)
Stream #0:1[0x2](und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, 5.1, fltp, 384 kb/s (default)
Stream #0:2[0x3](eng): Subtitle: mov_text (tx3g / 0x67337874), 0 kb/s (default)
Stream #0:3[0x4](ger): Subtitle: mov_text (tx3g / 0x67337874), 0 kb/s
Stream #0:4[0x5](fre): Subtitle: mov_text (tx3g / 0x67337874), 0 kb/s
The duration of a new video is 00:30
and all subtitles have been copied. If I decided to keep only one subtitle, I'd have to be more specific in which stream to include in output file. This is done via -map
s:
$> ffmpeg -ss 00:01:00 -t 00:00:30 -i SampleVideo_1280x720_30mb_srt.mp4 -map 0:v -map 0:a -map 0:s:0 -c copy output.mp4
Here maps 0:v
and 0:a
tell FFMpeg to include both video and audio streams from the input 0. Then, -map 0:s:0
only includes the first subtitle, the one in English. Again, using ffprobe
on such video gives the following output:
> ffprobe -hide_banner output.mp4
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'output.mp4':
Duration: 00:00:30.01, start: 0.000000, bitrate: 1806 kb/s
Stream #0:0[0x1](und): Video: h264 (Main) (avc1 / 0x31637661), yuv420p(progressive), 1280x720 [SAR 1:1 DAR 16:9], 1213 kb/s, 25 fps, 25 tbr, 12800 tbn (default)
Stream #0:1[0x2](und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, 5.1, fltp, 384 kb/s (default)
Stream #0:2[0x3](eng): Subtitle: mov_text (tx3g / 0x67337874), 0 kb/s (default)
I have used -c copy
in all above examples, which copies streams without any processing. Sometimes -ss
may produce artefacts at split points. A simple way to avoid is to slightly adjust time for -ss
. Otherwise, re-encode the video stream
$> ffmpeg -ss 00:01:00 -t 00:00:30 -i SampleVideo_1280x720_30mb_srt.mp4 -map 0 -c:v libx264 -preset slow -crf 20 -c:a copy -c:s copy output.mp4
libx264
and its settings is only an example.
You should check FFMpeg manual or FFMpeg official Wiki if you need more info. Just for completion ffmpeg -hide_banner -codecs
lists all available codecs, while ffmpeg -hide_banner -h encoder=libx264
will for instance list options available for H264 encoder.
Hope this helps.