ordigi/elodie/media/video.py

122 lines
4.0 KiB
Python

"""
The video module contains the :class:`Video` class, which represents video
objects (AVI, MOV, etc.).
.. moduleauthor:: Jaisen Mathai <jaisen@jmathai.com>
"""
# load modules
from distutils.spawn import find_executable
import tempfile
from datetime import datetime
import os
import re
import shutil
import subprocess
import time
from elodie import constants
from elodie import plist_parser
from elodie.dependencies import get_exiftool
from media import Base
from media import Media
class Video(Media):
"""A video object.
:param str source: The fully qualified path to the video file.
"""
__name__ = 'Video'
#: Valid extensions for video files.
extensions = ('avi', 'm4v', 'mov', 'mp4', 'mpg', 'mpeg', '3gp')
def __init__(self, source=None):
super(Video, self).__init__(source)
self.exif_map['date_taken'] = [
'QuickTime:CreationDate',
'QuickTime:CreationDate-und-US',
'QuickTime:MediaCreateDate'
]
self.title_key = 'XMP:DisplayName'
self.latitude_keys = [
'XMP:GPSLatitude',
#'QuickTime:GPSLatitude',
'Composite:GPSLatitude'
]
self.longitude_keys = [
'XMP:GPSLongitude',
#'QuickTime:GPSLongitude',
'Composite:GPSLongitude'
]
self.latitude_ref_key = 'EXIF:GPSLatitudeRef'
self.longitude_ref_key = 'EXIF:GPSLongitudeRef'
self.set_gps_ref = False
def get_avmetareadwrite(self):
"""Get path to executable avmetareadwrite binary.
We wrap this since we call it in a few places and we do a fallback.
:returns: None or string
"""
avmetareadwrite = find_executable('avmetareadwrite')
if(avmetareadwrite is None):
avmetareadwrite = '/usr/bin/avmetareadwrite'
if(not os.path.isfile(avmetareadwrite) or not os.access(avmetareadwrite, os.X_OK)): # noqa
return None
return avmetareadwrite
def get_date_taken(self):
"""Get the date which the photo was taken.
The date value returned is defined by the min() of mtime and ctime.
:returns: time object or None for non-photo files or 0 timestamp
"""
if(not self.is_valid()):
return None
source = self.source
seconds_since_epoch = min(os.path.getmtime(source), os.path.getctime(source)) # noqa
exif = self.get_exiftool_attributes()
for date_key in self.exif_map['date_taken']:
if date_key in exif:
# Example date strings we want to parse
# 2015:01:19 12:45:11-08:00
# 2013:09:30 07:06:05
date = re.search('([0-9: ]+)([-+][0-9:]+)?', exif[date_key])
if(date is not None):
date_string = date.group(1)
date_offset = date.group(2)
try:
exif_seconds_since_epoch = time.mktime(
datetime.strptime(
date_string,
'%Y:%m:%d %H:%M:%S'
).timetuple()
)
if(exif_seconds_since_epoch < seconds_since_epoch):
seconds_since_epoch = exif_seconds_since_epoch
if date_offset is not None:
offset_parts = date_offset[1:].split(':')
offset_seconds = int(offset_parts[0]) * 3600
offset_seconds = offset_seconds + int(offset_parts[1]) * 60 #noqa
if date_offset[0] == '-':
seconds_since_epoch - offset_seconds
elif date_offset[0] == '+':
seconds_since_epoch + offset_seconds
except:
pass
if(seconds_since_epoch == 0):
return None
return time.gmtime(seconds_since_epoch)