Welcome folks today in this blog post we will be writing a python
script which makes use of ffmpeg to split the video into multiple parts in terminal. All the full source code of the application is shown below.
Get Started
In order to get started you need to install the ffmpeg
library in your pc or laptop. After it you can check the version of ffmpeg installed using the below command
ffmpeg -version
And now you need to create an app.py
file inside the root directory and copy paste the following code
app.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 |
#!/usr/bin/env python from __future__ import print_function import csv import json import math import os import shlex import subprocess from optparse import OptionParser def split_by_manifest(filename, manifest, vcodec="copy", acodec="copy", extra="", **kwargs): """ Split video into segments based on the given manifest file. Arguments: filename (str) - Location of the video. manifest (str) - Location of the manifest file. vcodec (str) - Controls the video codec for the ffmpeg video output. acodec (str) - Controls the audio codec for the ffmpeg video output. extra (str) - Extra options for ffmpeg. """ if not os.path.exists(manifest): print("File does not exist: %s" % manifest) raise SystemExit with open(manifest) as manifest_file: manifest_type = manifest.split(".")[-1] if manifest_type == "json": config = json.load(manifest_file) elif manifest_type == "csv": config = csv.DictReader(manifest_file) else: print("Format not supported. File must be a csv or json file") raise SystemExit split_cmd = ["ffmpeg", "-i", filename, "-vcodec", vcodec, "-acodec", acodec, "-y"] + shlex.split(extra) try: fileext = filename.split(".")[-1] except IndexError as e: raise IndexError("No . in filename. Error: " + str(e)) for video_config in config: split_args = [] try: split_start = video_config["start_time"] split_length = video_config.get("end_time", None) if not split_length: split_length = video_config["length"] filebase = video_config["rename_to"] if fileext in filebase: filebase = ".".join(filebase.split(".")[:-1]) split_args += ["-ss", str(split_start), "-t", str(split_length), filebase + "." + fileext] print("########################################################") print("About to run: " + " ".join(split_cmd + split_args)) print("########################################################") subprocess.check_output(split_cmd + split_args) except KeyError as e: print("############# Incorrect format ##############") if manifest_type == "json": print("The format of each json array should be:") print("{start_time: <int>, length: <int>, rename_to: <string>}") elif manifest_type == "csv": print("start_time,length,rename_to should be the first line ") print("in the csv file.") print("#############################################") print(e) raise SystemExit def get_video_length(filename): output = subprocess.check_output(("ffprobe", "-v", "error", "-show_entries", "format=duration", "-of", "default=noprint_wrappers=1:nokey=1", filename)).strip() video_length = int(float(output)) print("Video length in seconds: " + str(video_length)) return video_length def ceildiv(a, b): return int(math.ceil(a / float(b))) def split_by_seconds(filename, split_length, vcodec="copy", acodec="copy", extra="", video_length=None, **kwargs): if split_length and split_length <= 0: print("Split length can't be 0") raise SystemExit if not video_length: video_length = get_video_length(filename) split_count = ceildiv(video_length, split_length) if split_count == 1: print("Video length is less then the target split length.") raise SystemExit split_cmd = ["ffmpeg", "-i", filename, "-vcodec", vcodec, "-acodec", acodec] + shlex.split(extra) try: filebase = ".".join(filename.split(".")[:-1]) fileext = filename.split(".")[-1] except IndexError as e: raise IndexError("No . in filename. Error: " + str(e)) for n in range(0, split_count): split_args = [] if n == 0: split_start = 0 else: split_start = split_length * n split_args += ["-ss", str(split_start), "-t", str(split_length), filebase + "-" + str(n + 1) + "-of-" + str(split_count) + "." + fileext] print("About to run: " + " ".join(split_cmd + split_args)) subprocess.check_output(split_cmd + split_args) def main(): 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_length", help="Split or chunk size in seconds, for example 10", type="int", action="store" ) parser.add_option("-c", "--split-chunks", dest="split_chunks", help="Number of chunks to split to", type="int", action="store" ) parser.add_option("-S", "--split-filesize", dest="split_filesize", help="Split or chunk size in bytes (approximate)", type="int", action="store" ) parser.add_option("--filesize-factor", dest="filesize_factor", help="with --split-filesize, use this factor in time to" " size heuristics [default: %default]", type="float", action="store", default=0.95 ) parser.add_option("--chunk-strategy", dest="chunk_strategy", help="with --split-filesize, allocate chunks according to" " given strategy (eager or even)", type="choice", action="store", choices=['eager', 'even'], default='eager' ) parser.add_option("-m", "--manifest", dest="manifest", help="Split video based on a json manifest file. ", type="string", action="store" ) parser.add_option("-v", "--vcodec", dest="vcodec", help="Video codec to use. ", type="string", default="copy", action="store" ) parser.add_option("-a", "--acodec", dest="acodec", help="Audio codec to use. ", type="string", default="copy", action="store" ) parser.add_option("-e", "--extra", dest="extra", help="Extra options for ffmpeg, e.g. '-e -threads 8'. ", type="string", default="", action="store" ) (options, args) = parser.parse_args() def bailout(): parser.print_help() raise SystemExit if not options.filename: bailout() if options.manifest: split_by_manifest(**options.__dict__) else: video_length = None if not options.split_length: video_length = get_video_length(options.filename) file_size = os.stat(options.filename).st_size split_filesize = None if options.split_filesize: split_filesize = int(options.split_filesize * options.filesize_factor) if split_filesize and options.chunk_strategy == 'even': options.split_chunks = ceildiv(file_size, split_filesize) if options.split_chunks: options.split_length = ceildiv(video_length, options.split_chunks) if not options.split_length and split_filesize: options.split_length = int(split_filesize / float(file_size) * video_length) if not options.split_length: bailout() split_by_seconds(video_length=video_length, **options.__dict__) if __name__ == '__main__': main() |
Now in order to run this script
you need to execute the below command
python app.py -f filename -s #noofsecondstosplit
Here in the above command you need to replace the videopath
instead of filename and also you need to replace the no of seconds to split the video as shown below
python app.py -f video.mp4 -s 10
This will split the video.mp4
into smaller sub parts. Each sub part of the video will be 10 seconds long. You can see in the below gif animation