#!/usr/bin/env python """MPAI CAE-ARP Packager. Implements MPAI CAE-ARP Packager Technical Specification, providing: - Access Copy Files: 1. Restored Audio Files. 2. Editing List. 3. Set of Irregularity Images in a .zip file. 4. Irregularity File. - Preservation Master Files: 1. Preservation Audio File. 2. Preservation Audio-Visual File where the audio has been replaced with the Audio of the Preservation Audio File fully synchronised with the video. 3. Set of Irregularity Images in a .zip file. 4. Irregularity File. """ import json import os import shutil import yaml from moviepy.editor import VideoFileClip, AudioFileClip __author__ = "Nadir Dalla Pozza" __copyright__ = "Copyright 2022, Audio Innova S.r.l." __credits__ = ["Niccolò Pretto", "Nadir Dalla Pozza", "Sergio Canazza"] __license__ = "GPL v3.0" __version__ = "1.0.1" __maintainer__ = "Nadir Dalla Pozza" __email__ = "nadir.dallapozza@unipd.it" __status__ = "Production" # Class for customizing console colors class ConsoleColors: PURPLE = '\033[95m' CYAN = '\033[96m' DARK_CYAN = '\033[36m' BLUE = '\033[94m' GREEN = '\033[92m' YELLOW = '\033[93m' RED = '\033[91m' BOLD = '\033[1m' UNDERLINE = '\033[4m' END = '\033[0m' if __name__ == '__main__': # Read configuration file config = object try: config = yaml.safe_load(open('./config.yaml', 'r')) if 'WORKING_PATH' not in config: print(ConsoleColors.RED + 'WORKING_PATH key not found in config.yaml!' + ConsoleColors.END) quit(os.EX_CONFIG) if 'PRESERVATION_FILES_NAME' not in config: print(ConsoleColors.RED + 'PRESERVATION_FILES_NAME key not found in config.yaml!' + ConsoleColors.END) quit(os.EX_CONFIG) except FileNotFoundError: print(ConsoleColors.RED + 'config.yaml file not found!' + ConsoleColors.END) quit(os.EX_NOINPUT) temp_path = os.path.join(config['WORKING_PATH'], 'temp/') # Access Copy Files print('\n' + ConsoleColors.BOLD + 'Creation of Access Copy Files...' + ConsoleColors.END) # By default, AccessCopyFiles directory is created in the output path... acf_dir = 'AccessCopyFiles/' + config['PRESERVATION_FILES_NAME'] + '/' acf_path = os.path.join(config['WORKING_PATH'], acf_dir) # ...however, if it already exists, it is possible to skip its creation make_acf = False if not os.path.exists(acf_path): # Create directory os.mkdir(acf_path) make_acf = True print("Directory '% s' created" % acf_path) else: print(ConsoleColors.PURPLE + 'AccessCopyFiles directory already exists!' + ConsoleColors.END) overwrite = input('Do you want to overwrite it? [y/n]: ') if overwrite.casefold() == 'y': # Overwrite directory shutil.rmtree(acf_path) os.mkdir(acf_path) make_acf = True print("Directory '% s' overwritten" % acf_path) elif overwrite.casefold() != 'n': print(ConsoleColors.RED + 'Unknown command, exiting' + ConsoleColors.END) quit(os.EX_USAGE) if make_acf: # Copy RestoredAudioFiles raf_path = os.path.join(temp_path, 'RestoredAudioFiles') if not os.path.exists(raf_path): print(ConsoleColors.RED + 'RestoredAudioFiles directory not found!' + ConsoleColors.END) quit(os.EX_NOINPUT) restored_audio_files = os.listdir(raf_path) if len(restored_audio_files) == 1: print(ConsoleColors.YELLOW + 'RestoredAudioFiles directory is empty' + ConsoleColors.END) shutil.copytree(raf_path, os.path.join(acf_path, 'RestoredAudioFiles')) print("Restored Audio Files copied") # Copy Editing List try: shutil.copy2(temp_path + 'EditingList.json', acf_path) except FileNotFoundError: print(ConsoleColors.RED + 'EditingList.json file not found!' + ConsoleColors.END) quit(os.EX_NOINPUT) print("Editing List copied") # Create Irregularity Images archive ii_path = os.path.join(temp_path, 'IrregularityImages') if not os.path.exists(ii_path): print(ConsoleColors.RED + 'IrregularityImages directory not found!' + ConsoleColors.END) quit(os.EX_NOINPUT) irregularity_images = os.listdir(ii_path) if len(irregularity_images) == 1: print(ConsoleColors.YELLOW + 'IrregularityImages directory is empty' + ConsoleColors.END) shutil.make_archive(acf_path + 'IrregularityImages', 'zip', temp_path, 'IrregularityImages') print("Irregularity Images archive created") # Copy Irregularity File try: shutil.copy2(temp_path + 'TapeIrregularityClassifier_IrregularityFileOutput2.json', acf_path + 'IrregularityFile.json') except FileNotFoundError: print(ConsoleColors.RED + 'TapeIrregularityClassifier_IrregularityFileOutput2.json file not found!' + ConsoleColors.END) quit(os.EX_NOINPUT) print("Irregularity File copied") # End Access Copy Files print(ConsoleColors.GREEN + ConsoleColors.BOLD + "Success!" + ConsoleColors.END) # Preservation Master Files print('\n' + ConsoleColors.BOLD + 'Creation of Preservation Master Files...' + ConsoleColors.END) # By default, PreservationMasterFiles directory is created in the output path... pmf_dir = 'PreservationMasterFiles/' + config['PRESERVATION_FILES_NAME'] + '/' pmf_path = os.path.join(config['WORKING_PATH'], pmf_dir) # ...however, if it already exists, it is possible to skip its creation if not os.path.exists(pmf_path): os.mkdir(pmf_path) print("Directory '% s' created" % pmf_path) else: print(ConsoleColors.PURPLE + 'PreservationMasterFiles directory already exists!' + ConsoleColors.END) overwrite = input('Do you want to overwrite it? [y/n]: ') if overwrite.casefold() == 'y': shutil.rmtree(pmf_path) os.mkdir(pmf_path) print("Directory '% s' overwritten" % pmf_path) elif overwrite.casefold() == 'n': print('Exit\n') quit(os.EX_OK) else: print(ConsoleColors.RED + 'Unknown command, exiting' + ConsoleColors.END) quit(os.EX_USAGE) # Copy Preservation Audio File audio_file = config['PRESERVATION_FILES_NAME'] + '.wav' try: shutil.copy2(os.path.join(config['WORKING_PATH'], 'PreservationAudioFile/') + audio_file, pmf_path + 'PreservationAudioFile.wav') except FileNotFoundError: print(ConsoleColors.RED + audio_file + ' file not found!' + ConsoleColors.END) quit(os.EX_NOINPUT) print("Preservation Audio File copied") # Create Preservation Audio-Visual File with substituted audio video_file = config['PRESERVATION_FILES_NAME'] + '.mov' try: video = VideoFileClip(os.path.join(config['WORKING_PATH'], 'PreservationAudioVisualFile/') + video_file) audio = AudioFileClip(os.path.join(config['WORKING_PATH'], 'PreservationAudioFile/') + audio_file) # Open Irregularity File to get offset irregularity_file_json = open(temp_path + 'TapeIrregularityClassifier_IrregularityFileOutput2.json') irregularity_file = json.load(irregularity_file_json) offset = irregularity_file['Offset']/1000 if offset > 0: audio = audio.subclip(t_start=offset) else: video = video.subclip(t_start=offset) video = video.set_audio(audio) video.write_videofile(pmf_path + 'PreservationAudioVisualFile.mov', bitrate='3000k', codec='mpeg4') print("Preservation Audio-Visual File created") except OSError: print(ConsoleColors.RED + video_file + ' file not found!' + ConsoleColors.END) quit(os.EX_NOINPUT) # Create Irregularity Images archive (already checked) shutil.make_archive(pmf_path + 'IrregularityImages', 'zip', temp_path, 'IrregularityImages') print("Irregularity Images archive created") # Copy Irregularity File (already checked) shutil.copy2(temp_path + 'TapeIrregularityClassifier_IrregularityFileOutput2.json', pmf_path + 'IrregularityFile.json') print("Irregularity File copied") # End Preservation Master Files print(ConsoleColors.GREEN + ConsoleColors.BOLD + "Success!" + ConsoleColors.END + '\n')