main.py 8.25 KB
Newer Older
Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/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"]
27
__license__ = "GPL v3.0"
Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
__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'))
53
54
        if 'WORKING_PATH' not in config:
            print(ConsoleColors.RED + 'WORKING_PATH key not found in config.yaml!' + ConsoleColors.END)
Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
55
            quit(os.EX_CONFIG)
56
57
        if 'PRESERVATION_FILES_NAME' not in config:
            print(ConsoleColors.RED + 'PRESERVATION_FILES_NAME key not found in config.yaml!' + ConsoleColors.END)
Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
58
59
60
61
62
            quit(os.EX_CONFIG)
    except FileNotFoundError:
        print(ConsoleColors.RED + 'config.yaml file not found!' + ConsoleColors.END)
        quit(os.EX_NOINPUT)

63
64
    temp_path = os.path.join(config['WORKING_PATH'], 'temp/')

Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
65
66
67
68
    # Access Copy Files
    print('\n' + ConsoleColors.BOLD + 'Creation of Access Copy Files...' + ConsoleColors.END)

    # By default, AccessCopyFiles directory is created in the output path...
69
70
    acf_dir = 'AccessCopyFiles/' + config['PRESERVATION_FILES_NAME'] + '/'
    acf_path = os.path.join(config['WORKING_PATH'], acf_dir)
Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
71
72
73
74
75
76
    # ...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
77
        print("Directory '% s' created" % acf_path)
Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
78
79
80
81
82
83
84
85
    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
86
            print("Directory '% s' overwritten" % acf_path)
Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
87
88
89
90
91
92
        elif overwrite.casefold() != 'n':
            print(ConsoleColors.RED + 'Unknown command, exiting' + ConsoleColors.END)
            quit(os.EX_USAGE)

    if make_acf:
        # Copy RestoredAudioFiles
93
        raf_path = os.path.join(temp_path, 'RestoredAudioFiles')
Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
94
95
96
97
98
99
100
101
102
103
104
        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:
105
            shutil.copy2(temp_path + 'EditingList.json', acf_path)
Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
106
107
108
109
110
111
        except FileNotFoundError:
            print(ConsoleColors.RED + 'EditingList.json file not found!' + ConsoleColors.END)
            quit(os.EX_NOINPUT)
        print("Editing List copied")

        # Create Irregularity Images archive
112
        ii_path = os.path.join(temp_path, 'IrregularityImages')
Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
113
114
115
116
117
118
        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)
119
        shutil.make_archive(acf_path + 'IrregularityImages', 'zip', temp_path, 'IrregularityImages')
Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
120
121
122
123
        print("Irregularity Images archive created")

        # Copy Irregularity File
        try:
124
            shutil.copy2(temp_path + 'TapeIrregularityClassifier_IrregularityFileOutput2.json', acf_path + 'IrregularityFile.json')
Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
125
        except FileNotFoundError:
126
            print(ConsoleColors.RED + 'TapeIrregularityClassifier_IrregularityFileOutput2.json file not found!' + ConsoleColors.END)
Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
127
128
129
            quit(os.EX_NOINPUT)
        print("Irregularity File copied")

130
131
132
        # End Access Copy Files
        print(ConsoleColors.GREEN + ConsoleColors.BOLD + "Success!" + ConsoleColors.END)

Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
133
134
135
136
    # Preservation Master Files
    print('\n' + ConsoleColors.BOLD + 'Creation of Preservation Master Files...' + ConsoleColors.END)

    # By default, PreservationMasterFiles directory is created in the output path...
137
138
    pmf_dir = 'PreservationMasterFiles/' + config['PRESERVATION_FILES_NAME'] + '/'
    pmf_path = os.path.join(config['WORKING_PATH'], pmf_dir)
Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
139
140
141
    # ...however, if it already exists, it is possible to skip its creation
    if not os.path.exists(pmf_path):
        os.mkdir(pmf_path)
142
        print("Directory '% s' created" % pmf_path)
Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
143
144
145
146
147
148
    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)
149
            print("Directory '% s' overwritten" % pmf_path)
Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
150
151
152
153
154
155
156
157
        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
158
    audio_file = config['PRESERVATION_FILES_NAME'] + '.wav'
Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
159
    try:
160
        shutil.copy2(os.path.join(config['WORKING_PATH'], 'PreservationAudioFile/') + audio_file, pmf_path + 'PreservationAudioFile.wav')
Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
161
162
163
164
165
166
    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
167
    video_file = config['PRESERVATION_FILES_NAME'] + '.mov'
Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
168
    try:
169
170
        video = VideoFileClip(os.path.join(config['WORKING_PATH'], 'PreservationAudioVisualFile/') + video_file)
        audio = AudioFileClip(os.path.join(config['WORKING_PATH'], 'PreservationAudioFile/') + audio_file)
Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
171
        # Open Irregularity File to get offset
172
        irregularity_file_json = open(temp_path + 'TapeIrregularityClassifier_IrregularityFileOutput2.json')
Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
173
174
175
176
177
178
179
180
181
182
183
184
185
186
        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)
187
    shutil.make_archive(pmf_path + 'IrregularityImages', 'zip', temp_path, 'IrregularityImages')
Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
188
189
190
    print("Irregularity Images archive created")

    # Copy Irregularity File (already checked)
191
    shutil.copy2(temp_path + 'TapeIrregularityClassifier_IrregularityFileOutput2.json', pmf_path + 'IrregularityFile.json')
Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
192
193
    print("Irregularity File copied")

194
195
    # End Preservation Master Files
    print(ConsoleColors.GREEN + ConsoleColors.BOLD + "Success!" + ConsoleColors.END + '\n')