def main(args_): print('\n - Normalise.py started') args = parse_args(args_) print(args) source = args.i output_folder = args.o file_list = ififuncs.get_video_files(source) if args.sip: if args.user: user = args.user else: user = ififuncs.get_user() if args.oe: if args.oe[:2] != 'oe': print 'First two characters must be \'oe\' and last four characters must be four digits' object_entry = ififuncs.get_object_entry() elif len(args.oe[2:]) not in range(4, 6): print 'First two characters must be \'oe\' and last four characters must be four digits' object_entry = ififuncs.get_object_entry() elif not args.oe[2:].isdigit(): object_entry = ififuncs.get_object_entry() print 'First two characters must be \'oe\' and last four characters must be four digits' else: object_entry = args.oe else: object_entry = ififuncs.get_object_entry() oe_digits = int(object_entry.replace('oe', '')) for filename in file_list: log_name_source = os.path.join( args.o, '%s_normalise_log.log' % time.strftime("_%Y_%m_%dT%H_%M_%S")) ififuncs.generate_log(log_name_source, 'normalise.py started.') ififuncs.generate_log(log_name_source, 'Command line arguments: %s' % args) ififuncs.generate_log(log_name_source, 'EVENT = agentName=%s' % user) print('\n - Processing: %s' % filename) ififuncs.generate_log( log_name_source, 'EVENT = Normalization, status=started, eventType=Normalization, agentName=ffmpeg, eventDetail=Source object to be normalised=%s' % filename) output, output_uuid, fmd5, ffv1_logfile = normalise_process( filename, output_folder) ififuncs.generate_log( log_name_source, 'EVENT = Normalization, status=finished, eventType=Normalization, agentName=ffmpeg, eventDetail=Source object normalised into=%s' % output) inputxml, inputtracexml, dfxml = ififuncs.generate_mediainfo_xmls( filename, output_folder, output_uuid, log_name_source) fmd5_logfile, fmd5ffv1, verdict = verify_losslessness( output_folder, output, output_uuid, fmd5) ififuncs.generate_log( log_name_source, 'EVENT = losslessness verification, status=finished, eventType=messageDigestCalculation, agentName=ffmpeg, eventDetail=MD5s of AV streams of output file generated for validation, eventOutcome=%s' % verdict) if args.sip: object_entry_complete = 'oe' + str(oe_digits) supplement_cmd = ['-supplement', inputxml, inputtracexml, dfxml] sipcreator_cmd = [ '-i', output, '-move', '-u', output_uuid, '-user', user, '-oe', object_entry_complete, '-o', args.o ] if args.supplement: supplement_cmd.extend(args.supplement) sipcreator_cmd.extend(supplement_cmd) sipcreator_log, sipcreator_manifest = sipcreator.main( sipcreator_cmd) metadata_dir = os.path.join( os.path.dirname(os.path.dirname(sipcreator_log)), 'metadata') shutil.move(fmd5, metadata_dir) shutil.move(fmd5_logfile, os.path.dirname(sipcreator_log)) shutil.move(fmd5ffv1, metadata_dir) shutil.move( ffv1_logfile.replace('\\\\', '\\').replace('\:', ':'), os.path.dirname(sipcreator_log)) logs_dir = os.path.dirname(sipcreator_log) ififuncs.manifest_update( sipcreator_manifest, os.path.join(metadata_dir, os.path.basename(fmd5))) ififuncs.manifest_update( sipcreator_manifest, os.path.join(metadata_dir, os.path.basename(fmd5ffv1))) ififuncs.manifest_update( sipcreator_manifest, os.path.join( logs_dir, os.path.basename( ffv1_logfile.replace('\\\\', '\\').replace('\:', ':')))) ififuncs.manifest_update( sipcreator_manifest, os.path.join( logs_dir, os.path.basename( fmd5_logfile.replace('\\\\', '\\').replace('\:', ':')))) ififuncs.merge_logs(log_name_source, sipcreator_log, sipcreator_manifest) os.remove(dfxml) os.remove(inputxml) os.remove(inputtracexml) oe_digits += 1
def package(objects, object_entry, uuid, source_abspath, args, log_name_source, normalisation_tool, user, rawcooked_logfiles, multi_reeler, current_dir): ''' Package the MKV using sipcreator.py ''' sip_dir = os.path.join( args.o, os.path.join(object_entry, uuid) ) inputxml, inputtracexml, dfxml = ififuncs.generate_mediainfo_xmls(source_abspath, args.o, uuid, log_name_source) source_manifest = os.path.join( args.o, os.path.basename(args.i) + '_manifest-md5.txt' ) ififuncs.generate_log( log_name_source, 'EVENT = message digest calculation, status=started, eventType=messageDigestCalculation, agentName=hashlib, eventDetail=MD5 checksum of source files' ) if multi_reeler: ififuncs.hashlib_manifest(args.i, source_manifest, args.i) else: ififuncs.hashlib_manifest(args.i, source_manifest, os.path.dirname(args.i)) ififuncs.generate_log( log_name_source, 'EVENT = message digest calculation, status=finished, eventType=messageDigestCalculation, agentName=hashlib, eventDetail=MD5 checksum of source files' ) ififuncs.generate_log( log_name_source, 'EVENT = losslessness verification, status=started, eventType=messageDigestCalculation, agentName=%s, eventDetail=Full reversibility of %s back to its original form, followed by checksum verification using %s ' % (normalisation_tool, objects, source_manifest) ) if args.reversibility_dir: reversibility_dir = args.reversibility_dir else: reversibility_dir = args.o judgement = reversibility_verification(objects, source_manifest, reversibility_dir) ififuncs.generate_log( log_name_source, 'EVENT = losslessness verification, status=finished, eventType=messageDigestCalculation, agentName=%s, eventDetail=Full reversibilty of %s back to its original form, followed by checksum verification using %s , eventOutcome=%s' % (normalisation_tool, objects, source_manifest, judgement) ) supplement_cmd = ['-supplement', inputxml, inputtracexml, dfxml, source_manifest] if args.supplement: supplement_cmd.extend(args.supplement) sipcreator_cmd = [ '-i', ] for i in objects: sipcreator_cmd.append(i) sipcreator_cmd += [ '-u', uuid, '-quiet', '-move', '-user', user, '-oe', object_entry, '-o', args.o ] sipcreator_cmd.extend(supplement_cmd) sipcreator_log, sipcreator_manifest = sipcreator.main(sipcreator_cmd) logs_dir = os.path.join(sip_dir, 'logs') for files in os.listdir(logs_dir): if files.endswith('.md5'): deletefiles.main(['-i', os.path.join(logs_dir, files), '-uuid_path', sip_dir, '-user', user]) for rawcooked_logfile in rawcooked_logfiles: rawcooked_logfile = rawcooked_logfile.replace('\'', '') shutil.move(rawcooked_logfile, logs_dir) ififuncs.manifest_update( sipcreator_manifest, os.path.join(logs_dir, os.path.basename(rawcooked_logfile)) ) metadata_dir = os.path.join(sip_dir, 'metadata') os.chdir(current_dir) shutil.copy(os.path.join(os.path.abspath(os.path.dirname(sys.argv[0])), 'film_scan_aip_documentation.txt'), metadata_dir) ififuncs.manifest_update( sipcreator_manifest, os.path.join(metadata_dir, 'film_scan_aip_documentation.txt') ) os.remove(dfxml) os.remove(inputtracexml) os.remove(inputxml) return judgement, sipcreator_log, sipcreator_manifest
def main(args_): ''' Launches the functions that prepare and execute the concatenation. ''' uuid = ififuncs.create_uuid() args = parse_args(args_) print args log_name_source = os.path.join(args.o, '%s_concat_log.log' % time.strftime("_%Y_%m_%dT%H_%M_%S")) ififuncs.generate_log(log_name_source, 'concat.py started.') if args.mov: container = 'mov' else: container = 'mkv' ififuncs.generate_log( log_name_source, 'eventDetail=concat.py %s' % ififuncs.get_script_version('concat.py')) ififuncs.generate_log( log_name_source, 'Command line arguments: %s' % args ) if args.user: user = args.user else: user = ififuncs.get_user() if args.oe: if args.oe[:2] != 'oe': print 'First two characters must be \'oe\' and last four characters must be four digits' object_entry = ififuncs.get_object_entry() elif len(args.oe[2:]) not in range(4, 6): print 'First two characters must be \'oe\' and last four characters must be four digits' object_entry = ififuncs.get_object_entry() elif not args.oe[2:].isdigit(): object_entry = ififuncs.get_object_entry() print 'First two characters must be \'oe\' and last four characters must be four digits' else: object_entry = args.oe else: object_entry = ififuncs.get_object_entry() ififuncs.generate_log( log_name_source, 'EVENT = agentName=%s' % user ) source_uuid_check = '' if os.path.isfile(args.i[0]): source_uuid = ififuncs.get_source_uuid() elif os.path.isdir(args.i[0]): source_uuid_check = ififuncs.check_for_uuid(args) if source_uuid_check == False: source_uuid = ififuncs.get_source_uuid() else: source_uuid = source_uuid_check ififuncs.generate_log( log_name_source, 'Relationship, derivation, has source=%s' % source_uuid ) video_files = args.i concat_file = ififuncs.get_temp_concat('concat_stuff') ififuncs.generate_log( log_name_source, 'concatenation file=%s' % concat_file) if args.r: video_files = recursive_file_list(video_files) video_files = ififuncs.sanitise_filenames(video_files) for source_files in video_files: ififuncs.generate_log( log_name_source, 'source_files = %s' % source_files) make_chapters(video_files) ififuncs.concat_textfile(video_files, concat_file) ififuncs.generate_log( log_name_source, 'EVENT = Concatenation, status=started, eventType=Creation, agentName=ffmpeg, eventDetail=Source media concatenated into a single file output=%s' % os.path.join(args.o, '%s.%s' % (uuid, container))) source_bitstream_md5, fmd5_logfile = ffmpeg_concat(concat_file, args, uuid, container) output_file = os.path.join(args.o, '%s.%s' % (uuid, container)) ififuncs.generate_log( log_name_source, 'EVENT = Concatenation, status=finished, eventType=Creation, agentName=ffmpeg, eventDetail=Source media concatenated into a single file output=%s' % os.path.join(args.o, '%s.%s' % (uuid, container))) ififuncs.generate_log( log_name_source, 'EVENT = losslessness verification, status=started, eventType=messageDigestCalculation, agentName=ffmpeg, eventDetail=MD5s of AV streams of output file generated for validation') validation_logfile = os.path.join(args.o, '%s_validation.log' % uuid).replace('\\', '\\\\').replace(':', '\:') validation_env_dict = ififuncs.set_environment(validation_logfile) output_bitstream_md5 = subprocess.check_output([ 'ffmpeg', '-report', '-i', output_file, '-f', 'md5', '-map', '0:v', '-map', '0:a?', '-c', 'copy', '-' ], env=validation_env_dict).rstrip() ififuncs.generate_log( log_name_source, 'EVENT = losslessness verification, status=finished, eventType=messageDigestCalculation, agentName=ffmpeg, eventDetail=MD5s of AV streams of output file generated for validation') if source_bitstream_md5 == output_bitstream_md5: print 'process appears to be lossless' print source_bitstream_md5, output_bitstream_md5 ififuncs.generate_log( log_name_source, 'EVENT = losslessness verification, eventOutcome=pass') else: print 'something went wrong - not lossless!' print source_bitstream_md5,output_bitstream_md5 ififuncs.generate_log( log_name_source, 'EVENT = losslessness verification, eventOutcome=fail') if args.nochapters != True: subprocess.call(['mkvpropedit', output_file, '-c', 'chapters.txt']) ififuncs.generate_log( log_name_source, 'EVENT = eventType=modification, agentName=mkvpropedit, eventDetail=Chapters added to file detailing start point of source clips.') ififuncs.concat_textfile(video_files, concat_file) with open(log_name_source, 'r') as concat_log: concat_lines = concat_log.readlines() if not args.no_sip: sipcreator_log, sipcreator_manifest = sipcreator.main(['-i', output_file, '-u', uuid, '-oe', object_entry, '-user', user, '-o', args.o]) shutil.move(fmd5_logfile, os.path.dirname(sipcreator_log)) shutil.move(validation_logfile.replace('\\\\', '\\').replace('\:', ':'), os.path.dirname(sipcreator_log)) logs_dir = os.path.dirname(sipcreator_log) ififuncs.manifest_update(sipcreator_manifest, os.path.join(logs_dir, os.path.basename(fmd5_logfile))) ififuncs.manifest_update(sipcreator_manifest, os.path.join(logs_dir,(os.path.basename(validation_logfile.replace('\\\\', '\\').replace('\:', ':'))))) ififuncs.merge_logs(log_name_source, sipcreator_log, sipcreator_manifest)
def make_ffv1( start_number, source_abspath, output_dirname, args, log_name_source, user ): ''' This launches the image sequence to FFV1/Matroska process as well as framemd5 losslessness verification. ''' uuid = ififuncs.create_uuid() if args.sip: object_entry = ififuncs.get_object_entry() files_to_move = [] pix_fmt = ififuncs.img_seq_pixfmt( start_number, source_abspath ) temp_dir = tempfile.gettempdir() ffv1_path = os.path.join(output_dirname, uuid + '.mkv') source_textfile = os.path.join( temp_dir, uuid + '_source.framemd5' ) files_to_move.append(source_textfile) # Just perform framemd5 at this stage if args.rawcooked: logfile = os.path.join( temp_dir, '%s_source_framemd5.log' % uuid ) files_to_move.append(logfile) logfile = "\'" + logfile + "\'" source_framemd5_env_dict = ififuncs.set_environment(logfile) source_framemd5_cmd = [ 'ffmpeg', '-report', '-f', 'image2', '-framerate', '24', '-start_number', start_number, '-i', source_abspath, '-pix_fmt', pix_fmt, '-f', 'framemd5', source_textfile ] print(source_abspath) rawcooked_logfile = os.path.join( temp_dir, '%s_rawcooked.log' % uuid ) normalisation_tool = ififuncs.get_rawcooked_version() files_to_move.append(rawcooked_logfile) rawcooked_logfile = "\'" + rawcooked_logfile + "\'" env_dict = ififuncs.set_environment(rawcooked_logfile) ififuncs.generate_log( log_name_source, 'EVENT = losslessness verification, status=started, eventType=messageDigestCalculation, agentName=ffmpeg, eventDetail=Frame level checksums of source' ) subprocess.call(source_framemd5_cmd, env=source_framemd5_env_dict) ififuncs.generate_log( log_name_source, 'EVENT = losslessness verification, status=finished, eventType=messageDigestCalculation, agentName=ffmpeg, eventDetail=Frame level checksums of source' ) rawcooked_cmd = ['rawcooked', os.path.dirname(source_abspath), '-o', ffv1_path] if args.audio: rawcooked_cmd.extend([args.audio, '-c:a', 'copy']) ffv12dpx = (rawcooked_cmd) else: logfile = os.path.join( temp_dir, '%s_ffv1_transcode.log' % uuid ) files_to_move.append(logfile) logfile = "\'" + logfile + "\'" env_dict = ififuncs.set_environment(logfile) ffv12dpx = [ 'ffmpeg', '-report', '-f', 'image2', '-framerate', '24', '-start_number', start_number, '-i', source_abspath, '-strict', '-2', '-c:v', 'ffv1', '-level', '3', '-g', '1', '-slicecrc', '1', '-slices', '16', '-pix_fmt', pix_fmt, ffv1_path, '-f', 'framemd5', source_textfile ] normalisation_tool = 'FFmpeg' print(ffv12dpx) ififuncs.generate_log( log_name_source, 'EVENT = normalisation, status=started, eventType=Creation, agentName=%s, eventDetail=Image sequence normalised to FFV1 in a Matroska container' % normalisation_tool ) subprocess.call(ffv12dpx, env=env_dict) ififuncs.generate_log( log_name_source, 'EVENT = normalisation, status=finshed, eventType=Creation, agentName=%s, eventDetail=Image sequence normalised to FFV1 in a Matroska container' % normalisation_tool ) ffv1_md5 = os.path.join( temp_dir, uuid + '_ffv1.framemd5' ) files_to_move.append(ffv1_md5) ififuncs.generate_log( log_name_source, 'EVENT = losslessness verification, status=started, eventType=messageDigestCalculation, agentName=ffmpeg, eventDetail=Frame level checksums of image' ) ffv1_fmd5_cmd = [ 'ffmpeg', '-report', '-i', ffv1_path, '-pix_fmt', pix_fmt, '-f', 'framemd5', ffv1_md5 ] ffv1_fmd5_logfile = os.path.join( temp_dir, '%s_ffv1_framemd5.log' % uuid ) files_to_move.append(ffv1_fmd5_logfile) ffv1_fmd5_logfile = "\'" + ffv1_fmd5_logfile + "\'" ffv1_fmd5_env_dict = ififuncs.set_environment(ffv1_fmd5_logfile) subprocess.call(ffv1_fmd5_cmd, env=ffv1_fmd5_env_dict) judgement = verify_losslessness(source_textfile, ffv1_md5) ififuncs.generate_log( log_name_source, 'EVENT = losslessness verification, status=finished, eventType=messageDigestCalculation, agentName=ffmpeg, eventDetail=Frame level checksums of image, eventOutcome=%s' % judgement ) if not args.sip: return judgement else: sip_dir = os.path.join( os.path.dirname(ffv1_path), os.path.join(object_entry, uuid) ) inputxml, inputtracexml, dfxml = ififuncs.generate_mediainfo_xmls(os.path.dirname(source_abspath), args.o, uuid, log_name_source) supplement_cmd = ['-supplement', inputxml, inputtracexml, dfxml] sipcreator_cmd = [ '-i', ffv1_path, '-u', uuid, '-quiet', '-move', '-user', user, '-oe', object_entry, '-o', os.path.dirname(ffv1_path) ] sipcreator_cmd.extend(supplement_cmd) sipcreator_log, sipcreator_manifest = sipcreator.main(sipcreator_cmd) logs_dir = os.path.join(sip_dir, 'logs') metadata_dir = os.path.join(sip_dir, 'metadata') for files in files_to_move: if files.endswith('.log'): shutil.move(files, logs_dir) ififuncs.manifest_update( sipcreator_manifest, os.path.join(logs_dir, os.path.basename(files)) ) elif files.endswith('.framemd5'): shutil.move(files, metadata_dir) ififuncs.manifest_update( sipcreator_manifest, os.path.join(metadata_dir, os.path.basename(files)) ) os.remove(dfxml) os.remove(inputtracexml) os.remove(inputxml) return judgement, sipcreator_log, sipcreator_manifest
def make_ffv1( start_number, source_abspath, output_dirname, root_filename, args, log_name_source ): ''' This launches the image sequence to FFV1/Matroska process as well as framemd5 losslessness verification. ''' uuid = ififuncs.create_uuid() if not args.no_sip: object_entry = ififuncs.get_object_entry() files_to_move = [] pix_fmt = ififuncs.img_seq_pixfmt( start_number, source_abspath ) temp_dir = tempfile.gettempdir() logfile = os.path.join( temp_dir, '%s_ffv1_transcode.log' % uuid ) files_to_move.append(logfile) logfile = "\'" + logfile + "\'" env_dict = ififuncs.set_environment(logfile) ffv1_path = os.path.join(output_dirname, uuid + '.mkv') source_textfile = os.path.join( temp_dir, uuid + '_source.framemd5' ) files_to_move.append(source_textfile) ififuncs.generate_log( log_name_source, 'EVENT = normalisation, status=started, eventType=Creation, agentName=ffmpeg, eventDetail=Image sequence normalised to FFV1 in a Matroska container' ) ffv12dpx = [ 'ffmpeg', '-report', '-f', 'image2', '-framerate', '24', '-start_number', start_number, '-i', source_abspath, '-strict', '-2', '-c:v', 'ffv1', '-level', '3', '-g', '1', '-slicecrc', '1', '-slices', '16', '-pix_fmt', pix_fmt, ffv1_path, '-f', 'framemd5', source_textfile ] ififuncs.generate_log( log_name_source, 'EVENT = normalisation, status=finished, eventType=Creation, agentName=ffmpeg, eventDetail=Image sequence normalised to FFV1 in a Matroska container' ) print ffv12dpx subprocess.call(ffv12dpx, env=env_dict) ffv1_md5 = os.path.join( temp_dir, uuid + '_ffv1.framemd5' ) files_to_move.append(ffv1_md5) ififuncs.generate_log( log_name_source, 'EVENT = losslessness verification, status=started, eventType=messageDigestCalculation, agentName=ffmpeg, eventDetail=Frame level checksums of image' ) ffv1_fmd5_cmd = [ 'ffmpeg', '-report', '-i', ffv1_path, '-pix_fmt', pix_fmt, '-f', 'framemd5', ffv1_md5 ] ffv1_fmd5_logfile = os.path.join( temp_dir, '%s_ffv1_framemd5.log' % uuid ) files_to_move.append(ffv1_fmd5_logfile) ffv1_fmd5_logfile = "\'" + ffv1_fmd5_logfile + "\'" ffv1_fmd5_env_dict = ififuncs.set_environment(ffv1_fmd5_logfile) subprocess.call(ffv1_fmd5_cmd, env=ffv1_fmd5_env_dict) judgement = verify_losslessness(source_textfile, ffv1_md5) ififuncs.generate_log( log_name_source, 'EVENT = losslessness verification, status=finished, eventType=messageDigestCalculation, agentName=ffmpeg, eventDetail=Frame level checksums of image, eventOutcome=%s' % judgement ) if args.no_sip: return judgement else: sip_dir = os.path.join( os.path.dirname(ffv1_path), os.path.join(object_entry, uuid) ) sipcreator_log, sipcreator_manifest = sipcreator.main([ '-i', ffv1_path, '-u', uuid, '-quiet', '-move', '-user', 'Kieran', '-oe', object_entry, '-o', os.path.dirname(ffv1_path)]) logs_dir = os.path.join(sip_dir, 'logs') metadata_dir = os.path.join(sip_dir, 'metadata') for files in files_to_move: if files.endswith('.log'): shutil.move(files, logs_dir) ififuncs.manifest_update( sipcreator_manifest, os.path.join(logs_dir, os.path.basename(files)) ) elif files.endswith('.framemd5'): shutil.move(files, metadata_dir) ififuncs.manifest_update( sipcreator_manifest, os.path.join(metadata_dir, os.path.basename(files)) ) return judgement, sipcreator_log, sipcreator_manifest
def main(args_): '''' Launch all the functions for creating an IFI SIP. ''' args = parse_args(args_) source_folder = args.i print(args) oe_dict = {} user = ififuncs.determine_user(args) if args.oe: object_entry = args.oe else: object_entry = ififuncs.get_object_entry() oe_digits = int(object_entry.replace('oe', '')) for folder in sorted(os.listdir(source_folder)): full_path = os.path.join(source_folder, folder) if os.path.isdir(full_path): try: folder_contents = os.listdir(full_path) except PermissionError: continue object_entry_complete = 'oe' + str(oe_digits) inputs = [] supplements = [] for files in folder_contents: if os.path.splitext(files)[1][1:].lower() in args.object_extension_pattern: inputs.append(os.path.join(full_path, files)) if os.path.splitext(files)[1][1:].lower() in args.supplement_extension_pattern: supplements.append(os.path.join(full_path, files)) if inputs: print(' - Object Entry: %s\n - Inputs: %s\n - Supplements: %s\n' % (object_entry_complete, inputs, supplements)) oe_dict[object_entry_complete] = [inputs, supplements] oe_digits += 1 else: print('Skipping %s as there are no files in this folder that match the -object_extension_pattern' % full_path) if args.dryrun: print('Exiting as you selected -dryrun') sys.exit() logs = [] if args.y: proceed = 'Y' else: proceed = ififuncs.ask_yes_no( 'Do you want to proceed?' ) if proceed == 'Y': for sips in sorted(oe_dict): print(oe_dict[sips]) sipcreator_cmd = ['-i',] for sipcreator_inputs in oe_dict[sips][0]: sipcreator_cmd.append(sipcreator_inputs) sipcreator_cmd += ['-supplement'] for sipcreator_supplements in oe_dict[sips][1]: sipcreator_cmd.append(sipcreator_supplements) sipcreator_cmd += ['-user', user, '-oe', sips, '-o', args.o] if args.rename_uuid: sipcreator_cmd.append('-rename_uuid') if args.zip: sipcreator_cmd.append('-zip') if args.l: sipcreator_cmd.append('-l') print(sipcreator_cmd) sipcreator_log, _ = sipcreator.main(sipcreator_cmd) logs.append(sipcreator_log) for i in logs: if os.path.isfile(i): print(("%-*s : copyit job was a %s" % (50, os.path.basename(i), analyze_log(i))))