media#

mediautils.media.gather_yes_no(in_dir: str | PathLike = 'in', out_dir: str | PathLike = 'out') → list[Path][source]#

Copy culled files from nested yes/no subdirectories to output buckets.

Recursively scans in_dir for files whose immediate parent directory is named yes or no, and copies them to out_dir/yes or out_dir/no respectively. Files in any other directory (e.g. temp) are ignored.

Parameters:
  • in_dir (str | os.PathLike) – Root directory to scan recursively.

  • out_dir (str | os.PathLike) – Output root. yes and no subdirectories are created as needed.

Returns:

Paths to the copied output files.

Return type:

list[Path]

mediautils.media.process_camera_timezone(camera_timezone: str, in_dir: str | PathLike = 'in', out_dir: str | PathLike = 'out', real_timezone: str = 'Europe/Paris') → list[Path][source]#

Correct photos from a camera left on a foreign time zone.

For a camera whose clock was never switched from camera_timezone while actually being used in real_timezone, corrects every file in in_dir with a standardized name (YYYYMMDD_HHMMSS...): the datetime encoded in the file name’s prefix is reinterpreted as a camera_timezone wall-clock reading, then converted — via the IANA time zone database, so daylight-saving time is resolved per the photo’s own date — to the corresponding real_timezone wall-clock time and UTC offset.

Unlike process_timezone_shift(), no reference photo is needed: both time zones are known upfront, so the correction is computed directly and stays correct even if in_dir spans a DST transition in either zone (the US and the EU do not switch to/from DST on the same dates, so the gap between them is not always the same number of hours).

For each file, writes a copy to out_dir with:

  • the file name’s YYYYMMDD_HHMMSS prefix replaced by the corrected datetime — anything after the prefix (e.g. the camera’s own original file name, kept as an identifier back to the source device) is left untouched, see replace_datetime_prefix();

  • for JPEG/RAW images, datetime_original/DateTimeOriginal and offset_time_original/OffsetTimeOriginal set to the corrected real_timezone datetime and UTC offset; videos have their creation_time set via set_time() (no offset tag);

  • the copy’s filesystem creation, modification and access times set to match, for the same reasons as process_clock_shift().

.xmp sidecars are not supported: the text-substitution approach used by process_clock_shift() assumes the offset embedded in the file does not change, which is false for a genuine time zone correction.

Parameters:
  • camera_timezone (str) – IANA time zone the camera’s clock was left on (e.g. "America/New_York").

  • in_dir (str | os.PathLike) – Directory containing the files to correct, with standardized names.

  • out_dir (str | os.PathLike) – Directory where corrected copies are saved.

  • real_timezone (str) – IANA time zone the photos were actually taken in.

Returns:

Paths to the output files.

Return type:

list[Path]

Raises:

ValueError – If a file has an unsupported extension, including .xmp.

mediautils.media.process_clock_shift(delta: timedelta, in_dir: str | PathLike = 'in', out_dir: str | PathLike = 'out') → list[Path][source]#

Correct a flat camera clock drift/error affecting a batch of files.

For each file in in_dir with a standardized name (YYYYMMDD_HHMMSS...), adds delta to the datetime encoded in the file name, then writes a copy to out_dir with:

  • the file name’s YYYYMMDD_HHMMSS prefix replaced by the corrected datetime (see replace_datetime_prefix());

  • the metadata timestamp set to the corrected datetime, dispatched by file extension like set_time() (EXIF datetime_original for images and RAW files, MP4/MOV creation_time for videos); .xmp sidecar files (e.g. Lightroom edits) are instead handled by shifting their embedded dates via text substitution, see _shift_xmp_datetimes();

  • the copy’s filesystem creation, modification and access times set to match (see set_file_creation_time()), since tools like FastStone Image Viewer’s rename feature read those instead of the EXIF metadata, and to give every tool the best chance of sorting the files chronologically.

Unlike process_timezone_shift(), this does not touch any EXIF timezone/offset tag: it corrects a clock drift (the camera’s wall-clock reading was wrong), not a timezone error, so an existing offset tag is still correct and is left untouched.

Parameters:
  • delta (timedelta) – Amount to add to every timestamp. Use a negative value if the camera’s clock was ahead of the real time.

  • in_dir (str | os.PathLike) – Directory containing the files to correct, with standardized names.

  • out_dir (str | os.PathLike) – Directory where corrected copies are saved.

Returns:

Paths to the output files.

Return type:

list[Path]

mediautils.media.process_date_subdirs(in_dir: str | PathLike = 'in', out_dir: str | PathLike = 'out') → list[Path][source]#

Process files organized in date-named subdirectories.

Each subdirectory of in_dir must have a name starting with YYYYMMDD. Files inside each subdirectory are assigned timestamps near end of day (incrementing by one second per file), renamed to YYYYMMDD_HHMMSS_originalname, and written to out_dir with updated metadata.

Parameters:
  • in_dir (str | os.PathLike) – Directory containing date-named subdirectories.

  • out_dir (str | os.PathLike) – Directory where processed files are saved.

Returns:

Paths to the output files.

Return type:

list[Path]

mediautils.media.process_datetime_filenames(in_dir: str | PathLike = 'in', out_dir: str | PathLike = 'out') → list[Path][source]#

Process files with standardized names: set timestamps from file names.

For each file in in_dir whose name starts with YYYYMMDD_HHMMSS, writes a copy to out_dir with metadata matching the datetime encoded in the file name.

Parameters:
  • in_dir (str | os.PathLike) – Directory containing media files with standardized names.

  • out_dir (str | os.PathLike) – Directory where processed files are saved.

Returns:

Paths to the output files.

Return type:

list[Path]

mediautils.media.process_timezone_shift(phone_reference: str | PathLike, in_dir: str | PathLike = 'in', out_dir: str | PathLike = 'out', home_timezone: str = 'Europe/Paris') → list[Path][source]#

Correct the recorded time of images from a camera left on the wrong timezone.

For a trip where the camera’s clock was never updated from home_timezone while the phone auto-updated to the destination’s local time, phone_reference (any photo taken on the phone during the trip, with correct local time and an offset_time_original EXIF tag) is enough to derive both the destination’s UTC offset and the camera’s clock error: the true instant of phone_reference is computed from its own datetime and offset, then compared to what a home_timezone clock would have displayed at that same instant. That gap, plus the destination offset, are applied to every image in in_dir: for each one, reads its datetime_original, shifts it by the gap, and writes a copy to out_dir with the corrected datetime and the destination offset_time_original. The copy’s filesystem creation, modification and access times are also set to match (see set_file_creation_time()), since tools like FastStone Image Viewer’s rename feature read those instead of the EXIF metadata. File names are left untouched.

Parameters:
  • phone_reference (str | os.PathLike) – Path to any phone photo taken during the trip, with correct local time and an offset_time_original EXIF tag.

  • in_dir (str | os.PathLike) – Directory containing the camera images to correct.

  • out_dir (str | os.PathLike) – Directory where corrected copies are saved.

  • home_timezone (str) – IANA timezone the camera’s clock was left on (e.g. "Europe/Paris").

Returns:

Paths to the output files.

Return type:

list[Path]

Raises:
  • ValueError – If in_dir contains no files, or if phone_reference has no offset_time_original EXIF tag.

  • NotImplementedError – If not running on Windows.

mediautils.media.process_videos(in_dir: str | PathLike = 'in', out_dir: str | PathLike = 'out', tz: str = 'Europe/Paris', shift: timedelta = datetime.timedelta(0)) → list[Path][source]#

Standardize the names of videos and set all their dates accordingly.

Each video of in_dir, subdirectories included, is copied to out_dir under its standardized name (see standardize_name()), in the same relative subdirectory, with every date it carries set to the datetime of that name (see set_all_dates_video()).

Files that cannot be processed (unknown naming convention, extension that is not a video, name already taken in out_dir, date that cannot be set) are left untouched, produce no output, and are listed at the end. Dates exiftool cannot write but that already give the right time are accepted silently.

Parameters:
  • in_dir (str | os.PathLike) – Directory containing the videos, possibly in subdirectories.

  • out_dir (str | os.PathLike) – Directory where processed videos are saved.

  • tz (str) – IANA timezone in which the datetimes of the file names are expressed.

  • shift (timedelta) – Correction added to the datetime of each (standardized) name, e.g. for a camera whose clock was off, or to switch to the local time of a trip abroad. The prefix of the name is changed accordingly, and so are the dates exiftool cannot write (Lumix EXIF block and XML metadata).

Returns:

Paths to the output files.

Return type:

list[Path]

mediautils.media.process_whatsapp_files(in_dir: str | PathLike = 'in', out_dir: str | PathLike = 'out') → list[Path][source]#

Process WhatsApp media files: set timestamps and rename.

For each file in in_dir, extracts the date from the WhatsApp file name, assigns a time near end of day (incrementing by one second per file within the same date), renames to YYYYMMDD_HHMMSS_originalname, and writes the result to out_dir with updated metadata.

Parameters:
  • in_dir (str | os.PathLike) – Directory containing WhatsApp media files.

  • out_dir (str | os.PathLike) – Directory where processed files are saved.

Returns:

Paths to the output files.

Return type:

list[Path]

mediautils.media.set_time(path: str | PathLike, dt: datetime, out_dir: str | PathLike = 'out', out_name: str | None = None) → Path[source]#

Write a copy of an image or video with its timestamps set to dt.

Dispatches to set_time_image() or set_time_video() based on the file extension.

Parameters:
  • path (str | os.PathLike) – Path to the source file.

  • dt (datetime) – The datetime to write into the metadata.

  • out_dir (str | os.PathLike) – Directory where the modified copy is saved. Created if it does not exist.

  • out_name (str | None) – Output file name. If None, the original file name is kept.

Returns:

Path to the output file.

Return type:

Path

Raises:

ValueError – If the file extension is not supported.