107

I wish to split a large avi video into two smaller consecutive videos. I am using ffmpeg.

One way is to run ffmpeg two times:

ffmpeg -i input.avi -vcodec copy -acodec copy -ss 00:00:00 -t 00:30:00 output1.avi
ffmpeg -i input.avi -vcodec copy -acodec copy -ss 00:30:00 -t 00:30:00 output2.avi

But according to manpage of ffmpeg, I can make more than one ouput file from one input file using just one line:

ffmpeg -i input.avi -vcodec copy -acodec copy -ss 00:00:00 -t 00:30:00 output1.avi \
   -vcodec copy -acodec copy -ss 00:30:00 -t 00:30:00 output2.avi

My question is, does the later approach save computation time and memory?

Antony
  • 1,210
  • 2
  • 9
  • 9
  • 3
    when using the "-vcodec copy -acodec copy" it is very fast:)) – Savas Adar May 02 '12 at 20:39
  • @Antony, Why don't you time both versions (and look at the memory monitor such as `htop`), and tell us what the answer is? – AlcubierreDrive Jul 03 '13 at 19:01
  • The first example does it sequentially, while the second example uses threads. Both will do the same thing, no noticeable speedups should occur. But to simplify things, you might use ffmpeg stream segmenter muxer: http://www.ffmpeg.org/ffmpeg-all.html#segment_002c-stream_005fsegment_002c-ssegment – Mladen B. Aug 24 '13 at 10:04
  • 1
    This example looks badly wrong! The ffmpeg documentation says about the -ss option: "When used as an input option (before -i), seeks in this input file to position. When used as an output option (before an output filename), decodes but discards input until the timestamps reach position." You are using it in the output position, so your second line wastes effort decoding and discarding the first 30 minutes. – Lucian Wischik Feb 22 '15 at 20:51
  • If using MP4, consider [MP4Box](http://gpac.wp.mines-telecom.fr/mp4box/) [-split](http://forum.doom9.org/showthread.php?t=93240) `MP4Box -split 5 input.mp4` to split every 5 secs. Options also available to split every x bytes. – Philip Bulley Mar 10 '15 at 16:22
  • If TS contain multiple program (TV programs that captured by DVB-T), how can split it? For example I have a TS file that contain football + cooking + cartoon .How can i split this TS file to 3 mpg files? – Dr.jacky Jul 20 '15 at 12:36
  • 1
    @LucianWischik but using `-ss` as input option in the second split might not be accurate, so you might not get a clean split. IMO the example by OP is more correct. – jiggunjer Dec 08 '15 at 07:10
  • Using `--ss 00:00:00` might actually result in the first key frame being skipped, so best to simply leave that out, to start at the start. – luckydonald Jul 20 '20 at 23:54
  • Is there any reason the second video output is also `-t 00:30:00`? – StickySli Mar 11 '21 at 13:11

9 Answers9

85

The ffmpeg wiki links back to this page in reference to "How to split video efficiently". I'm not convinced this page answers that question, so I did as @AlcubierreDrive suggested…

echo "Two commands" 
time ffmpeg -v quiet -y -i input.ts -vcodec copy -acodec copy -ss 00:00:00 -t 00:30:00 -sn test1.mkv
time ffmpeg -v quiet -y -i input.ts -vcodec copy -acodec copy -ss 00:30:00 -t 01:00:00 -sn test2.mkv
echo "One command" 
time ffmpeg -v quiet -y -i input.ts -vcodec copy -acodec copy -ss 00:00:00 -t 00:30:00 \
  -sn test3.mkv -vcodec copy -acodec copy -ss 00:30:00 -t 01:00:00 -sn test4.mkv

Which outputs...

Two commands
real    0m16.201s
user    0m1.830s
sys 0m1.301s

real    0m43.621s
user    0m4.943s
sys 0m2.908s

One command
real    0m59.410s
user    0m5.577s
sys 0m3.939s

I tested a SD & HD file, after a few runs & a little maths.

Two commands SD 0m53.94 #2 wins  
One command  SD 0m49.63  

Two commands SD 0m55.00  
One command  SD 0m52.26 #1 wins 

Two commands SD 0m58.60 #2 wins  
One command  SD 0m58.61 

Two commands SD 0m54.60  
One command  SD 0m50.51 #1 wins 

Two commands SD 0m53.94  
One command  SD 0m49.63 #1 wins  

Two commands SD 0m55.00  
One command  SD 0m52.26 #1 wins 

Two commands SD 0m58.71  
One command  SD 0m58.61 #1 wins

Two commands SD 0m54.63  
One command  SD 0m50.51 #1 wins  

Two commands SD 1m6.67s #2 wins  
One command  SD 1m20.18  

Two commands SD 1m7.67  
One command  SD 1m6.72 #1 wins

Two commands SD 1m4.92  
One command  SD 1m2.24 #1 wins

Two commands SD 1m1.73  
One command  SD 0m59.72 #1 wins

Two commands HD 4m23.20  
One command  HD 3m40.02 #1 wins

Two commands SD 1m1.30  
One command  SD 0m59.59 #1 wins  

Two commands HD 3m47.89  
One command  HD 3m29.59 #1 wins  

Two commands SD 0m59.82  
One command  SD 0m59.41 #1 wins  

Two commands HD 3m51.18  
One command  HD 3m30.79 #1 wins  

SD file = 1.35GB DVB transport stream
HD file = 3.14GB DVB transport stream

Conclusion

The single command is better if you are handling HD, it agrees with the manuals comments on using -ss after the input file to do a 'slow seek'. SD files have a negligible difference.

The two command version should be quicker by adding another -ss before the input file for the a 'fast seek' followed by the more accurate slow seek.

Community
  • 1
  • 1
user2867531
  • 866
  • 7
  • 3
  • If TS contain multiple program (TV programs that captured by DVB-T), how can split it? For example I have a TS file that contain football + cooking + cartoon .How can i split this TS file to 3 mpg files? – Dr.jacky Jul 20 '15 at 12:35
  • I used your answer in my question here (http://stackoverflow.com/questions/41983940/ffmpeg-disassemble-video-into-parts) but it did not work, what do you think I am doing wrong? – utdev Feb 01 '17 at 15:58
  • 2
    The result file was with no video (only audio) in my case. After some experiments I found soultion. It need to specify key for "do not modify quality" like this `-q:v 0`. – oklas Apr 25 '17 at 06:39
21

Here's a useful script, it helps you split automatically: A script for splitting videos using ffmpeg

#!/bin/bash
 
# Written by Alexis Bezverkhyy <alexis@grapsus.net> in 2011
# This is free and unencumbered software released into the public domain.
# For more information, please refer to <http://unlicense.org/>
 
function usage {
        echo "Usage : ffsplit.sh input.file chunk-duration [output-filename-format]"
        echo -e "\t - input file may be any kind of file reconginzed by ffmpeg"
        echo -e "\t - chunk duration must be in seconds"
        echo -e "\t - output filename format must be printf-like, for example myvideo-part-%04d.avi"
        echo -e "\t - if no output filename format is given, it will be computed\
 automatically from input filename"
}
 
IN_FILE="$1"
OUT_FILE_FORMAT="$3"
typeset -i CHUNK_LEN
CHUNK_LEN="$2"
 
DURATION_HMS=$(ffmpeg -i "$IN_FILE" 2>&1 | grep Duration | cut -f 4 -d ' ')
DURATION_H=$(echo "$DURATION_HMS" | cut -d ':' -f 1)
DURATION_M=$(echo "$DURATION_HMS" | cut -d ':' -f 2)
DURATION_S=$(echo "$DURATION_HMS" | cut -d ':' -f 3 | cut -d '.' -f 1)
let "DURATION = ( DURATION_H * 60 + DURATION_M ) * 60 + DURATION_S"
 
if [ "$DURATION" = '0' ] ; then
        echo "Invalid input video"
        usage
        exit 1
fi
 
if [ "$CHUNK_LEN" = "0" ] ; then
        echo "Invalid chunk size"
        usage
        exit 2
fi
 
if [ -z "$OUT_FILE_FORMAT" ] ; then
        FILE_EXT=$(echo "$IN_FILE" | sed 's/^.*\.\([a-zA-Z0-9]\+\)$/\1/')
        FILE_NAME=$(echo "$IN_FILE" | sed 's/^\(.*\)\.[a-zA-Z0-9]\+$/\1/')
        OUT_FILE_FORMAT="${FILE_NAME}-%03d.${FILE_EXT}"
        echo "Using default output file format : $OUT_FILE_FORMAT"
fi
 
N='1'
OFFSET='0'
let 'N_FILES = DURATION / CHUNK_LEN + 1'
 
while [ "$OFFSET" -lt "$DURATION" ] ; do
        OUT_FILE=$(printf "$OUT_FILE_FORMAT" "$N")
        echo "writing $OUT_FILE ($N/$N_FILES)..."
        ffmpeg -i "$IN_FILE" -vcodec copy -acodec copy -ss "$OFFSET" -t "$CHUNK_LEN" "$OUT_FILE"
        let "N = N + 1"
        let "OFFSET = OFFSET + CHUNK_LEN"
done
slhck
  • 30,965
  • 24
  • 125
  • 174
Marco C.
  • 1,166
  • 1
  • 14
  • 19
  • 3
    Same comment goes for you as for SEARAS. Writing batch files is useful when absolutely needed and when you have no other option available, because it is not portable. You won't be able to run the same script on Windows, for example. When there are more generic/portable ways, batch scripts should be avoided, to save the time needed to port them. Since ffmpeg has multiple ways to solve this issue, the proper way would be to use ffmpeg alone, without the help of scripts. – Mladen B. Aug 24 '13 at 10:00
  • Nice script. Did you write it? Is it on GitHub? I'd like to make some suggestions :) – voices Jan 21 '17 at 04:41
  • for mp4, scenes are damaged. better replace copy with: -vcodec libx264 -acodec aac – kishu Feb 28 '18 at 15:26
10

In my experience, don't use ffmpeg for splitting/join. MP4Box, is faster and light than ffmpeg. Please tryit. Eg if you want to split a 1400mb MP4 file into two parts a 700mb you can use the following cmdl: MP4Box -splits 716800 input.mp4 eg for concatenating two files you can use:

MP4Box -cat file1.mp4 -cat file2.mp4 output.mp4

Or if you need split by time, use -splitx StartTime:EndTime:

MP4Box -add input.mp4 -splitx 0:15 -new split.mp4

Classsic
  • 139
  • 1
  • 4
  • This was exactly what I needed! When I was cutting with ffmpeg, the clips didn't start on keyframes and had weird freezes at the ends. Using MP4Box -splitz did the trick! – matt Dec 12 '16 at 00:12
  • 1
    how can I trim the video using Mp4Box with multiple numbers? for example I need to have sub clips in seconds are : 5 - 8 , 21 - 30 , 12 - 18 so I need three output video file. – mhndev Dec 01 '18 at 11:39
  • And is much easier to use `EndTime` than `-t`. – vmassuchetto Dec 31 '18 at 11:48
  • The best and quick solution than vlc or ffmpeg. Thanks – sapatelbaps Dec 21 '20 at 07:32
6

http://ffmpeg.org/trac/ffmpeg/wiki/Seeking%20with%20FFmpeg may also be useful to you. Also ffmpeg has a segment muxer that might work.

Anyway my guess is that combining them into one command would save time.

rogerdpack
  • 50,731
  • 31
  • 212
  • 332
2

does the later approach save computation time and memory?

There is no big difference between those two examples that you provided. The first example cuts the video sequentially, in 2 steps, while the second example does it at the same time (using threads). No particular speed-up will be noticeable. You can read more about creating multiple outputs with FFmpeg

Further more, what you can use (in recent FFmpeg) is the stream segmenter muxer which can:

output streams to a number of separate files of nearly fixed duration. Output filename pattern can be set in a fashion similar to image2.

Mladen B.
  • 2,297
  • 2
  • 18
  • 30
2

Here is a simple Windows bat file to split incoming file into 50 parts. Each part has length 1 minute. Sorry for such dumb script. I hope it is better to have a dumb windows script instead of do not have it at all. Perhaps it help someone. (Based on "bat file for loop" from this site.)

set var=0
@echo off
:start
set lz=
if %var% EQU 50 goto end
if %var% LEQ 9 set lz=0
echo part %lz%%var%
ffmpeg -ss 00:%lz%%var%:00 -t 00:01:00 -i %1 -acodec copy -vcodec copy %2_%lz%%var%.mp4
set /a var+=1
goto start

:end
echo var has reached %var%.
exit
Alex Bor
  • 29
  • 2
  • This is essentially the first code snippet in the question (consecutive `ffmpeg` commands) rewritten as a loop. This doesn't answer the question of whether that approach or a single command will "save computation time and memory". – Lance U. Matthews Dec 04 '18 at 03:34
1

Didn't test ist, but this looks promising:

Basic stream segmenter

It is obviously splitting AVI into segments of same size, which implies these chunks don't loose quality or increase memory or must be recalculated.

It also uses the codec copy - does that mean it can handle very large streams ? Because this is my problem, i want to break down my avi so i could use a filter to get rid of the distorsion. But a whole avi runs for hours.

Mathias Weitz
  • 171
  • 1
  • 2
-1

Here is a perfect way to split the video. I have done it previously, and it's working well for me.

ffmpeg -i C:\xampp\htdocs\videoCutting\movie.mp4 -ss 00:00:00 -t 00:00:05 -async 1 C:\xampp\htdocs\videoCutting\SampleVideoNew.mp4 (For cmd). shell_exec('ffmpeg -i C:\xampp\htdocs\videoCutting\movie.mp4 -ss 00:00:00 -t 00:00:05 -async 1 C:\xampp\htdocs\videoCutting\SampleVideoNew.mp4') (for php).

Please follow this and I am sure it will work perfectly.

erikrunia
  • 2,291
  • 1
  • 13
  • 21
  • Why is this the "perfect way" to split the video? Like the command line in the question, you're passing `-i` followed by `-ss` and `-t`. The question is about how to efficiently extract multiple segments from the same input file, though, whereas you are only extracting a single segment. I don't see how this answers the question. – Lance U. Matthews Dec 04 '18 at 03:31
-2

one simple way is to use trim option with publitio url-based api.

once you get your video uploaded, just set start offset and end offset in url (so_2,eo_2) like so:

    https://media.publit.io/file/so_2,eo_2/tummy.mp4

this will create instantly new videos starting from 2nd second and 2 seconds in length. you can split videos this way anyway you like.

ob1y2k
  • 27
  • 5
  • The question is asking which is more efficient of two approaches to extracting multiple segments from an input file with `ffmpeg`. Unless you have a really, really fast internet connection, I think having to _upload the entire video_ to a cloud service and then _download the results_ is going to increase processing time significantly. Even so, this still doesn't answer the question of which approach **with `ffmpeg`** is more efficient. – Lance U. Matthews Dec 04 '18 at 03:42