Add video geotagging support using avmetareadwrite on OS X
This commit is contained in:
		
							parent
							
								
									0f7bfd9f23
								
							
						
					
					
						commit
						8221e3c020
					
				@ -1,3 +1 @@
 | 
			
		||||
from media import Media
 | 
			
		||||
from photo import Photo
 | 
			
		||||
from video import Video
 | 
			
		||||
from media import *
 | 
			
		||||
 | 
			
		||||
@ -19,6 +19,10 @@ import time
 | 
			
		||||
Media class for general video operations
 | 
			
		||||
"""
 | 
			
		||||
class Media(object):
 | 
			
		||||
    # class / static variable accessible through get_valid_extensions()
 | 
			
		||||
    video_extensions = ('avi','m4v','mov','mp4','3gp')
 | 
			
		||||
    photo_extensions = ('jpg', 'jpeg', 'nef', 'dng')
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    @param, source, string, The fully qualified path to the video file
 | 
			
		||||
    """
 | 
			
		||||
@ -201,12 +205,17 @@ class Media(object):
 | 
			
		||||
 | 
			
		||||
        return mimetype[0]
 | 
			
		||||
 | 
			
		||||
    def get_class_by_file(Media, _file):
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def get_class_by_file(Media, _file, classes):
 | 
			
		||||
        extension = os.path.splitext(_file)[1][1:].lower()
 | 
			
		||||
        if(extension in Photo.get_valid_extensions()):
 | 
			
		||||
            return Photo
 | 
			
		||||
        elif(extension in Video.get_valid_extensions()):
 | 
			
		||||
            return Video
 | 
			
		||||
        else:
 | 
			
		||||
            return None
 | 
			
		||||
        name = None
 | 
			
		||||
        if(extension in Media.photo_extensions):
 | 
			
		||||
            name = 'Photo'
 | 
			
		||||
        elif(extension in Media.video_extensions):
 | 
			
		||||
            name = 'Video'
 | 
			
		||||
 | 
			
		||||
        for i in classes:
 | 
			
		||||
            if(name == i.__name__):
 | 
			
		||||
                return i(_file)
 | 
			
		||||
 | 
			
		||||
        return None
 | 
			
		||||
 | 
			
		||||
@ -9,17 +9,17 @@ from datetime import datetime
 | 
			
		||||
 | 
			
		||||
import mimetypes
 | 
			
		||||
import os
 | 
			
		||||
import pyexiv2
 | 
			
		||||
import re
 | 
			
		||||
import time
 | 
			
		||||
 | 
			
		||||
from elodie.media.media import Media
 | 
			
		||||
from media import Media
 | 
			
		||||
from elodie import geolocation
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
Video class for general photo operations
 | 
			
		||||
Photo class for general photo operations
 | 
			
		||||
"""
 | 
			
		||||
class Photo(Media):
 | 
			
		||||
    # class / static variable accessible through get_valid_extensions()
 | 
			
		||||
    __valid_extensions = ('jpg', 'jpeg', 'nef', 'dng')
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    @param, source, string, The fully qualified path to the photo file
 | 
			
		||||
@ -48,11 +48,77 @@ class Photo(Media):
 | 
			
		||||
                return re.search('(\d{2}:\d{2}.\d{2})', key).group(1).replace('.', ':')
 | 
			
		||||
        return None
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    Set album for a photo
 | 
			
		||||
 | 
			
		||||
    @param, name, string, Name of album
 | 
			
		||||
 | 
			
		||||
    @returns, boolean
 | 
			
		||||
    """
 | 
			
		||||
    def set_album(self, name):
 | 
			
		||||
        if(name is None):
 | 
			
		||||
            return False
 | 
			
		||||
 | 
			
		||||
        source = self.source
 | 
			
		||||
        exif_metadata = pyexiv2.ImageMetadata(source)
 | 
			
		||||
        exif_metadata.read()
 | 
			
		||||
 | 
			
		||||
        exif_metadata['Xmp.elodie.album'] = name
 | 
			
		||||
 | 
			
		||||
        exif_metadata.write()
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    Set the date/time a photo was taken
 | 
			
		||||
 | 
			
		||||
    @param, time, datetime, datetime object of when the photo was taken
 | 
			
		||||
 | 
			
		||||
    @returns, boolean
 | 
			
		||||
    """
 | 
			
		||||
    def set_datetime(self, time):
 | 
			
		||||
        if(time is None):
 | 
			
		||||
            return False
 | 
			
		||||
 | 
			
		||||
        source = self.source
 | 
			
		||||
        exif_metadata = pyexiv2.ImageMetadata(source)
 | 
			
		||||
        exif_metadata.read()
 | 
			
		||||
 | 
			
		||||
        exif_metadata['Exif.Photo.DateTimeOriginal'].value = time
 | 
			
		||||
        exif_metadata['Exif.Image.DateTime'].value = time
 | 
			
		||||
 | 
			
		||||
        exif_metadata.write()
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    Set lat/lon for a photo
 | 
			
		||||
 | 
			
		||||
    @param, latitude, float, Latitude of the file
 | 
			
		||||
    @param, longitude, float, Longitude of the file
 | 
			
		||||
 | 
			
		||||
    @returns, boolean
 | 
			
		||||
    """
 | 
			
		||||
    def set_location(self, latitude, longitude):
 | 
			
		||||
        if(latitude is None or longitude is None):
 | 
			
		||||
            return False
 | 
			
		||||
 | 
			
		||||
        source = self.source
 | 
			
		||||
        exif_metadata = pyexiv2.ImageMetadata(source)
 | 
			
		||||
        exif_metadata.read()
 | 
			
		||||
 | 
			
		||||
        exif_metadata['Exif.GPSInfo.GPSLatitude'] = geolocation.decimal_to_dms(latitude)
 | 
			
		||||
        exif_metadata['Exif.GPSInfo.GPSLatitudeRef'] = pyexiv2.ExifTag('Exif.GPSInfo.GPSLatitudeRef', 'N' if latitude >= 0 else 'S')
 | 
			
		||||
        exif_metadata['Exif.GPSInfo.GPSLongitude'] = geolocation.decimal_to_dms(longitude)
 | 
			
		||||
        exif_metadata['Exif.GPSInfo.GPSLongitudeRef'] = pyexiv2.ExifTag('Exif.GPSInfo.GPSLongitudeRef', 'E' if longitude >= 0 else 'W')
 | 
			
		||||
 | 
			
		||||
        exif_metadata.write()
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    Static method to access static __valid_extensions variable.
 | 
			
		||||
    def set_location(self, latitude, longitude):
 | 
			
		||||
        return None
 | 
			
		||||
 | 
			
		||||
    @returns, tuple
 | 
			
		||||
    """
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def get_valid_extensions(Photo):
 | 
			
		||||
        return Photo.__valid_extensions
 | 
			
		||||
        return Media.photo_extensions
 | 
			
		||||
 | 
			
		||||
@ -5,23 +5,25 @@ Video package that handles all video operations
 | 
			
		||||
 | 
			
		||||
# load modules
 | 
			
		||||
from distutils.spawn import find_executable
 | 
			
		||||
import tempfile
 | 
			
		||||
from sys import argv
 | 
			
		||||
from datetime import datetime
 | 
			
		||||
 | 
			
		||||
import mimetypes
 | 
			
		||||
import os
 | 
			
		||||
import re
 | 
			
		||||
import shutil
 | 
			
		||||
import subprocess
 | 
			
		||||
import time
 | 
			
		||||
 | 
			
		||||
from elodie.media.media import Media
 | 
			
		||||
from media import Media
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
Video class for general video operations
 | 
			
		||||
"""
 | 
			
		||||
class Video(Media):
 | 
			
		||||
    # class / static variable accessible through get_valid_extensions()
 | 
			
		||||
    __valid_extensions = ('avi','m4v','mov','mp4','3gp')
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    @param, source, string, The fully qualified path to the video file
 | 
			
		||||
@ -29,8 +31,63 @@ class Video(Media):
 | 
			
		||||
    def __init__(self, source=None):
 | 
			
		||||
        super(Video, self).__init__(source)
 | 
			
		||||
 | 
			
		||||
        # We only want to parse EXIF once so we store it here
 | 
			
		||||
        self.exif = None
 | 
			
		||||
    """
 | 
			
		||||
    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.
 | 
			
		||||
 | 
			
		||||
    @returns, time object or None for non-video files or 0 timestamp
 | 
			
		||||
    """
 | 
			
		||||
    def get_date_taken(self):
 | 
			
		||||
        if(not self.is_valid()):
 | 
			
		||||
            return None
 | 
			
		||||
 | 
			
		||||
        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()
 | 
			
		||||
        for key in ['Creation Date', 'Media Create Date']:
 | 
			
		||||
            date = re.search('%s +: +([0-9: ]+)' % key, 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())
 | 
			
		||||
                    break
 | 
			
		||||
                except:
 | 
			
		||||
                    pass
 | 
			
		||||
 | 
			
		||||
        if(seconds_since_epoch == 0):
 | 
			
		||||
            return None
 | 
			
		||||
 | 
			
		||||
        return time.gmtime(seconds_since_epoch)
 | 
			
		||||
        
 | 
			
		||||
    """
 | 
			
		||||
    Get the duration of a video in seconds.
 | 
			
		||||
@ -50,6 +107,183 @@ 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.
 | 
			
		||||
 | 
			
		||||
    @returns, dictionary or None for non-video files
 | 
			
		||||
    """
 | 
			
		||||
    def get_metadata(self):
 | 
			
		||||
        if(not self.is_valid()):
 | 
			
		||||
            return None
 | 
			
		||||
 | 
			
		||||
        source = self.source
 | 
			
		||||
        metadata = {
 | 
			
		||||
            "date_taken": self.get_date_taken(),
 | 
			
		||||
            "latitude": self.get_coordinate('latitude'),
 | 
			
		||||
            "longitude": self.get_coordinate('longitude'),
 | 
			
		||||
            "album": None,
 | 
			
		||||
            #"length": self.get_duration(),
 | 
			
		||||
            "mime_type": self.get_mimetype(),
 | 
			
		||||
            "base_name": os.path.splitext(os.path.basename(source))[0],
 | 
			
		||||
            "extension": self.get_extension()
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return metadata
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    Set album for a photo
 | 
			
		||||
    Not yet implemented
 | 
			
		||||
 | 
			
		||||
    @param, name, string, Name of album
 | 
			
		||||
 | 
			
		||||
    @returns, boolean
 | 
			
		||||
    """
 | 
			
		||||
    def set_album(self, name):
 | 
			
		||||
        if(name is None):
 | 
			
		||||
            return False
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    Set the date/time a photo was taken
 | 
			
		||||
 | 
			
		||||
    @param, time, datetime, datetime object of when the photo was taken
 | 
			
		||||
 | 
			
		||||
    @returns, boolean
 | 
			
		||||
    """
 | 
			
		||||
    def set_datetime(self, time):
 | 
			
		||||
        if(time is None):
 | 
			
		||||
            return False
 | 
			
		||||
 | 
			
		||||
        source = self.source
 | 
			
		||||
        exif_metadata = pyexiv2.ImageMetadata(source)
 | 
			
		||||
        exif_metadata.read()
 | 
			
		||||
 | 
			
		||||
        exif_metadata['Exif.Photo.DateTimeOriginal'].value = time
 | 
			
		||||
        exif_metadata['Exif.Image.DateTime'].value = time
 | 
			
		||||
 | 
			
		||||
        exif_metadata.write()
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    Set lat/lon for a video
 | 
			
		||||
 | 
			
		||||
    @param, latitude, float, Latitude of the file
 | 
			
		||||
    @param, longitude, float, Longitude of the file
 | 
			
		||||
 | 
			
		||||
    @returns, boolean
 | 
			
		||||
    """
 | 
			
		||||
    def set_location(self, latitude, longitude):
 | 
			
		||||
        if(latitude is None or longitude is None):
 | 
			
		||||
            return False
 | 
			
		||||
 | 
			
		||||
        print 'SET LOCATION %s %s' % (latitude, longitude)
 | 
			
		||||
        result = self.__update_using_plist(latitude=latitude, longitude=longitude)
 | 
			
		||||
        return result
 | 
			
		||||
 | 
			
		||||
    def __update_using_plist(self, **kwargs):
 | 
			
		||||
        if('latitude' not in kwargs and 'longitude' not in kwargs):
 | 
			
		||||
            print 'No lat/lon passed into __create_plist'
 | 
			
		||||
            return False
 | 
			
		||||
 | 
			
		||||
        avmetareadwrite = find_executable('avmetareadwrite')
 | 
			
		||||
        if(avmetareadwrite is None):
 | 
			
		||||
            print 'Could not find avmetareadwrite'
 | 
			
		||||
            return False
 | 
			
		||||
 | 
			
		||||
        source = self.source
 | 
			
		||||
 | 
			
		||||
        # First we need to write the plist for an existing file to a temporary location
 | 
			
		||||
        with tempfile.NamedTemporaryFile() as plist_temp:
 | 
			
		||||
            # We need to write the plist file in a child process but also block for it to be complete.
 | 
			
		||||
            # http://stackoverflow.com/a/5631819/1318758
 | 
			
		||||
            avmetareadwrite_generate_plist_command = '%s -p "%s" "%s"' % (avmetareadwrite, plist_temp.name, source)
 | 
			
		||||
            write_process = subprocess.Popen([avmetareadwrite_generate_plist_command], stdout=subprocess.PIPE, shell=True)
 | 
			
		||||
            streamdata = write_process.communicate()[0]
 | 
			
		||||
            if(write_process.returncode != 0):
 | 
			
		||||
                print 'Failed to generate plist file'
 | 
			
		||||
                return False
 | 
			
		||||
 | 
			
		||||
            with open(plist_temp.name, 'r') as plist_written:
 | 
			
		||||
                plist_text = plist_written.read()
 | 
			
		||||
 | 
			
		||||
            # Once the plist file has been written we need to open the file to read and update it.
 | 
			
		||||
            plist_final = None
 | 
			
		||||
            with open(plist_temp.name, 'w') as plist_written:
 | 
			
		||||
                # Depending on the kwargs that were passed in we regex the plist_text before we write it back.
 | 
			
		||||
                if('latitude' in kwargs and 'longitude' in kwargs):
 | 
			
		||||
                    latitude = kwargs['latitude']
 | 
			
		||||
                    longitude = kwargs['longitude']
 | 
			
		||||
 | 
			
		||||
                    # Add a literal '+' to the lat/lon if it is positive.
 | 
			
		||||
                    # Do this first because we convert longitude to a string below.
 | 
			
		||||
                    lat_sign = '+' if latitude > 0 else ''
 | 
			
		||||
                    # We need to zeropad the longitude.
 | 
			
		||||
                    # No clue why - ask Apple.
 | 
			
		||||
                    # We set the sign to + or - and then we take the absolute value and fill it.
 | 
			
		||||
                    lon_sign = '+' if longitude > 0 else '-'
 | 
			
		||||
                    longitude_str = '{:9.5f}'.format(abs(longitude)).replace(' ', '0')
 | 
			
		||||
 | 
			
		||||
                    print longitude_str
 | 
			
		||||
                    print '>%s%s%s%s' % (lat_sign, latitude, lon_sign, longitude_str)
 | 
			
		||||
 | 
			
		||||
                    plist_updated_text = re.sub('\>([+-])([0-9.]+)([+-])([0-9.]+)', '>%s%s%s%s' % (lat_sign, latitude, lon_sign, longitude_str), plist_text);
 | 
			
		||||
                    plist_final = plist_written.name
 | 
			
		||||
                    plist_written.write(plist_updated_text)
 | 
			
		||||
                    
 | 
			
		||||
                    f = open('/Users/jaisenmathai/dev/tools/elodie/script.plist', 'w')
 | 
			
		||||
                    f.write(plist_updated_text)
 | 
			
		||||
                    f.close()
 | 
			
		||||
                    print plist_updated_text
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            # If we've written to the plist file then we proceed
 | 
			
		||||
            if(plist_final is None):
 | 
			
		||||
                print 'plist file was not be written to'
 | 
			
		||||
                return False
 | 
			
		||||
 | 
			
		||||
            # We create a temporary file to save the modified file to.
 | 
			
		||||
            # If the modification is successful we will update the existing file.
 | 
			
		||||
            temp_movie = None
 | 
			
		||||
            with tempfile.NamedTemporaryFile() as temp_file:
 | 
			
		||||
                temp_movie = temp_file.name
 | 
			
		||||
 | 
			
		||||
            # We need to block until the child process completes.
 | 
			
		||||
            # http://stackoverflow.com/a/5631819/1318758
 | 
			
		||||
            avmetareadwrite_command = '%s -w %s "%s" "%s"' % (avmetareadwrite, plist_written.name, source, temp_movie)
 | 
			
		||||
            update_process = subprocess.Popen([avmetareadwrite_command], stdout=subprocess.PIPE, shell=True)
 | 
			
		||||
            streamdata = update_process.communicate()[0]
 | 
			
		||||
            print streamdata
 | 
			
		||||
            if(update_process.returncode != 0):
 | 
			
		||||
                print '%s did not complete successfully' % avmetareadwrite_command
 | 
			
		||||
                return False
 | 
			
		||||
 | 
			
		||||
            # Before we do anything destructive we confirm that the file is in tact.
 | 
			
		||||
            metadata = self.get_metadata()
 | 
			
		||||
            if(metadata['latitude'] is None or metadata['longitude'] is None or metadata['date_taken'] is None):
 | 
			
		||||
                print 'Something went wrong updating video metadata'
 | 
			
		||||
                return False
 | 
			
		||||
 | 
			
		||||
            # Copy file information from original source to temporary file before copying back over
 | 
			
		||||
            print 'copy from %s to %s' % (temp_movie, source)
 | 
			
		||||
            shutil.copystat(source, temp_movie)
 | 
			
		||||
            shutil.move(temp_movie, source)
 | 
			
		||||
            return True
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    Static method to access static __valid_extensions variable.
 | 
			
		||||
 | 
			
		||||
@ -57,7 +291,7 @@ class Video(Media):
 | 
			
		||||
    """
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def get_valid_extensions(Video):
 | 
			
		||||
        return Video.__valid_extensions
 | 
			
		||||
        return Media.video_extensions
 | 
			
		||||
 | 
			
		||||
class Transcode(object):
 | 
			
		||||
    # Constructor takes a video object as it's parameter
 | 
			
		||||
 | 
			
		||||
@ -5,26 +5,24 @@ import shutil
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
from elodie import arguments
 | 
			
		||||
from elodie.media.photo import Media
 | 
			
		||||
from elodie.media.photo import Photo
 | 
			
		||||
from elodie.media.video import Video
 | 
			
		||||
 | 
			
		||||
def main(argv):
 | 
			
		||||
    args = arguments.parse(argv, None, ['file=','type='], './import.py --type=<photo or video> --file=<path to file>')
 | 
			
		||||
    args = arguments.parse(argv, None, ['file='], './import.py --file=<path to file>')
 | 
			
		||||
 | 
			
		||||
    if('file' not in args):
 | 
			
		||||
        print 'No file specified'
 | 
			
		||||
        sys.exit(1)
 | 
			
		||||
 | 
			
		||||
    if('type' in args and args['type'] == 'video'):
 | 
			
		||||
        media_type = Video
 | 
			
		||||
    else:
 | 
			
		||||
        media_type = Photo
 | 
			
		||||
    media = Media.get_class_by_file(args['file'], [Photo, Video])
 | 
			
		||||
 | 
			
		||||
    if(media is None):
 | 
			
		||||
        print 'Not a valid file'
 | 
			
		||||
        sys.exit(1)
 | 
			
		||||
 | 
			
		||||
    media = media_type(args['file'])
 | 
			
		||||
    metadata = media.get_metadata()
 | 
			
		||||
 | 
			
		||||
    print '%r' % metadata
 | 
			
		||||
 | 
			
		||||
    output = {'date_taken': metadata['date_taken']}
 | 
			
		||||
    print '%r' % output
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -6,6 +6,7 @@ import sys
 | 
			
		||||
 | 
			
		||||
from elodie import arguments
 | 
			
		||||
from elodie import geolocation
 | 
			
		||||
from elodie.media.photo import Media
 | 
			
		||||
from elodie.media.photo import Photo
 | 
			
		||||
from elodie.media.video import Video
 | 
			
		||||
 | 
			
		||||
@ -16,12 +17,12 @@ def main(argv):
 | 
			
		||||
        print 'No file specified'
 | 
			
		||||
        sys.exit(1)
 | 
			
		||||
 | 
			
		||||
    if('type' in args and args['type'] == 'photo'):
 | 
			
		||||
        media_type = Photo
 | 
			
		||||
    else:
 | 
			
		||||
        media_type = Video
 | 
			
		||||
    media = Media.get_class_by_file(args['file'], [Photo, Video])
 | 
			
		||||
 | 
			
		||||
    if(media is None):
 | 
			
		||||
        print 'Not a valid file'
 | 
			
		||||
        sys.exit(1)
 | 
			
		||||
 | 
			
		||||
    media = media_type(args['file'])
 | 
			
		||||
    metadata = media.get_metadata()
 | 
			
		||||
 | 
			
		||||
    place_name = geolocation.place_name(metadata['latitude'], metadata['longitude'])
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										39
									
								
								update.py
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								update.py
									
									
									
									
									
								
							@ -29,10 +29,6 @@ def parse_arguments(args):
 | 
			
		||||
    return config
 | 
			
		||||
 | 
			
		||||
def main(config, args):
 | 
			
		||||
    try:
 | 
			
		||||
        pyexiv2.xmp.register_namespace('https://github.com/jmathai/elodie/', 'elodie')
 | 
			
		||||
    except KeyError:
 | 
			
		||||
        pass
 | 
			
		||||
    location_coords = None
 | 
			
		||||
    for arg in args:
 | 
			
		||||
        if(arg[:2] == '--'):
 | 
			
		||||
@ -54,19 +50,20 @@ def main(config, args):
 | 
			
		||||
        if(_class is None):
 | 
			
		||||
            continue
 | 
			
		||||
 | 
			
		||||
        write = False
 | 
			
		||||
        exif_metadata = pyexiv2.ImageMetadata(file_path)
 | 
			
		||||
        exif_metadata.read()
 | 
			
		||||
        media = _class(file_path)
 | 
			
		||||
 | 
			
		||||
        updated = False
 | 
			
		||||
        if(config['location'] is not None):
 | 
			
		||||
            if(location_coords is None):
 | 
			
		||||
                location_coords = geolocation.coordinates_by_name(config['location'])
 | 
			
		||||
 | 
			
		||||
            if(location_coords is not None and 'latitude' in location_coords and 'longitude' in location_coords):
 | 
			
		||||
                exif_metadata['Exif.GPSInfo.GPSLatitude'] = geolocation.decimal_to_dms(location_coords['latitude'])
 | 
			
		||||
                exif_metadata['Exif.GPSInfo.GPSLatitudeRef'] = pyexiv2.ExifTag('Exif.GPSInfo.GPSLatitudeRef', 'N' if location_coords['latitude'] >= 0 else 'S')
 | 
			
		||||
                exif_metadata['Exif.GPSInfo.GPSLongitude'] = geolocation.decimal_to_dms(location_coords['longitude'])
 | 
			
		||||
                exif_metadata['Exif.GPSInfo.GPSLongitudeRef'] = pyexiv2.ExifTag('Exif.GPSInfo.GPSLongitudeRef', 'E' if location_coords['longitude'] >= 0 else 'W')
 | 
			
		||||
                write = True
 | 
			
		||||
                location_status = media.set_location(location_coords['latitude'], location_coords['longitude'])
 | 
			
		||||
                if(location_status != True):
 | 
			
		||||
                    print 'Failed to update location'
 | 
			
		||||
                    sys.exit(1)
 | 
			
		||||
                updated = True
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        if(config['time'] is not None):
 | 
			
		||||
            time_string = config['time']
 | 
			
		||||
@ -79,21 +76,15 @@ def main(config, args):
 | 
			
		||||
                sys.exit(1)
 | 
			
		||||
 | 
			
		||||
            if(time_format is not None):
 | 
			
		||||
                exif_metadata['Exif.Photo.DateTimeOriginal'].value = datetime.strptime(time_string, time_format)
 | 
			
		||||
                exif_metadata['Exif.Image.DateTime'].value = datetime.strptime(time_string, time_format)
 | 
			
		||||
                write = True
 | 
			
		||||
                time = datetime.strptime(time_string, time_format)
 | 
			
		||||
                media.set_datetime(time)
 | 
			
		||||
                updated = True
 | 
			
		||||
 | 
			
		||||
        if(config['album'] is not None):
 | 
			
		||||
            exif_metadata['Xmp.elodie.album'] = config['album']
 | 
			
		||||
            write = True
 | 
			
		||||
            media.set_album(config['album'])
 | 
			
		||||
            updated = True
 | 
			
		||||
                
 | 
			
		||||
        if(write == True):
 | 
			
		||||
            exif_metadata.write()
 | 
			
		||||
 | 
			
		||||
            exif_metadata = pyexiv2.ImageMetadata(file_path)
 | 
			
		||||
            exif_metadata.read()
 | 
			
		||||
 | 
			
		||||
            media = _class(file_path)
 | 
			
		||||
        if(updated == True):
 | 
			
		||||
            dest_path = filesystem.process_file(file_path, destination, media, move=True, allowDuplicate=True)
 | 
			
		||||
            print '%s -> %s' % (file_path, dest_path)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user