""" Convert Image sequence to Mp4 Format Uses ffmpeg.exe Documentation : https://www.ffmpeg.org/ffmpeg.html Ref to Ruby version here //[Project]/tools/script/video/ """ import os import re import sys import time import getopt import subprocess # LD_Keep ff_profile = "ld" crf_setting = "25" TOOLS_BIN = "{}\\Bin".format(os.environ.get('RS_TOOLSROOT')) FFMPEG_BIN = "{}\\video\\ffmpeg.exe".format(TOOLS_BIN) def ffmpeg(input_file, output_file, *command_order, **command_parameters): """ Converts a video or set of images into another video format This command accepts all the flags that the command line version does as keyword arguements. Please refer to the ffmpeg documentation to learn what arguments this command accepts. When using keyword arguments the positioning of the arguments is not saved and will be randomly placed. If you need to Keyword values can't be used more than once in python, so if you need to use the same flag with different values concecutively, pass the values inside a list e.i. ffmpeg -i stereo.wav -map 0:0 -map 0:0 -map_channel 0.0.0:0.0 -map_channel 0.0.1:0.1 -y out.ogg If you need a specific order and multiple values then you would write it as ffmpeg('stereo.wav', 'out.ogg', 'map', 'map', 'map_channel', 'map_channel', map=['0:0,0:0'], map_channel=['0.0.0:0.0','0.0.1:0.1']) Arguments: in_file: string or list[string, string, etc.]; path(s) to the image sequence(s) or video file(s) to convert. out_file: string; path where you want the new mp4 file to be saved out *command_order: list[string, string, etc.]; the order you want the flags the ffmpeg command to be in Keyword Arguments: Any flag that the ffmpeg.exe is accepted as a keyword arguement. If the flag is meant to be used multiple times then simply add the multiple values as a list to the keyword arguement. Returns: None """ command_order = list(command_order) #Remove output flags if they are in command_parameters command_parameters.pop("o", None) command_parameters.pop("y", None) #Put the input value(s) into the command_parameters dictionary command_parameters["i"] = input_file #Convert all command_parameter value to lists if they are not lists already for each_flag, each_value in command_parameters.iteritems(): if not isinstance(each_value, list): command_parameters[each_flag] = [each_value] if each_flag not in command_order: command_order.append(each_flag) #Add the i flag into the command order if it isn't there already if "i" not in command_order: #Insert "i" to the front of the list for each in command_parameters["i"]: command_order[0:0] = ["i"] #Build format string command_format = [] for each in command_order: index = 0 each = each.strip() while "{%s[%d]}" % (each, index) in command_format: index += 1 command_format.append("-%s {%s[%d]} " % (each, each, index)) command_format = "".join(command_format) #Build the command command = command_format.format(**command_parameters) command = r'{} {} -y {}'.format(FFMPEG_BIN, command, os.path.abspath(output_file)) #Run command return subprocess.check_call(command, shell=True) def convertToMp4(in_file, out_file=None): """ Converts a given image sequence or video into a mp4 format video Arguments: in_file: string; path to the image sequence or video file to convert. out_file: string; path where you want the new mp4 file to be saved out Returns: None """ flag_order = ['i', 'r', 'vf', 'pix_fmt', 'ar', 'f', 'vcodec', 'strict', 'acodec', 'vpre' , 'crf'] #If an image sequence is passed, put the rate flag upfront to lower the byte rate if re.search('%0[0-9]+d', in_file): flag_order[0:0] = "r" #Resolve output file if not out_file: out_file = re.sub('-%0[0-9]+d', '', in_file) out_file = setExtension(out_file) return ffmpeg(in_file, out_file, r=[30,30], vf="scale=960:520", pix_fmt="yuv420p", ar=44100, f="mp4", vcodec="libx264", strict="experimental", acodec="aac", vpre=ff_profile, crf=crf_setting, *flag_order) def setExtension(filePath, extension='mp4'): """ changes the extension of the given file to .mp4 Arguments filePath: string ; path of the file that you want to change the extension of extension: string ; extension that you want to use, the default extension is mp4 Return string ; file path with updated extension """ root = os.path.splitext(filePath)[0] return '{root}.{extension}'.format(root=root, extension=extension) def main(argv): """ Converts files to mp4g """ inputfile = '' outputfile = '' #Get arguments try: opts, args = getopt.getopt(argv,"hi:o:",["ifile=","ofile="]) except getopt.GetoptError: print 'sequenceToMp4.py -i -o ' sys.exit(2) for opt, arg in opts: if opt == '-h': print 'sequenceToMp4.py -i -o ' sys.exit() elif opt in ("-i", "--ifile"): inputfile = arg elif opt in ("-o", "--ofile"): outputfile = arg #Check if there is a number after the - in the file name numbers_in_input_file = re.search("(?<=-)[0-9]+", inputfile) if numbers_in_input_file: #Get the number as string number_string = numbers_in_input_file.group() #Get the string length, which also equals the amount of numbers in the number amount_of_numbers = len(number_string) #Make the number formatting equal the correct length number_formatting ='%0{}d'.format(amount_of_numbers) inputfile = inputfile.replace(number_string, number_formatting) outputfile = setExtension(inputfile.replace("-{}".format(number_formatting), '')) convertToMp4(inputfile, outputfile) if __name__ == "__main__": main(sys.argv[1:])