-
Notifications
You must be signed in to change notification settings - Fork 0
/
create_albums_metadata.py
100 lines (75 loc) · 4.16 KB
/
create_albums_metadata.py
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
27
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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#!/usr/bin/python
import argparse
import datetime
import glob
import json
import os
import re
import subprocess
import time
import uuid
import exifread
def process_photo(photo_file):
with open(photo_file, 'rb') as file:
try:
tags = exifread.process_file(file, details=False)
if 'EXIF DateTimeOriginal' not in tags.keys():
print("[ERROR] Missing EXIF info. Can't place photo {0} into album {1}".format(photo_file, albumdata['title']))
return ''
dt = datetime.datetime.strptime(str(tags['EXIF DateTimeOriginal']).split(' ')[0], '%Y:%m:%d')
return os.sep.join([dt.strftime('%Y-%m-%d'), os.path.basename(photo_file)])
except PermissionError:
print("[ERROR] PermissionError. Can't place photo {0} into album {1}".format(photo_file, albumdata['title']))
return ''
def process_video(video_file):
cmnd = ['ffprobe', '-show_format', '-print_format', 'json', '-loglevel', 'quiet', '{0}'.format(video_file)]
p = subprocess.Popen(cmnd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, _err = p.communicate()
info = json.loads(out.decode('utf-8'))
creation_time_found = False
if 'format' in info and 'tags' in info['format']:
tags = info['format']['tags']
if 'creation_time' in tags:
creation_time_found = True
now_timestamp = time.time()
utc_offset = datetime.datetime.fromtimestamp(now_timestamp) - datetime.datetime.utcfromtimestamp(now_timestamp)
dt = datetime.datetime.strptime(tags['creation_time'], '%Y-%m-%dT%H:%M:%S.%fZ') + utc_offset
return os.sep.join([dt.strftime('%Y-%m-%d'), os.path.basename(video_file)])
if not creation_time_found:
print('[ERROR] Creation time not found in {0}'.format(video_file))
return ''
if __name__ == '__main__':
parser = argparse.ArgumentParser(description="Create <UUID>.json file for each album with title, date and time, list of files, etc. As an input it takes metadata.json that is generated by Google Photos")
parser.add_argument('--takeout-dir', type=str,
help='Google Photos takeout directory')
parser.add_argument('--out-dir', type=str,
help='destination directory')
args = parser.parse_args()
out_dir = args.out_dir
takeout_dir = args.takeout_dir
for json_file in glob.glob(os.path.join(takeout_dir, '**/metadata.json'), recursive=True):
album_dir_name = os.path.basename(os.path.dirname(json_file))
# If '12-7-10' or '12.07.10' or '2012-07-10 -' or '2012-07-10 #2' or '2013-03-22-23'
# then skip
if re.match(r'^\d{1,4}(.|-)\d{1,2}(.|-)\d{2}$', album_dir_name) \
or re.match(r'^\d{1,4}-\d{1,2}-\d{2}\s?-$', album_dir_name) \
or re.match(r'^\d{1,4}-\d{1,2}-\d{2}-\d{2}$', album_dir_name) \
or re.match(r'^\d{1,4}-\d{1,2}-\d{2}\s{1}#\d{1}$', album_dir_name):
continue
print('Found album directory {0}'.format(album_dir_name))
with open(json_file, encoding='utf-8') as metadata_file:
metadata = json.load(metadata_file)
albumdata = {}
albumdata['title'] = metadata['title']
albumdata['date'] = metadata['date']
albumdata['description'] = metadata['description']
albumdata['enrichments'] = metadata['enrichments'] if 'enrichments' in metadata else []
albumdata['files'] = []
for media_file in glob.glob(os.path.join(os.path.dirname(json_file), '*.*')):
if media_file.lower().endswith('.jpg') or media_file.lower().endswith('.jpeg'):
albumdata['files'].append(process_photo(media_file))
if media_file.lower().endswith('.mp4') or media_file.lower().endswith('.mov') or media_file.lower().endswith('.mpg'):
albumdata['files'].append(process_video(media_file))
with open(os.path.join(out_dir, str(uuid.uuid4()) + '.json'), 'w', encoding='utf-8') as outfile:
albumdata['files'] = list(filter(None, albumdata['files']))
json.dump(albumdata, outfile, ensure_ascii=False, indent=4)