Skip to main content

photo-metadata

Python library to extract, read, modify, and write photo and video metadata (EXIF, IPTC, XMP) using ExifTool. Supports JPEG, RAW, and video files.


PyPI Downloads


📕 README_Japanese


photo-metadata is a Python library for extracting, manipulating, and writing metadata from photo and video files. It uses ExifTool as a backend and supports a wide range of image and video formats. Full support for Japanese tags is also provided.


Key Features

  • Extract metadata from photos and videos
  • Read, write, and delete metadata
  • Convenient methods for various metadata operations
  • Compare two Metadata objects
  • Filter multiple files by metadata
  • Rename multiple files based on capture date or other metadata

Supported OS

  • Windows
  • Linux

Installation

pip install photo-metadata

Dependencies

  • [ExifTool] (needs to be installed separately; either add to PATH or provide full path)
  • [tqdm] (automatically installed via pip; used for progress display)
  • [charset-normalizer] (automatically installed via pip; used for encoding detection)

Configuring ExifTool

import photo_metadata

# Set the path to ExifTool
photo_metadata.set_exiftool_path(exiftool_path)

Notes

The default exiftool_path is "exiftool". If ExifTool is already in your PATH, calling set_exiftool_path is not required.


Metadata Class

The Metadata class is the core class for working with metadata.

from photo_metadata import Metadata

Initialization

metadata = Metadata(file_path="path/to/your/image.jpg")
  • file_path (str): Path to the image file

Accessing Metadata

Metadata can be accessed like a dictionary.

Access using English tags:

date_time = metadata["EXIF:DateTimeOriginal"]
print(date_time)

Access using Japanese tags:

date_time = metadata[photo_metadata.key_ja_to_en("EXIF:撮影日時")]
print(date_time)

Modifying Metadata

You can modify metadata like a dictionary:

metadata["EXIF:DateTimeOriginal"] = "2024:02:17 12:34:56"

Writing Metadata to File

metadata.write_metadata_to_file()

Deleting Metadata

Metadata can be deleted using the del statement:

del metadata["EXIF:DateTimeOriginal"]

Comparison

Two Metadata objects can be compared using == and !=:

metadata1 = Metadata("image1.jpg")
metadata2 = Metadata("image2.jpg")

if metadata1 == metadata2:
    print("Metadata is identical")
else:
    print("Metadata is different")

Working with Multiple Files – MetadataBatchProcess Class

MetadataBatchProcess allows you to process metadata for multiple files.

from photo_metadata import MetadataBatchProcess

Initialization

mbp = MetadataBatchProcess(file_path_list)

Filter Files by Metadata

mbp.filter_by_metadata(
    keyword_list=["NEX-5R", 2012],
    exact_match=True,
    all_keys_match=True,
    search_by="value"
)

for file, md in mbp.metadata_objects.items():
    print(f"{os.path.basename(file)}")

This example keeps files whose metadata values include both "NEX-5R" and 2012.

Filter Using Custom Conditions

mbp.filter_by_custom_condition(
    lambda md: md[photo_metadata.key_ja_to_en("EXIF:F値")] >= 4.0
    and md[photo_metadata.key_ja_to_en("EXIF:モデル")] == 'NEX-5R'
)

for file, md in mbp.metadata_objects.items():
    print(f"{os.path.basename(file)}")

This example keeps files where the EXIF F-number is ≥ 4.0 and the camera model is 'NEX-5R'.

Rename Files Using Metadata

import os
from tkinter import filedialog
from photo_metadata import MetadataBatchProcess, Metadata

def date(md: Metadata):
    date = md.get_date('%Y-%m-%d_%H.%M.%S', default_time_zone="+00:00")
    if date == md.error_string:
        raise Exception("Not Found")
    return f"{date}-{MetadataBatchProcess.DUP_SEQ_1_DIGIT}"  # This is a duplicate sequence. It increments if duplicates exist, starting from 0. Must be included in the format.

file_path_list = list(map(os.path.normpath, filedialog.askopenfilenames()))
mbp = MetadataBatchProcess(file_path_list)

# Prepare rename creates new_name_dict for preview
mbp.prepare_rename(format_func=date)

print("new_name_dict")
for file, new_name in mbp.new_name_dict.items():
    print(f"{file}\n{new_name}")

print("\nerror_dist")
for file, new_name in mbp.error_files.items():
    print(f"{file}\n{new_name}")

input("Press Enter to rename files")

mbp.rename_files()

API Reference

photo_metadata

  • get_key_map() -> dict: Returns a dictionary for Japanese key conversion.
  • set_exiftool_path(exiftool_path: str | Path) -> None: Sets the path to exiftool.
  • get_exiftool_path() -> Path: Returns the configured path to exiftool.
  • set_jp_tags_json_path(jp_tags_json_path: str | Path) -> None: Sets the path to the Japanese tags JSON file.
  • get_jp_tags_json_path() -> Path: Returns the configured path to the Japanese tags JSON file.
  • key_en_to_ja(key_en: str) -> str: Converts an English key to its Japanese equivalent.
  • key_ja_to_en(key_ja: str) -> str: Converts a Japanese key to its English equivalent.

photo_metadata.Metadata

  • __init__(self, file_path: str | Path): Constructor.

  • display_japanese(self, return_type: Literal["str", "print", "dict"] = "print") -> str: Displays metadata using Japanese keys.

  • write_metadata_to_file(self, file_path: str = None) -> None: Writes metadata to a file.

  • get_metadata_dict(self) -> dict: Returns the metadata as a dictionary.

  • export_metadata(self, output_path: str = None, format: Literal["json", "csv"] = 'json', lang_ja_metadata: bool = False) -> None: Exports metadata to a file.

  • keys(self) -> list[str]: Returns a list of metadata keys.

  • values(self) -> list[Any]: Returns a list of metadata values.

  • items(self) -> list[tuple[str, Any]]: Returns a list of key-value pairs for metadata.

  • get_gps_coordinates(self) -> str: Returns GPS coordinates.

  • export_gps_to_google_maps(self) -> str: Converts GPS information to a Google Maps URL.

  • get_date(self, format: str = '%Y:%m:%d %H:%M:%S', default_time_zone: str = '+00:00') -> str: Returns the capture date (customizable date format).

  • get_image_dimensions(self) -> str: Returns image dimensions.

  • get_file_size(self) -> tuple[str, int]: Returns the file size.

  • get_model_name(self) -> str: Returns the camera model name.

  • get_lens_name(self) -> str: Returns the lens name.

  • get_focal_length(self) -> dict: Returns focal length information.

  • show(self) -> None: Displays the file.

  • get_main_metadata(self) -> dict: Returns major metadata fields.

  • contains_key(self, key, exact_match: bool = True): Checks whether the specified key exists.

  • contains_value(self, value, exact_match: bool = True): Checks whether the specified value exists.

  • copy(self) -> "Metadata": Copies the instance of the Metadata class.

  • @classmethod def load_all_metadata(cls, file_path_list: list[str], progress_func: Callable[[int], None] | None = None, max_workers: int = 40) -> dict[str, "Metadata"]: Efficiently loads metadata from multiple files in parallel.

photo_metadata.MetadataBatchProcess

  • __init__(self, file_list: list[str], progress_func: Callable[[int], None] | None = None, max_workers: int = 40): Constructor.
  • filter_by_custom_condition(self, condition_func: Callable[[Metadata], bool]) -> None: Filters metadata using a custom condition function.
  • filter_by_metadata(self, keyword_list: list[str], exact_match: bool, all_keys_match: bool, search_by: Literal["either", "value", "key"]) -> None: Finds files containing specific values, keys, or either in their metadata.
  • prepare_rename(self, format_func: Callable[[Metadata], str]) -> None: Prepares files for renaming.
  • rename_files(self) -> str: Renames the files.
  • copy(self) -> "MetadataBatchProcess": Copies the instance of the MetadataBatchProcess class.

If you find this library useful, please consider giving it a ⭐ on GitHub!


URLs

  • PyPI: https://pypi.org/project/photo-metadata/
  • GitHub: https://github.com/kingyo1205/photo-metadata

Notes

ExifTool is required. This library uses ExifTool as an external command to process image and video metadata.


About AI-assisted Code Generation

Some parts of the code in this repository were generated or assisted by AI tools such as ChatGPT and Gemini CLI.


Required Software

ExifTool must be installed on your system. Download it from the official website.


License

This library is distributed under the MIT License.

However, this library utilizes ExifTool as an external tool, and ExifTool is distributed under a dual license (GPL 1.0 or later, or Artistic License 1.0).

If you use ExifTool, please make sure to comply with its license terms.

Dependencies and Licenses

Library
charset_normalizer
tqdm

Metadata

Release files for photo-metadata 0.3.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for photo-metadata 0.3.2
File Size Uploaded
photo_metadata-0.3.2.tar.gz 23.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for photo-metadata 0.3.2
File Interpreter ABI Platform
photo_metadata-0.3.2-py3-none-any.whl Python 3 none any Details

Total release size: 43.0 kB

Release files / photo_metadata-0.3.2.tar.gz

Download URL photo_metadata-0.3.2.tar.gz
Size 23.2 kB
Tags Source
SHA-256 checksum
How to use checksums
a9c8fb2ee58c9a93fe11cbde1c7a427dfeec25d030bd6a6c3e1c026465a272d8
BLAKE2b-256 checksum
How to use checksums
83ec89221b79d22e088f13008e770ea3f16497c017c9413c9e0cc799010e3aa5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.10

Release files / photo_metadata-0.3.2-py3-none-any.whl

Download URL photo_metadata-0.3.2-py3-none-any.whl
Size 19.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e4013073558375f94d9186710419d62c1c2b29dc03376cb2a6f79c83691b17b4
BLAKE2b-256 checksum
How to use checksums
96bbc354ea0589b7d2892cc8bbac1e4ec8cb9c4db97ddf69f864e3007121baa9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.10

Release history Release notifications | RSS feed

This release

0.3.2 This release

2 release files

0.3.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page