PhπΈtein
A no-nonsense way to organize your personal photo library.
What does it do?
Photein manages your photos at the filesystem level. It wonβt let you browse or edit your photos, but it will give them a uniform folder structure and filenames, no matter where they come from:
# Before # After
~ ~
βββ Downloads βββ Downloads
β βββ 1619593208911.jpeg βββ Pictures
β βββ DCIM βββ 2020
β β βββ 2021_03_26 β βββ 2020-08-01_113129.heic
β β βββ R0014285.MOV β βββ 2020-05-20_160209.png
β β βββ R0014286.DNG βββ 2021
β β βββ R0014286.JPG βββ 2021-02-12_081933a.jpg
β β βββ R0014287.DNG βββ 2021-02-12_081933b.jpg
β β βββ R0014287.JPG βββ 2021-02-12_081939.mp4
β βββ IMG_20210212_081933_001.jpg βββ 2021-03-26_161245.mp4
β βββ IMG_20210212_081933_002.jpg βββ 2021-03-26_161518.dng
β βββ IMG_8953.HEIC βββ 2021-03-26_161518.jpg
β βββ Screenshot_20200520_160209.png βββ 2021-03-26_170304.dng
β βββ VID_20210212_081939.mp4 βββ 2021-03-26_170304.jpg
βββ Pictures βββ 2021-04-28_000008.jpg
Photein generates these folders & filenames based on metadata timestamps, filename timestamps, or file creation times.
β οΈ Note
If you use a photo management app that decides where and how your photos should be stored on disk (looking at you, Apple Photos π), Photein is not for you.
It can also:
-
optimize photos and videos for reduced file size
-
shift all timestamps by a given interval (for when you forget to update the clock on your camera for, e.g., daylight savings or traveling across time zones)
-
backfill GPS metadata /
OffsetTime*
tags based on a given IANA time zoneπ€ Why would you want that?
One unfortunate quirk of this problem space is that the EXIF standard does not cover video file formats, meaning photos and videos do not have the same set of metadata fields. Worse yet, the field we care about most (timestamps) is inconsistently defined, with photo timestamps recorded in local time and video timestamps in UTC.
(I havenβt been able to find the text of these specsβsupposedly, they are expensiveβbut itβs been stated on a few occasions by a pretty authoritative member of the Exiftool forum. That same user has noted that βthere is no standard for embedding EXIF data in a video file. Not that that has stopped a lot of camera makers from forcing it into the file.β)
Photein attempts to set all filenames in local time, applying an offset to videos based on the time zone inferred from their GPS location tagsβwhich is only possible if they are present. Other photo utilities (like immich) follow the same strategy, meaning that setting GPS tags can improve filename consistency elsewhere, too.
(What about
OffsetTime*
, then? Those tags are superfluous for our needs since they can only be set on photos, which are already in local timeβbut implementation was straightforward, and they serve the parallel purpose of backfilling missing time zone info, so I figured what the heck. Β―\_(γ)_/Β―)
What doesnβt it do?
On its own, Photein is not an alternative to cloud photo services like Google Photos or iCloudβbut in combination with other software, it can be.
If you want to:
- import photos from your phone as soon as you take them
- import photos from a digital camera / SD card as soon as you plug it in
- mirror a low-res copy of your entire photo library to your Android phone
check out Photeinβs sister utility Xferase, or try the automation guides below.
Installation
$ gem install photein
Dependencies
- Ruby 2.6+
- ExifTool
- MediaInfo files)
- ImageMagick (for
--optimize-for=web
option) - OptiPNG (for
--optimize-for=web
option) - ffmpeg (for
--optimize-for={web,desktop}
options) -
mkvtoolnix (for
--shift-timestamp
/--local-tz
options on .webm
Usage
$ photein \
--source /media/ricoh_gr/DCIM \ # batch-import photos from here
--recursive \ # including subdirectories
--dest /home/rlue/Pictures # into here
Use photein --help
for a summary of all options.
Supported media formats
- .jpg
- .dng
- .heic
- .png
- .mp4
- .mov
Automation guides
Using Photein + systemd, you can:
But for more complex tasks, like:
- π±β‘οΈπ₯οΈ Setting up auto-import from an Android phone
- π±ππ₯οΈ Mirroring your library across multiple devices
check out the documentation for Xferase, an always-on background service based on Photein.
Development
Contributions welcome.
β οΈ Warning
The RSpec test suite contains no unit tests. It solely tests
photein
as a CLI utility, or in other words, it defines expectations against the effects ofsystem('photein <args>')
.Because
Kernel#system
runs the given command in a subprocess, it prints to a different stdout thanrspec
itself. This makes test failures cumbersome to debug, becauseputs
statements never appear in the test output, andbinding.pry
will cause the test to appear to hang as it waits for user input on an invisible stdin.
License
Β© 2021 Ryan Lue. This project is licensed under the terms of the MIT License.