A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://github.com/mceachen/exiftool-vendored below:

photostructure/exiftool-vendored.js: Fast, cross-platform Node.js access to ExifTool

Fast, cross-platform Node.js access to ExifTool. Built and supported by PhotoStructure.

Installation & Quick Start

Requirements: Node.js Active LTS or Maintenance LTS versions only

npm install exiftool-vendored
import { exiftool } from "exiftool-vendored";

// Read metadata
const tags = await exiftool.read("photo.jpg");
console.log(`Camera: ${tags.Make} ${tags.Model}`);
console.log(`Taken: ${tags.DateTimeOriginal}`);
console.log(`Size: ${tags.ImageWidth}x${tags.ImageHeight}`);

// Write metadata
await exiftool.write("photo.jpg", {
  XPComment: "Amazing sunset!",
  Copyright: "© 2024 Your Name",
});

// Extract thumbnail
await exiftool.extractThumbnail("photo.jpg", "thumb.jpg");

// The singleton instance automatically cleans up on process exit by default.
// If you need immediate cleanup or have disabled registerExitHandlers:
// await exiftool.end();

Order of magnitude faster than other Node.js ExifTool modules. Powers PhotoStructure and 1,000+ other projects.

const tags = await exiftool.read("photo.jpg");

// Camera info
console.log(tags.Make, tags.Model, tags.LensModel);

// Capture settings
console.log(tags.ISO, tags.FNumber, tags.ExposureTime);

// Location (if available)
console.log(tags.GPSLatitude, tags.GPSLongitude);

// Always check for parsing errors
if (tags.errors?.length > 0) {
  console.warn("Metadata warnings:", tags.errors);
}
// Add keywords and copyright
await exiftool.write("photo.jpg", {
  Keywords: ["sunset", "landscape"],
  Copyright: "© 2024 Photographer Name",
  "IPTC:CopyrightNotice": "© 2024 Photographer Name",
});

// Update all date fields at once
await exiftool.write("photo.jpg", {
  AllDates: "2024:03:15 14:30:00",
});

// Delete tags
await exiftool.write("photo.jpg", {
  UserComment: null,
});
// Extract thumbnail
await exiftool.extractThumbnail("photo.jpg", "thumbnail.jpg");

// Extract preview (larger than thumbnail)
await exiftool.extractPreview("photo.jpg", "preview.jpg");

// Extract JPEG from RAW files
await exiftool.extractJpgFromRaw("photo.cr2", "processed.jpg");

The Tags interface contains thousands of metadata fields from an auto-generated TypeScript file. Each tag includes semantic JSDoc annotations:

/**
 * @frequency 🔥 ★★★★ (85%)
 * @groups EXIF, MakerNotes
 * @example 100
 */
ISO?: number;

/**
 * @frequency 🧊 ★★★☆ (23%)
 * @groups MakerNotes
 * @example "Custom lens data"
 */
LensSpec?: string;

Important: The interface isn't comprehensive - unknown fields may still exist in returned objects.

📖 Complete Tags Documentation →

Images rarely specify timezones. This library uses sophisticated heuristics:

  1. Explicit metadata (TimeZoneOffset, OffsetTime)
  2. GPS location → timezone lookup
  3. UTC timestamps → calculate offset
const dt = tags.DateTimeOriginal;
if (dt instanceof ExifDateTime) {
  console.log("Timezone offset:", dt.tzoffset, "minutes");
  console.log("Timezone:", dt.zone);
}

📖 Date & Timezone Guide →

Always call .end() on ExifTool instances to prevent Node.js from hanging:

import { exiftool } from "exiftool-vendored";

// Use the singleton
const tags = await exiftool.read("photo.jpg");

// Clean up when done
process.on("beforeExit", () => exiftool.end());
Automatic Cleanup with Disposable Interfaces

For TypeScript 5.2+ projects, use automatic resource management:

import { ExifTool } from "exiftool-vendored";

// Automatic synchronous cleanup
{
  using et = new ExifTool();
  const tags = await et.read("photo.jpg");
  // ExifTool automatically cleaned up when block exits
}

// Automatic asynchronous cleanup (recommended)
{
  await using et = new ExifTool();
  const tags = await et.read("photo.jpg");
  // ExifTool gracefully cleaned up when block exits
}

Benefits:

The Tags interface shows the most common fields, but ExifTool can extract many more. Cast to access unlisted fields:

const tags = await exiftool.read("photo.jpg");
const customField = (tags as any).UncommonTag;

The default singleton is throttled for stability. For high-throughput processing:

import { ExifTool } from "exiftool-vendored";

const exiftool = new ExifTool({
  maxProcs: 8, // More concurrent processes
  minDelayBetweenSpawnMillis: 0, // Faster spawning
  streamFlushMillis: 10, // Faster streaming
});

// Process many files efficiently
const results = await Promise.all(filePaths.map((file) => exiftool.read(file)));

await exiftool.end();

Benchmarks: 20+ files/second/thread, 500+ files/second using all CPU cores.

Matthew McEachen, Joshua Harris, Anton Mokrushin, Luca Ban, Demiurga, David Randler


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4