Description of a folder

From ActiveArchives
Jump to: navigation, search

Script used for the Erkki Kurenniemi: In 2048, and Dataradio.

Takes a folder of images produces a textual reading of the images, mainly describing the time intervals between each images' EXIF date/timestamp.

#!/bin/bash
 
for i
do
echo $i
filename=$(basename "$i")
basename=${filename%.*}
o="doaf_$basename.ogg"
 
python exifreader.py "$i" > tmp.txt
text2wave -o tmp.wav < tmp.txt
sox tmp.wav silence.wav tmp2.wav
ffmpeg -i tmp2.wav -ac 2 -y -metadata album="Description of a folder" \
  -metadata title="Description of a folder: $filename" \
  -acodec libvorbis "$o"
 
# cleanup
rm tmp.txt
rm tmp.wav
rm tmp2.wav
done

exifreader.py

import sys, pyexiv2, os, humanize
from num2eng import num2eng
 
 
paths = sys.argv[1:]
lasttime = None
WDAYS = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
MDAYS = ["first", "second", "third", "fourth", "fifth", "sixth", "seventh", "eighth", "ninth", "tenth", "eleventh", "twelfth", "thirteenth", "fourteenth", "fifteenth", "sixteenth", "seventeenth", "eighteenth", "nineteenth", "twentieth", "twenty-first", "twenty-second", "twenty-third", "twenty-fourth", "twenty-fifth", "twenty-sixth", "twenty-seventh", "twenty-eighth", "twenty-nineth", "thirtieth", "thirty-first"]
 
 
# 1. describe an image...
# 2. describe a folder of images...
 
def small_number (n):
    return str(n)
    # return humanize.apnumber(n)
 
def describe_date (d):
    ret = ""
    ret += d.strftime("%A")
    ret += " the "+MDAYS[d.day-1]
    ret += d.strftime(" of %B")
    if d.year < 2000:
        ret += ", " + str(d.year)[:2] + " " + str(d.year)[2:]
    else:
        ret += ", " + str(d.year)
    return ret
 
def describe_minutes(dt):
    m = dt.minute
    if m == 0:
        return "o'clock"
    elif m < 10:
#        return "o " + num2eng(m).strip()
        return "o " + str(m)
    else:
        return str(m)
#        return num2eng(m).strip()
#        return humanize.apnumber(m)
 
def describe_time(dt):
    ret = ""
    h = dt.hour
    if h < 12:
        ret += small_number(h)
        ret += " " + describe_minutes(dt)
        ret += " in the morning"
    elif h == 12:
        ret += small_number(h)
        ret += " " + describe_minutes(dt)
        ret += " in the afternoon"
    else:
        h -= 12
        ret += small_number(h)
        ret += " " + describe_minutes(dt)
        if h < 6:
            ret += " in the afternoon"
        else:
            ret += " in the evening"
    return ret
 
def describe_datetime_full (dt):
    ret = describe_date(dt)
    ret +=", at " + describe_time(dt)
    return ret
 
 
tags = [ 'Exif.Image.Orientation',
 'Exif.Image.Make',
 'Exif.Image.Model',
 'Exif.Photo.Flash',
 'Exif.Photo.FocalLength',
 'Exif.Photo.ExposureTime',
 'Exif.Photo.FNumber',
 'Exif.Photo.ExposureProgram',
'Exif.Image.ImageDescription'
 'Exif.Photo.MeteringMode',
 'Exif.Photo.LightSource',
 'Exif.Photo.SceneType' ]
 
def describe_filesize (bytes):
    ret = humanize.naturalsize(bytes)
    ret = ret.replace("kB", "kilobytes")
    ret = ret.replace("MB", "megabytes")
    return ret
 
def describe_mime (mt):
    _, mt = mt.split('/', 1)
    mt = mt.replace("jpeg", "j-peg")
    return mt
 
def describe_interval (start, end):
    return humanize.naturaltime(end - start).replace("ago", "later")
 
def describe_image (ipath):
    _, parname = os.path.split(os.path.abspath(os.path.join(ipath, os.path.pardir)).rstrip("/"))
    metadata = pyexiv2.ImageMetadata(ipath)
    metadata.read()
    global meta
    meta = metadata
    statinfo = os.stat(ipath)
    phrases = []
    phrases.append("Description of an image")
    dt = metadata['Exif.Image.DateTime'].value
    _, filename = os.path.split(ipath)
    phrases.append("The name of the file is {}, contained in a folder named {}".format(
        filename, parname
    ))
    phrases.append("The size of the file is {} and it's format is {}".format(
        describe_filesize(statinfo.st_size),
        describe_mime(meta.mime_type)
    ))
    phrases.append("It is an image with dimensions {} by {} pixels".format(meta.dimensions[0],   meta.dimensions[1]))
    phrases.append("According to the metadata within the file, the camera used was a {} {}".format(
        meta['Exif.Image.Make'].raw_value,
        meta['Exif.Image.Model'].raw_value
    ))
    phrases.append("The image was taken {} on {}".format(humanize.naturaltime(dt), describe_datetime_full(dt)))
    exp = metadata['Exif.Photo.ExposureTime'].raw_value
    if exp:
        phrases.append("The exposure time was {} of a second".format(exp))
    flash = meta['Exif.Photo.Flash'].value != 0
    if flash:
        phrases.append("The flash was used")
    else:
        phrases.append("The flash was not used")
    return ".\n".join(phrases)
 
def describe_image_folder (path):
    phrases = []
    phrases.append("Description of a folder")
    times = []
    _, fname = os.path.split(path.rstrip("/"))
    for ipath in os.listdir(path):
        if ipath.startswith("."): continue
        fpath = os.path.join(path, ipath)
#        print fpath
        try:
            metadata = pyexiv2.ImageMetadata(fpath)
            metadata.read()
            # print "\n".join(metadata.exif_keys)
            dt = metadata['Exif.Image.DateTime']
            # print dt.raw_value, dt.value
            dt = dt.value
            times.append(dt)
        except IOError:
            pass
    times.sort()
    phrases.append("The folder, named {0}, contains {1} images".format(fname, len(times)))
 
    phrases.append("The first image was taken {0}, on {1}".format(humanize.naturaltime(dt), describe_datetime_full(times[0])))
 
    lasttime = None
    for i, dt in enumerate(times):
        if lasttime:
            if (i+1 < len(times)):
                phrases.append("{0}, image {1} was taken".format(describe_interval(lasttime, dt), (i+1)))
            else:
                phrases.append("{0}, at {1}, image {2}, the final image, was taken".format(describe_interval(lasttime, dt), describe_time(times[-1]), (i+1)))
 
        lasttime = dt
 
    span = describe_interval(times[-1], times[0]).replace(" from now", "")
    phrases.append("From first to last image, the folder represents a span of {}".format(span))
 
    return ".\n".join(phrases)
 
if __name__ == "__main__":
    meta = None
    p = sys.argv[1]
    if os.path.isfile(p):
        print describe_image(p)
    else:
        print describe_image_folder(p).lower()

Sample Result

Doaf venetsia.ogg
description of a folder.
the folder, named venetsia, contains 15 images.
the first image was taken 10 years ago, on thursday the twelfth of june, 2003, at 5 49 in the afternoon.
33 minutes later, image 2 was taken.
20 seconds later, image 3 was taken.
an hour later, image 4 was taken.
28 minutes later, image 5 was taken.
26 minutes later, image 6 was taken.
a minute later, image 7 was taken.
33 minutes later, image 8 was taken.
2 minutes later, image 9 was taken.
7 minutes later, image 10 was taken.
59 seconds later, image 11 was taken.
18 seconds later, image 12 was taken.
6 minutes later, image 13 was taken.
8 minutes later, image 14 was taken.
7 minutes later, at 9 44 in the evening, image 15, the final image, was taken.
from first to last image, the folder represents a span of 3 hours
Personal tools
Namespaces

Variants
Actions
Navigation
Toolbox