diff --git a/README.md b/README.md index e950e89..381f0c8 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,33 @@ start_time,length,rename_to * end_time - end time of the video +## Additional Arguments + +* -v or --vcodec ffmpeg video codec to be used. +* -a or --acodec ffmpeg audio codec to be used. +* -m or --manifest manifest file to control the splitting of videos. +* -f or --file video file to split. +* -s or --split-size seconds to evenly split the videos + +#### Notes: + +The -s and -m options should not be used together. If they are, -m option takes +precedent over the -s option + + +## Known Issues with ffmpeg + +* There might be some videos that aren't showing properly after splitting the source video with ffmpeg. To resolve +this, use the -v option and pass in the associated video codec for the source video or video format. For example, mp4 videos +use h264 video codec. Therefore, running the command +`python ffmpeg-split.py -f example.mp4 -s -v h264`, may resolve this issue. + + +## Installing ffmpeg + +See [FFmpeg installation guide](https://www.ffmpeg.org/download.html) for details. + + [FFMpeg]: https://www.ffmpeg.org/ diff --git a/ffmpeg-split.py b/ffmpeg-split.py index b98ff84..097bf21 100644 --- a/ffmpeg-split.py +++ b/ffmpeg-split.py @@ -12,62 +12,78 @@ from optparse import OptionParser length_regexp = 'Duration: (\d{2}):(\d{2}):(\d{2})\.\d+,' re_length = re.compile(length_regexp) -def split_by_manifest(filename, manifest): +def split_by_manifest(filename, manifest, vcodec="copy", acodec="copy", + **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. + """ if not os.path.exists(manifest): print "File does not exist: %s" % manifest raise SystemExit - try: - 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 + 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 copy " - split_count = 1 - split_error = [] + split_cmd = "ffmpeg -i '%s' -vcodec %s -acodec %s -y " % (filename, + vcodec, + acodec) + split_count = 1 + split_error = [] + try: + fileext = filename.split(".")[-1] + except IndexError as e: + raise IndexError("No . in filename. Error: " + str(e)) + for video_config in config: + split_str = "" try: - fileext = filename.split(".")[-1] - except IndexError as e: - raise IndexError("No . in filename. Error: " + str(e)) - for video_config in config: - split_str = "" - 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_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_str += " -ss " + str(split_start) + " -t " + \ - str(split_length) + \ - " '"+ filebase + "." + fileext + \ - "'" - print "About to run: "+split_cmd+split_str - output = subprocess.Popen(split_cmd+split_str, - shell = True, stdout = - subprocess.PIPE).stdout.read() - except IndexError as e: - print "############# Incorrect format ##############" + split_str += " -ss " + str(split_start) + " -t " + \ + str(split_length) + \ + " '"+ filebase + "." + fileext + \ + "'" + print "########################################################" + print "About to run: "+split_cmd+split_str + print "########################################################" + output = subprocess.Popen(split_cmd+split_str, + shell = True, stdout = + subprocess.PIPE).stdout.read() + except KeyError as e: + print "############# Incorrect format ##############" + if manifest_type == "json": print "The format of each json array should be:" print "{start_time: , length: , rename_to: }" - print "#############################################" - print e - raise SystemExit - except Exception as e: - print e - raise SystemExit + 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 split_by_seconds(filename, split_length): +def split_by_seconds(filename, split_length, vcodec="copy", acodec="copy", + **kwargs): if split_length and split_length <= 0: print "Split length can't be 0" raise SystemExit @@ -91,7 +107,8 @@ def split_by_seconds(filename, split_length): print "Video length is less then the target split length." raise SystemExit - split_cmd = "ffmpeg -i '"+filename+"' -vcodec copy " + split_cmd = "ffmpeg -i '%s' -vcodec %s -acodec %s " % (filename, vcodec, + acodec) try: filebase = ".".join(filename.split(".")[:-1]) fileext = filename.split(".")[-1] @@ -133,21 +150,29 @@ def main(): 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" + ) (options, args) = parser.parse_args() - if options.filename and options.split_size: - split_by_seconds(options.filename, options.split_size) - elif options.filename and options.manifest: - split_by_manifest(options.filename, options.manifest) + if options.filename and options.manifest: + split_by_manifest(**(options.__dict__)) + elif options.filename and options.split_size: + split_by_seconds(**(options.__dict__)) else: parser.print_help() raise SystemExit if __name__ == '__main__': - - try: - main() - except Exception, e: - print "Exception occured running main():" - print str(e) - + main()