Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 33 additions & 12 deletions bereal_exporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from shutil import copy2 as cp
from datetime import datetime as dt
import argparse
from PIL import Image



Expand Down Expand Up @@ -94,12 +95,25 @@ def get_datetime_from_str(time: str) -> dt:

def export_img(self, old_img_name: str, img_name: str, img_dt: dt, img_location=None):
"""
Makes a copy of the image and adds EXIF tags to the image.
Makes a copy of the image or video and adds EXIF tags to supported formats.
"""
self.verbose_msg(f"Export {old_img_name} image to {img_name}")

if os.path.isfile(old_img_name):
cp(old_img_name, img_name)
if not os.path.isfile(old_img_name):
self.verbose_msg(f"File not found: {old_img_name}")
return

ext = os.path.splitext(old_img_name)[1].lower()

# Video and image formats supported
video_exts = [".mp4", ".mov", ".avi", ".mkv", ".m4v", ".hevc", ".webm"]
image_exts = [".jpg", ".jpeg", ".tif", ".tiff", ".png", ".heic", ".webp"]

cp(old_img_name, img_name)
self.verbose_msg(f"Copied file ({ext})")

# For .webp images only, try to add EXIF metadata
if ext == ".webp":
tags = {"DateTimeOriginal": img_dt.strftime("%Y:%m:%d %H:%M:%S")}
if img_location:
self.verbose_msg(f"Add metadata to image:\n - DateTimeOriginal={img_dt}\n - GPS=({img_location['latitude']}, {img_location['longitude']})")
Expand All @@ -109,15 +123,13 @@ def export_img(self, old_img_name: str, img_name: str, img_dt: dt, img_location=
})
else:
self.verbose_msg(f"Add metadata to image:\n - DateTimeOriginal={img_dt}")

if self.exiftool_path:
et(executable=self.exiftool_path).set_tags(img_name, tags=tags, params=["-P", "-overwrite_original"])
else:
et().set_tags(img_name, tags=tags, params=["-P", "-overwrite_original"])
else:
self.verbose_msg(f"File {old_img_name} not found. Skipping this image.")


try:
with et(executable=self.exiftool_path) if self.exiftool_path else et() as exif:
exif.set_tags(img_name, tags=tags, params=["-P", "-overwrite_original"])
except Exception as e:
self.verbose_msg(f"Could not write EXIF to {img_name}: {e}")

def export_memories(self, memories: list):
"""
Exports all memories from the Photos/post directory to the corresponding output folder.
Expand All @@ -138,7 +150,16 @@ def export_memories(self, memories: list):

if self.time_span[0] <= memory_dt <= self.time_span[1]:
for img_name, type in zip(img_names, types):
old_img_name = os.path.join(self.bereal_path, f"Photos/post/{self.get_img_filename(memory[type[0]])}")

# Recreating local photo path from json file
json_path = memory[type[0]]['path'].lstrip("/")
parts = json_path.split("/")
if len(parts) > 3 and parts[0] == "Photos":
clean_path = os.path.join(parts[0], parts[2], *parts[3:])
else:
clean_path = json_path # fallback
old_img_name = os.path.join(self.bereal_path, clean_path)

self.verbose_msg(f"Export Memory nr {i} {type[0]}:")
if 'location' in memory:
self.export_img(old_img_name, img_name, memory_dt, memory['location'])
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
pyexiftool=0.5.6
Pillow pyexiftool