diff --git a/README.md b/README.md index bfbd3a0..ff43dd9 100644 --- a/README.md +++ b/README.md @@ -3,4 +3,6 @@ pip install exifread pip install LatLon pip install requests +brew install exiftool + Need config.ini for reverse lookup diff --git a/elodie/media/photo.py b/elodie/media/photo.py index c9e720f..8ff7fc1 100644 --- a/elodie/media/photo.py +++ b/elodie/media/photo.py @@ -104,7 +104,7 @@ class Photo(Media): return self.exif """ - Get latitude of photo from EXIF + Get latitude or longitude of photo from EXIF @returns, float or None if not present in EXIF or a non-photo file """ diff --git a/elodie/media/video.py b/elodie/media/video.py index 25c1db5..d058a41 100644 --- a/elodie/media/video.py +++ b/elodie/media/video.py @@ -4,7 +4,10 @@ Video package that handles all video operations """ # load modules +from distutils.spawn import find_executable from sys import argv +from datetime import datetime + import mimetypes import os import re @@ -26,6 +29,34 @@ class Video(Media): def __init__(self, source=None): super(Video, self).__init__(source) + """ + Get latitude or longitude of photo from EXIF + + @returns, time object or None for non-video files or 0 timestamp + """ + def get_coordinate(self, type='latitude'): + exif_data = self.get_exif() + if(exif_data is None): + return None + + coords = re.findall('(GPS %s +: .+)' % type.capitalize(), exif_data) + if(coords is None or len(coords) == 0): + return None + + coord_string = coords[0] + coordinate = re.findall('([0-9.]+)', coord_string) + direction = re.search('[NSEW]$', coord_string) + if(coordinate is None or direction is None): + return None + + direction = direction.group(0) + + decimal_degrees = float(coordinate[0]) + float(coordinate[1])/60 + float(coordinate[2])/3600 + if(direction == 'S' or direction == 'W'): + decimal_degrees = decimal_degrees * -1 + + return decimal_degrees + """ Get the date which the video was taken. The date value returned is defined by the min() of mtime and ctime. @@ -38,6 +69,17 @@ class Video(Media): source = self.source seconds_since_epoch = min(os.path.getmtime(source), os.path.getctime(source)) + # We need to parse a string from EXIF into a timestamp. + # we use date.strptime -> .timetuple -> time.mktime to do the conversion in the local timezone + exif_data = self.get_exif() + date = re.search('Media Create Date +: +(.+)', exif_data) + if(date is not None): + date_string = date.group(1) + try: + seconds_since_epoch = time.mktime(datetime.strptime(date_string, '%Y:%m:%d %H:%M:%S').timetuple()) + except: + pass + if(seconds_since_epoch == 0): return None @@ -61,6 +103,21 @@ class Video(Media): return re.search('(\d{2}:\d{2}.\d{2})', key).group(1).replace('.', ':') return None + """ + Get exif data from video file. + Not all video files have exif and this currently relies on the CLI exiftool program + + @returns, string or None if exiftool is not found + """ + def get_exif(self): + exiftool = find_executable('exiftool') + if(exiftool is None): + return None + + source = self.source + process_output = subprocess.Popen(['%s %s ' % (exiftool, source)], stdout=subprocess.PIPE, shell=True) + return process_output.stdout.read() + """ Get a dictionary of metadata for a video. All keys will be present and have a value of None if not obtained. @@ -74,6 +131,8 @@ class Video(Media): source = self.source metadata = { "date_taken": self.get_date_taken(), + "latitude": self.get_coordinate('latitude'), + "longitude": self.get_coordinate('longitude'), "length": self.get_duration(), "mime_type": self.get_mimetype(), "base_name": os.path.splitext(os.path.basename(source))[0], diff --git a/import.py b/import.py index 1fac599..f30965b 100755 --- a/import.py +++ b/import.py @@ -25,14 +25,7 @@ def process_file(_file, destination, media): metadata = media.get_metadata() - if(type(media).__name__ == 'Video'): - directory_name = filesystem.get_folder_path(date=metadata['date_taken']) - elif(type(media).__name__ == 'Photo'): - directory_name = filesystem.get_folder_path(date=metadata['date_taken'], latitude=metadata['latitude'], longitude=metadata['longitude']) - else: - print 'Invalid media type' - sys.exit(2) - + directory_name = filesystem.get_folder_path(date=metadata['date_taken'], latitude=metadata['latitude'], longitude=metadata['longitude']) dest_directory = '%s/%s' % (destination, directory_name) # TODO remove the day prefix of the file that was there prior to the crawl