Beispiel #1
0
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
Beispiel #2
0
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
Beispiel #3
0
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)
Beispiel #4
0
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
Beispiel #5
0
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
Beispiel #6
0
 def set_av_status(self):
     if not self.isDocumentation:
         self.avStatus = pymmFunctions.is_av(self.inputPath)
     else:
         self.avStatus = None
Beispiel #7
0
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
Beispiel #8
0
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