def main(CurrentIngest=None): # DO STUFF args = set_args() inputPath = args.inputPath # for ingestfile.py this is the packageDerivDir outputDir = args.outputDir derivType = args.derivType logDir = args.logDir rsMulti = args.rspaceMulti isSequence = args.isSequence mixdown = args.mixdown combine_audio_streams = args.combine_audio_streams # CurrentIngest = args.current_ingest if logDir: pymmFunctions.set_ffreport(logDir, 'makeDerivs') if not isSequence: inputType = pymmFunctions.is_av(inputPath) else: inputType = 'sequence' ffmpegArgs = [] inputOptions, audioPath = set_input_options(derivType, inputPath, logDir, isSequence) middleOptions = set_middle_options(derivType, inputType, inputPath, mixdown, combine_audio_streams, audioPath) outputOptions = set_output_options(derivType, inputType, inputPath, outputDir) ffmpegArgs = inputOptions + middleOptions + outputOptions ffmpegArgs.insert(0, 'ffmpeg') # print(ffmpegArgs) print(' '.join(ffmpegArgs)) output = subprocess.run(ffmpegArgs, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # out,err = output.communicate() # print(out.decode('utf-8')) if output.stderr: print(output.stderr.decode('utf-8')) # if output.stdout: # print(output.stdout.decode('utf-8')) if logDir: pymmFunctions.unset_ffreport() # get the output path to rsync the deriv to access directories outputFilePath = outputOptions[-1] if pymmFunctions.boolean_answer( config['deriv delivery options'][derivType]): additional_delivery(outputFilePath, derivType, rsMulti) # print(outputFilePath) if inputType == "AUDIO": add_audio_images(CurrentIngest, outputFilePath) return outputFilePath
def make_frame_md5(inputPath,metadataDir): print('making frame md5') if not pymmFunctions.is_av(inputPath): # FUN FACT: YOU CAN RUN FFMPEG FRAMEMD5 ON A TEXT FILE!! print(inputPath+" IS NOT AN AV FILE SO WHY ARE YOU TRYING TO MAKE A FRAME MD5 REPORT?") return False else: md5File = pymmFunctions.get_base(inputPath)+"_frame-md5.txt" frameMd5Filepath = os.path.join(metadataDir,md5File) frameMd5Command = ['ffmpeg','-i',inputPath,'-f','framemd5',frameMd5Filepath] output = subprocess.Popen(frameMd5Command,stdout=subprocess.PIPE,stderr=subprocess.PIPE) try: out,err = output.communicate() if err: print(err.decode('utf-8')) return frameMd5Filepath except: return False
def check_av_status(inputPath, interactiveMode, ingestLogBoilerplate): ''' Check whether or not a file is recognized as an a/v file. If it isn't and user declares interactive mode, ask whether to continue, otherwise quit. ''' if not pymmFunctions.is_av(inputPath): _is_av = False message = "WARNING: " + ingestLogBoilerplate[ 'filename'] + " is not recognized as an a/v file." print(message) pymmFunctions.ingest_log( # message message, #status 'warning', # ingest boilerplate **ingestLogBoilerplate) if interactiveMode: stayOrGo = input( "If you want to quit press 'q' and hit enter, otherwise press any other key:" ) if stayOrGo == 'q': # CLEANUP AND LOG THIS @fixme sys.exit() else: if _is_av == False: pymmFunctions.ingest_log( # message message, # status 'warning', # ingest boilerplate **ingestLogBoilerplate) else: pymmFunctions.ingest_log( # message ingestLogBoilerplate['filename'] + " is an AV file, way to go.", # status 'OK', # ingest boilerplate **ingestLogBoilerplate)
def check_av_status(CurrentIngest): ''' Check whether or not a file is recognized as an a/v object. ''' avStatus = False event = 'format identification' CurrentIngest.caller = 'pymmFunctions.is_av()' AV = pymmFunctions.is_av(CurrentIngest.currentTargetObject.inputPath) if not AV: outcome = "WARNING: {} is not recognized as an a/v object.".format( CurrentIngest.currentTargetObject.inputPath) status = "WARNING" print(outcome) else: outcome = "{} is a(n) {} object, way to go.".format( CurrentIngest.currentTargetObject.inputPath, AV) status = "OK" avStatus = True loggers.log_event(CurrentIngest, event, outcome, status) return avStatus, AV
def make_derivs(CurrentIngest, rsPackage=None, isSequence=None): ''' Make derivatives based on options declared in config... ''' initialObject = CurrentIngest.currentTargetObject inputPath = initialObject.inputPath packageObjectDir = CurrentIngest.packageObjectDir packageLogDir = CurrentIngest.packageLogDir packageMetadataObjects = CurrentIngest.packageMetadataObjects makeProres = CurrentIngest.ProcessArguments.makeProres ingestType = CurrentIngest.ProcessArguments.ingestType resourcespace_deliver = CurrentIngest.ProcessArguments.resourcespace_deliver mono = CurrentIngest.ProcessArguments.mono combineAudio = CurrentIngest.ProcessArguments.combineAudio # make an enclosing folder for access copies if the input is a # group of related video files if rsPackage != None: rsPackageDelivery = make_rs_package( CurrentIngest.InputObject.canonicalName, resourcespace_deliver) CurrentIngest.accessDelivery = rsPackageDelivery else: rsPackageDelivery = None # we'll always output a resourcespace access file for video ingests, # so init the derivtypes list with `resourcespace` if ingestType in ('film scan', 'video transfer', 'audio xfer'): derivTypes = ['resourcespace'] # deliveredDerivPaths is a dict as follows: # {derivtype1:/path/to/deriv/file1} deliveredDerivPaths = {} if pymmFunctions.boolean_answer( config['deriv delivery options']['proresHQ']): derivTypes.append('proresHQ') elif makeProres == True: derivTypes.append('proresHQ') else: pass for derivType in derivTypes: sysargs = [ '', '-i' + inputPath, '-o' + packageObjectDir, '-d' + derivType, '-L' + packageLogDir ] if rsPackageDelivery != None: sysargs.append('-r' + rsPackageDelivery) if isSequence: sysargs.append('-s') if mono: # select to mixdown audio to mono sysargs.append('-m') if combineAudio: # select to mix all audio tracks to one stereo track sysargs.append('-k') sys.argv = sysargs deliveredDeriv = makeDerivs.main(CurrentIngest) deliveredDerivPaths[derivType] = deliveredDeriv event = 'migration' CurrentIngest.caller = CurrentIngest.ProcessArguments.ffmpegVersion if pymmFunctions.is_av(deliveredDeriv): outcome = 'create access copy at {}'.format(deliveredDeriv) status = 'OK' else: outcome = 'could not create access copy' status = 'FAIL' loggers.log_event(CurrentIngest, event, outcome, status) CurrentIngest.caller = None for key, value in deliveredDerivPaths.items(): # metadata for each deriv is stored in a folder named # for the derivtype under the main Metadata folder mdDest = os.path.join(packageMetadataObjects, key) if not os.path.isdir(mdDest): os.mkdir(mdDest) if os.path.isfile(value): # if the new access file exists, # create it as a ComponentObject object and # add it to the list in InputObject newObject = ingestClasses.ComponentObject( value, objectCategoryDetail='access file', topLevelObject=False) newObject.metadataDirectory = mdDest CurrentIngest.InputObject.ComponentObjects.append(newObject) CurrentIngest.currentTargetObject = newObject loggers.insert_object(CurrentIngest, objectCategory='file', objectCategoryDetail='access file') else: pass # get a return value that is the path to the access copy(ies) delivered # to a destination defined in config.ini # * for a single file it's the single deriv path # * for a folder of files it's the path to the enclosing deriv folder # # this path is used to make an API call to resourcespace if rsPackageDelivery not in ('', None): accessPath = rsPackageDelivery else: SIPaccessPath = deliveredDerivPaths['resourcespace'] deliveredAccessBase = os.path.basename(SIPaccessPath) accessPath = os.path.join(resourcespace_deliver, deliveredAccessBase) CurrentIngest.ingestResults['accessPath'] = accessPath CurrentIngest.accessDelivery = accessPath return accessPath
def set_av_status(self): if not self.isDocumentation: self.avStatus = pymmFunctions.is_av(self.inputPath) else: self.avStatus = None
def make_frame_md5(inputPath, metadataDir): print('making frame md5') print(inputPath) md5File = pymmFunctions.get_base(inputPath) + "_frame-md5.txt" frameMd5Filepath = os.path.join(metadataDir, md5File) av = pymmFunctions.is_av(inputPath) returnValue = False if not av: # FUN FACT: YOU CAN RUN FFMPEG FRAMEMD5 ON A TEXT FILE!! print("{} IS NOT AN AV FILE SO " "WHY ARE YOU TRYING TO MAKE " "A FRAME MD5 REPORT?".format(inputPath)) elif av == 'VIDEO': frameMd5Command = [ 'ffmpeg', '-i', inputPath, '-f', 'framemd5', frameMd5Filepath ] output = subprocess.Popen(frameMd5Command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) try: out, err = output.communicate() if err: # this output is captured in stderr for some reason print("FRAME MD5 CHA CHA CHA") # print(err.decode('utf-8')) returnValue = frameMd5Filepath except: print(out.decode()) elif av == 'AUDIO': sampleRate = pymmFunctions.get_audio_sample_rate(inputPath) frameMd5Command = [ 'ffmpeg', '-i', inputPath, '-af', 'asetnsamples=n={}'.format(sampleRate), '-f', 'framemd5', '-vn', frameMd5Filepath ] output = subprocess.run(frameMd5Command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # print(output.returncode) try: if output.returncode == 0: # print(output) print("FRAME MD5 CHA CHA CHA") returnValue = frameMd5Filepath except: print(output.stderr.decode()) elif av == 'DPX': pass ''' OK: FOOD FOR THOUGHT: IT TAKES EFFING FOREVER TO CALCULATE FRAMEMD5 VALUES FOR A DPX SEQUENCE. SLIGHTLY LONGER THAN THE HASHDEEP MANIFEST THAT WILL BE CREATED LATER. SO... SKIP FRAMEMD5 FOR DPX? SINCE WE ARE ALREADY CALCULATING A HASH MANIFEST LATER ON? MAYBE LATER GET A FUNCTION TO PARSE A HASH MANIFEST FOR THE FOLDER AND TURN IT INTO A ACTUALLY ON THE SOUPED UP LINUX SERVER THIS IS REALLY FAST. SO MAYBE RUN A BENCH MARK AND IF THE SYSTEM CAN HANDLE IT RUN THIS FUNCTION ''' # filePattern,startNumber,file0 = pymmFunctions.parse_sequence_folder(inputPath) # frameMd5Command = [ # 'ffmpeg', # '-start_number',startNumber, # '-i',filePattern, # '-f','framemd5', # frameMd5Filepath # ] # print(' '.join(frameMd5Command)) # output = subprocess.Popen( # frameMd5Command, # stdout=subprocess.PIPE, # stderr=subprocess.PIPE # ) # try: # out,err = output.communicate() # if err: # # this output is captured in stderr for some reason # print("FRAME MD5 CHA CHA CHA") # # print(err.decode('utf-8')) # returnValue = frameMd5Filepath # except: # print(out.decode()) return returnValue
def main(): args = parse_args() _input = args.inputPath canonicalName = args.canonical_name wrapper = args.wrapper success = False problems = "" if os.path.isdir(_input): # get rid of any hidden files pymmFunctions.remove_hidden_system_files(_input) # get the abs path of each input file sourceList = pymmFunctions.list_files(_input) elif isinstance(_input, list): sourceList = _input else: problems += "\ninput is not a dir or list of files. exiting!" print(problems) # sys.exit() if not canonicalName: canonicalName = os.path.basename(sourceList[0]) print("You didn't specify a canonical_name " "so we will treat the first item in sourceList as " "the canonical name for your object.") ####################### # START TESTING FILES stream_compatability, streams = count_streams(sourceList) if not stream_compatability: problems += ("\nCan't concatenate. There are stream count differences " "in your input files. See this: \n{}".format(streams)) success = False print(problems) return problems, success # safe_to_concat returns either True or a list of problems safeToConcat = None simpleConcat = safe_to_concat(sourceList) complexConcat = None # placeholder if not simpleConcat == True: complexConcat = False # placeholder: # complexConcat = safe_to_concat(sourceList,complex=True) if True in (simpleConcat, complexConcat): safeToConcat = True concattedFile = False if safeToConcat == True: try: concattedFile = concat(sourceList, canonicalName, wrapper, simple=True) except: problems += "\nsome problem with the concat process." # print(problems) else: problems += simpleConcat # rename the file so it sorts to the top of the output directory # maybe this is a stupid idea? but it will be handy if not concattedFile == False: concatBase = os.path.basename(concattedFile) concatDir = os.path.dirname(concattedFile) newBase = "00_concatenated_{}".format(concatBase) newPath = os.path.join(concatDir, newBase) # actually rename the file os.rename(concattedFile, newPath) # reset the var to the new path name concattedFile = newPath if pymmFunctions.is_av(concattedFile) in ('VIDEO', 'AUDIO'): success = True else: success = False try: os.remove(concattedFile) except: pass problems += ("\nOutput concat file is not recognized as AV!! " "Something must have gone wrong. Sorry.") concattedFile = problems else: success = False concattedFile = problems return concattedFile, success