Michael Hamilton
Michael Hamilton

Reputation: 63

Using Python script to cut long videos into chunks in FFMPEG

Starting off by saying I'm not a programmer, but I really need the application this Python script I found says it can do.

Auto-Splitting Script by Antarctic Nest of Icephoenix

Basically I have a directory of long .MP4s that need to be cut into equal parts based on a total running time of 3 hours 15 minutes. For example, I would have an 8 hour video that needs to be cut into smaller parts each under 3:15:00.

We've been manually crating FFMPEG codes to do this, but I found the Python script above that seems like it will do what we are needing. The issue is that I have no Python experience. I don't know where in the script to enter in the folder path with the videos, or where to specify my codecs, or where to tell the program that the max time for each video chunk is 3:15:00.

I'm on a 64-bit windows system working in command prompt

Here's what I have done:

I have no idea where to go from here. It seems like the script is loading properly, but I haven't entered my variables. Any help with where to put the information would be appreciated.

Here is the FFMPEG code we usually use:

ffmpeg -i V:\ffmpeg\88518_63c392af.mp4 -vcodec libx264 -acodec copy -vf fps=fps=30000/1001 -ss 00:05:01.000 -t 02:43:49.000 V:\events\88518.mp4

The ffmpeg codes we use:

-i is a .mp4

-vcodec h.264 codec

-acodec should be “copy” or can be “libvo_aacenc”

-vf fps=30000/1000 a forced fps of 29.97

-ss is start time (we would use this to manually cut into parts along with -t)

-t is duration (we would calculate the duration for each part as the total run time divided by the equal time under 3:15:00 be it two, three, or four parts)

Thank you a million dollars

Upvotes: 6

Views: 15122

Answers (3)

Vishwanath Hiremath
Vishwanath Hiremath

Reputation: 211

U can install FFMPEG from here

Here is the python code to cut the long video into chunks of 5mins i.e(600 sec)

import os
import re
import sys
import subprocess
from decimal import Decimal

process = subprocess.Popen(['ffmpeg', '-i', path_of_video_file], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
stdout, stderr = process.communicate()
matches = re.search(r"Duration:\s{1}(?P<hours>\d+?):(?P<minutes>\d+?):(?P<seconds>\d+\.\d+?),", stdout, re.DOTALL).groupdict()
total_sec=(Decimal(matches['hours'])*60*60)+(Decimal(matches['minutes'])*60)+(Decimal(matches['seconds']))    #duration of the media file

dir_name=path_of_video_file.split('.')[0]+"_chunks"
if not os.path.exists(dir_name):                 
    os.makedirs(dir_name)       #creating directory to save the chunks of the media file

from_time=0
file_no=1
file_names=path_of_video_file.split('.')[0]+'_'
while total_sec>0:
    os.system('ffmpeg -ss '+str(from_time)+' -t 600 -i '+path_of_video_file+' '+dir_name+'/'+file_names+str(file_no)+'.mp4')   #In case if you want the chunks of the file to be in other formats then you can change 'mp4' to the required audio or video format.
    file_no=file_no+1
    from_time=from_time+600
    total_sec=total_sec-600

Upvotes: 0

Padraic Cunningham
Padraic Cunningham

Reputation: 180512

You need to add parens to the print's and change the exception syntax to except Exception as e:

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'",
                            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 as e:
        print("Exception occured running main():")
        print(e)

After those changes the script will run fine, it could also improved.

Updated version should be compatible with python2 and 3:

import re
import math
from optparse import OptionParser

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

from subprocess import check_call, PIPE, Popen
import shlex

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

    p1 = Popen(["ffmpeg", "-i", filename], stdout=PIPE, stderr=PIPE, universal_newlines=True)
    # get p1.stderr as input
    output = Popen(["grep", 'Duration'], stdin=p1.stderr, stdout=PIPE, universal_newlines=True)
    p1.stdout.close()
    matches = re_length.search(output.stdout.read())
    if matches:
        video_length = int(matches.group(1)) * 3600 + \
                       int(matches.group(2)) * 60 + \
                       int(matches.group(3))
        print("Video length in seconds: {}".format(video_length))
    else:
        print("Can't determine video length.")
        raise SystemExit

    split_count = math.ceil(video_length / split_length)

    if split_count == 1:
        print("Video length is less than the target split length.")
        raise SystemExit

    for n in range(split_count):
        split_start = split_length * n
        pth, ext = filename.rsplit(".", 1)
        cmd = "ffmpeg -i {} -vcodec copy  -strict -2 -ss {} -t {} {}-{}.{}".\
            format(filename, split_start, split_length, pth, n, ext)
        print("About to run: {}".format(cmd))
        check_call(shlex.split(cmd), universal_newlines=True)


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 as e:
        print(e)

Upvotes: 4

xorsyst
xorsyst

Reputation: 8257

It looks like the python script is written in Python 2. Unfortunately, it won't run with Python 3. You need to uninstall Python 3 and install Python 2.7.

Upvotes: 0

Related Questions