Project

photein

0.0
The project is in a healthy, maintained state
Import/rename photos & videos from one directory to another.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
 Dependencies

Development

~> 3.10

Runtime

~> 1.6
~> 0.6
~> 0.1
~> 3.4
~> 2.0
~> 0.0
~> 1.5
~> 1.11
~> 0.2
 Project Readme

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 of system('photein <args>').

Because Kernel#system runs the given command in a subprocess, it prints to a different stdout than rspec itself. This makes test failures cumbersome to debug, because puts statements never appear in the test output, and binding.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.