Giter Site home page Giter Site logo

tomchomiak / exiftool-vendored.js Goto Github PK

View Code? Open in Web Editor NEW

This project forked from photostructure/exiftool-vendored.js

0.0 2.0 0.0 2.97 MB

Fast, cross-platform Node.js access to ExifTool

Home Page: https://exiftool-vendored.js.org/

License: MIT License

JavaScript 0.44% TypeScript 99.56%

exiftool-vendored.js's Introduction

exiftool-vendored

Fast, cross-platform Node.js access to ExifTool.

npm version Build status Build status Maintainability

If links are broken, please read this on exiftool-vendored.js.org.

Features

  1. Best-of-class cross-platform performance and reliability.

    Expect an order of magnitude faster performance than other packages.

  2. Proper extraction of

  3. Support for

  4. Robust type definitions of the top 99.5% tags used by over 6,000 different camera makes and models (see an example)

  5. Auditable ExifTool source code (the vendored code is checksum verified)

  6. Automated updates to ExifTool (as new versions come out monthly)

  7. Robust test coverage, performed with the latest Node v6, v8, and v10 on Linux, Mac, & Windows.

Installation

 yarn add exiftool-vendored

or

 npm install --save exiftool-vendored

Note that exiftool-vendored provides an installation of ExifTool relevant for your local platform through optionalDependencies.

You shouldn't include either the exiftool-vendored.exe or exiftool-vendored.pl as direct dependencies to your project.

Upgrading

See the CHANGELOG for breaking changes since you last updated.

Usage

There are many configuration options to ExifTool, but all values have (more or less sensible) defaults.

Those defaults have been used to create the exiftool singleton. Feel free to review the ExifTool constructor parameters and override default values where appropriate if the defaults wont' work for you, but you should use your singleton to minimize system load. Note that if you don't use the default singleton, you don't need to .end() it.

// We're using the singleton here for convenience:
const exiftool = require("exiftool-vendored").exiftool

// And to verify everything is working:
exiftool
  .version()
  .then(version => console.log(`We're running ExifTool v${version}`))

General API

ExifTool.read() returns a Promise to a Tags instance. Note that errors may be returned either by rejecting the promise, or for less severe problems, via the errors field.

All other public ExifTool methods return Promise<void>, and will reject the promise if the operation is not successful.

Errors and Warnings

ExifTool has a pretty exhaustive set of error checking, and many "errors" are actually non-fatal warnings about invalid tag structures that seem to be regularly found in otherwise-not-corrupt images.

If we rejected every read or write when any error happened, this would prevent reading and/or writing to otherwise-ok files. To "demote" errors to be warnings that don't reject the underlying task, you can provide either a minorErrorsRegExp, or an implementation of rejectTaskOnStderr. Either of these parameters are provided to the ExifTool constructor.

Logging and events

To enable trace, debug, info, warning, or error logging from this library and the underlying batch-cluster library, usesetLogger. Example code can be found here.

ExifTool instances emits events for "startError", "taskError", "endError", "beforeEnd", and "end" that you can register listeners for, using on.

Reading tags

exiftool
  .read("path/to/image.jpg")
  .then((tags /*: Tags */) =>
    console.log(
      `Make: ${tags.Make}, Model: ${tags.Model}, Errors: ${tags.errors}`
    )
  )
  .catch(err => console.error("Something terrible happened: ", err))

Extracting embedded images

Extract the low-resolution thumbnail in path/to/image.jpg, write it to path/to/thumbnail.jpg, and return a Promise<void> that is fulfilled when the image is extracted:

exiftool.extractThumbnail("path/to/image.jpg", "path/to/thumbnail.jpg")

Extract the Preview image (only found in some images):

exiftool.extractPreview("path/to/image.jpg", "path/to/preview.jpg")

Extract the JpgFromRaw image (found in some RAW images):

exiftool.extractJpgFromRaw("path/to/image.cr2", "path/to/fromRaw.jpg")

Extract the binary value from "tagname" tag in path/to/image.jpg and write it to dest.bin (which cannot exist already and whose parent directory must already exist):

exiftool.extractBinaryTag("tagname", "path/to/file.exf", "path/to/dest.bin")

Writing tags

Note that only a portion of tags are writable. Refer to the documentation and look under the "Writable" column.

If you apply malformed values or ask to write to tags that aren't supported, the returned Promise will be rejected.

Only string and numeric primitive are supported as values to the object

Write a comment to the given file so it shows up in the Windows Explorer Properties panel:

exiftool.write("path/to/file.jpg", { XPComment: "this is a test comment" })

Change the DateTimeOriginal, CreateDate and ModifyDate tags (using the AllDates shortcut) to 4:56pm UTC on February 6, 2016:

exiftool.write("path/to/file.jpg", { AllDates: "2016-02-06T16:56:00" })

Always Beware: Timezones

If you edit a timestamp tag, realize that the difference between the changed timestamp tag and the GPS value is used by exiftool-vendored to infer the timezone.

In other words, if you only edit the CreateDate and don't edit the GPS timestamps, your timezone will either be incorrect or missing. See the section about Dates below for more information.

Rewriting tags

You may find that some of your images have corrupt metadata, and that writing new dates, or editing the rotation information, for example, fails. ExifTool can try to repair these images by rewriting all the metadata into a new file, along with the original image content. See the documentation for more details about this functionality.

rewriteAllTags returns a void Promise that will be rejected if there are any errors.

exiftool.rewriteAllTags("problematic.jpg", "rewritten.jpg")

Resource hygene

Remember to call .end().

ExifTool processes consume system resources. If you're done with it, turn it off with .end(), which returns a Promise<void> if you want to wait for the shutdown to be complete.

Mocha v4.0.0

If you use mocha v4 or later, and you don't call exiftool.end(), you will find that your test suite hangs. The relevant change is described here, and can be solved by adding an after block that shuts down the instance of ExifTool that your tests are using:

after(() => exiftool.end()) // assuming your singleton is called `exiftool`

Dates

Generally, EXIF tags encode dates and times with no timezone offset. Presumably the time is captured in local time, but this means parsing the same file in different parts of the world results in a different absolute timestamp for the same file.

Rather than returning a Date which always includes a timezone, this library returns classes that encode the date, the time of day, or both, with an optional tzoffset. It's up to you, then, to do what's right.

In many cases, though, a tzoffset can be determined, either by the composite TimeZone tag, or by looking at the difference between the local DateTimeOriginal and GPSDateTime tags. GPSDateTime is present in most smartphone images.

If a tzoffset can be determined, it is encoded in all related ExifDateTime tags for those files.

Note also that some smartphones record timestamps with microsecond precision (not just millis!), and both ExifDateTime and ExifTime have floating point milliseconds.

Tags

Official EXIF tag names are PascalCased, like AFPointSelected and ISO. ("Fixing" the field names to be camelCase, would result in ungainly aFPointSelected and iSO atrocities).

The Tags interface is autogenerated by the mktags script, which parses through over 6,000 unique camera make and model images, in large part sourced from the ExifTool site. mktags groups tags, extracts their type, popularity, and example values such that your IDE can autocomplete.

For an example of a group of tags, see the EXIFTags interface.

Tags marked with "★★★★", like MIMEType, should be found in most files. Of the several thousand metadata tags, realize less than 50 are found generally. You'll need to do your own research to determine which tags are valid for your uses.

Note that if parsing fails (for, example, a datetime string), the raw string will be returned. Consuming code should verify both existence and type as reasonable for safety.

Performance

The npm run mktags target reads all tags found in a batch of sample images and parses the results.

Using exiftool-vendored:

Read 2236 unique tags from 3011 files.
Parsing took 16191ms (5.4ms / file) # win32, core i7, maxProcs 4
Parsing took 27141ms (9.0ms / file) # ubuntu, core i3, maxProcs 1
Parsing took 12545ms (4.2ms / file) # ubuntu, core i3, maxProcs 4

Using the exiftool npm package takes 7x longer (and doesn't work on Windows):

Reading 3011 files...
Parsing took 85654ms (28.4ms / file) # ubuntu, core i3

Batch mode

Starting the perl version of ExifTool is expensive, and is especially expensive on the Windows version of ExifTool.

On Windows, for every invocation, exiftool installs a distribution of Perl and extracts the ~1000 files that make up ExifTool, and then runs the perl script. Windows virus scanners prevent reads on these files while they are scanned, which makes this approach even more costly.

Using ExifTool's -stay_open batch mode means we can reuse a single instance of ExifTool across many requests, dropping response latency dramatically as well as reducing system load.

Parallelism

To avoid overwhelming your system, the exiftool singleton is configured with a maxProcs set to a quarter the number of CPUs on the current system (minimally 1); no more than maxProcs instances of exiftool will be spawned. If the system is CPU constrained, however, you may want a smaller value. If you have very fast disk IO, you may see a speed increase with larger values of maxProcs, but note that each child process can consume 100 MB of RAM.

Author

Contributors 🎉

CHANGELOG

See the CHANGELOG on github.

exiftool-vendored.js's People

Contributors

mceachen avatar amokrushin avatar apolkingg8 avatar mesqueeb avatar

Watchers

James Cloos avatar Tom Chomiak avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.