Auto-splitting video file in equal chunks with ffmpeg and python

Recently I needed to upload a whole bunch of long video files. Maximum allowed length for each video was just few minutes, while the actual length of files I tried to upload were about an hour each. FFmpeg is really great for splitting the video files and Python is quite handy for automating the task. Combining two together in this handy little script(see below). The script below takes a video file and a chunk size in seconds and splits the video file into chunks using ffmpeg, so each chunk is self contained, playable video.

Source code:

#!/usr/bin/env python

import subprocess
import re
import math
from optparse import OptionParser


length_regexp = 'Duration: (\d{2}):(\d{2}):(\d{2})\.\d+,'
re_length = re.compile(length_regexp)

def main():

    (filename, split_length) = parse_options()
    if split_length <= 0:
        print "Split length can't be 0"
        raise SystemExit

    output = subprocess.Popen("ffmpeg -i '"+filename+"' 2>&1 | grep 'Duration'", 
                            shell = True,
                            stdout = subprocess.PIPE
                            ).stdout.read()
    print output
    matches = re_length.search(output)
    if matches:
        video_length = int(matches.group(1)) * 3600 + \
                        int(matches.group(2)) * 60 + \
                        int(matches.group(3))
        print "Video length in seconds: "+str(video_length)
    else:
        print "Can't determine video length."
        raise SystemExit

    split_count = math.ceil(video_length/float(split_length))
    if(split_count == 1):
        print "Video length is less then the target split length."
        raise SystemExit

    split_cmd = "ffmpeg -i '"+filename+"' -vcodec copy "
    for n in range(0, split_count):
        split_str = ""
        if n == 0:
            split_start = 0
        else:
            split_start = split_length * n
        
        split_str += " -ss "+str(split_start)+" -t "+str(split_length) + \
                    " '"+filename[:-4] + "-" + str(n) + "." + filename[-3:] + \
                    "'"
        print "About to run: "+split_cmd+split_str
        output = subprocess.Popen(split_cmd+split_str, shell = True, stdout =
                               subprocess.PIPE).stdout.read()


def parse_options():
    parser = OptionParser()    
    
    parser.add_option("-f", "--file",
                        dest = "filename",
                        help = "file to split, for example sample.avi",
                        type = "string",
                        action = "store"
                        )
    parser.add_option("-s", "--split-size",
                        dest = "split_size",
                        help = "split or chunk size in seconds, for example 10",
                        type = "int",
                        action = "store"
                        )
    (options, args) = parser.parse_args()
    
    if options.filename and options.split_size:

        return (options.filename, options.split_size)

    else:
        parser.print_help()
        raise SystemExit

if __name__ == '__main__':

    try: 
        main()
    except Exception, e:
        print "Exception occured running main():"
        print str(e)


Or download it here: splitting video file script link

8 thoughts on “Auto-splitting video file in equal chunks with ffmpeg and python

  1. Hi there,

    I found this blog entry to be just what i needed. I am currently trying to split a single video file into several pieces. However, after tinkering around with your script, i have a few questions that i need help with:

    1. What video files is the script meant for? I tinkered with AVI, MOV, and WMV so far, and i’m not having much luck getting mov and wmv to split and play correctly.
    2. Although my avi file does get split, i hit two problems:
    ___a. some of the split files aren’t the correct chunk size (ie. i had the split_size = 30 (seconds), yet some of the files were 60 or more
    ___b. the first split file played the video correctly, but the rest merely displayed a still image and audio continued. Know what is happening?
    3. Could you point me in the right direction to learn more about ffmpeg btw?

    Thanks again for this entry and your help in advance.

    Cheers,
    -Matt

    Please let me know! And please don’t consider this spam!

  2. Hey Matt,

    Glad that you found this useful.
    In regards to your questions:
    1. This script is really just a convenience wrapper around FFmpeg, so you can use whatever formats your install of ffmpeg supports. To add support for more formats you may need to recompile ffmpeg. For mov and wmv you need to make sure you have appropriate codes. I think you need libx264 for mov. Not sure what you need to wmv. Try googling ffmpeg wmv or something like that

    2. This might be a bug… or your ffmpeg missing some libs. Can you upload your avi file to something like http//ge.tt and give me a link to take a look at? Also what command line params did u use?

    3. FFmpeg docs are pretty good – http://www.ffmpeg.org/ffmpeg-doc.html but might be a bit rigid. Just google for ffmpeg commands to get a bunch of articles about various handy things you can do with it

  3. I’ve also found that splitting WMV’s does not seem to work. No matter what you specify in the -t option, it will always encode the whole video (which I believe is a bug in ffmpeg).

  4. I know this is somewhat late from when this was originally posted, but for me this script raises an invalid range() argument exception – math.ceil() returns a float (at least for me in python 2.7.1 and all 2.x.x as far as I recall). Thus line 33 should read:


    split_count = int(math.ceil(video_length/float(split_length)))

  5. The script should also set ‘-acodec copy’ so that the audio is not re-encoded when the file is split up. Just split the audio with the video.

    Also, the range error is still broken – can you update that?

  6. I put the int fix in and added -acodec copy but also changed ffmpeg instances to avconv. Worked on large mp4 videos.
    Thanks very much for the script.
    Now I can incorporate it all into a batch spilitter in bash.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>