[ffmpeg] FFmpeg: How to split video efficiently?

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?

This question is related to ffmpeg

The answer is


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


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.


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

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

#!/bin/bash
 
# Written by Alexis Bezverkhyy <[email protected]> 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

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.


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.


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.


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.