GithubHelp home page GithubHelp logo

photostructure / exiftool-vendored.js Goto Github PK

View Code? Open in Web Editor NEW
396.0 6.0 34.0 35.64 MB

Fast, cross-platform Node.js access to ExifTool

Home Page: https://photostructure.github.io/exiftool-vendored.js/

License: MIT License

TypeScript 97.56% JavaScript 0.58% Perl 1.86%
exiftool cross-platform metadata metadata-extraction photos movies exif nodejs image images

exiftool-vendored.js's Introduction

exiftool-vendored

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

npm version Node.js CI GitHub issues Known Vulnerabilities

Features

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

    This is the module that PhotoStructure (and 500+ other projects) use for photo and video metadata reading and writing.

    Expect an order of magnitude faster performance than other Node.js ExifTool modules.

  2. Best-effort 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. Automated updates to ExifTool (as new versions come out frequently)

  6. Robust test coverage, performed with on macOS, Linux, and Windows

Installation

 yarn add exiftool-vendored

or

 npm install --save exiftool-vendored

Debug logging

If anything doesn't work, the first thing to try is enabling the logger.

You can provide a Logger implementation via ExifToolOptions.logger, or set the environment variable NODE_DEBUG=exiftool-vendored. See the debuglog() documentation for more details.

Regarding use within Electron

Due to how different every Electron application setup is, and how new versions frequently have breaking changes, do not ask for help by opening a github issue on this project.

Please seek help via StackOverflow, the Electron discord, or other channels.

Electron-builder support

Add the following pattern to electron-builder.yml's asarUnpack:

- "node_modules/exiftool-vendored.*/**/*"

The default exiftoolPath implementation will detect app.asar in your require path and replace it with app.asar.unpacked automatically.

Electron-forge support

Version 25.0 of this library added experimental support for electron-forge: add the following element to your ForgeConfig.packagerConfig.extraResource string array, and things should "just work" for the main process.

"./node_modules/exiftool-vendored." +
  (process.platform === "win32" ? "exe" : "pl")

If your main process forks any node subprocesses, process.resourcesPath will not be set in those subprocesses, and the default exiftoolPath won't work.

If this is your case, you must provide a correct implementation of ExifToolOptions.exiftoolPath, either by passing through resourcesPath via process.env, or some other method.

Installation notes

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

  • You shouldn't include either exiftool-vendored.exe or exiftool-vendored.pl as direct dependencies to your project, unless you know what you're doing.

  • If you're installing on a minimal Linux distribution, you may need to install perl. On Alpine, run apk add perl.

  • Node.js's -slim docker images don't include a working perl build. Use the non-slim image instead. See the issue report for details.

  • If the platform-correct vendor module (exiftool-vendored.exe or exiftool-vendored.pl) is not found, exiftool is searched for on your PATH. Note that very old versions of exiftool are found on currently-supported Linux distributions which this library will not work correctly with.

Upgrading

See the CHANGELOG for breaking changes since you last updated.

Major version bumps

I bump the major version if there's a chance existing code might be affected.

I've been bit too many times by my code breaking when I pull in minor or patch upgrades with other libraries. I think it's better to be pessimistic in code change impact analysis: "over-promise and under-deliver" your breaking-code changes.

When you upgrade to a new major version, please take a bit more care in validating your own systems, but don't be surprised when everything still works.

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. 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}`))

If the default ExifTool constructor parameters wont' work for you, it's just a class that takes an options hash:

const ExifTool = require("exiftool-vendored").ExifTool
const exiftool = new ExifTool({ taskTimeoutMillis: 5000 })

You should only use the exported default exiftool singleton, or only create one instance of ExifTool as a singleton.

Remember to .end() whichever singleton you use.

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.

Tags types

ExifTool knows how to extract several thousand different tag fields.

Unfortunately, TypeScript crashes with error TS2590: Expression produces a union type that is too complex to represent if the Tags interface was comprehensive.

Instead, we build a corpus of "commonly seen" tags from over 10,000 different digital camera makes and models, many from the ExifTool metadata repository and <raw.pixls.us>.

Here are some example fields:

  /** ★☆☆☆ ✔ Example: 200 */
  ISO?: number

  /** ★★★★ ✔ Example: 1920 */
  ImageHeight?: number

  /** ★★★★ ✔ Example: 1080 */
  ImageWidth?: number

  /** ★★★★ ✔ Example: "image/jpeg" */
  MIMEType?: string

The stars represent how common that field has a value in the example corpus. ★★★★ fields are found in > 50% of the examples. ☆☆☆☆ fields are found in < 1% of examples.

The checkmark denotes if the field is found in "popular" cameras (like recent Nikon, Canon, Sony, and Apple devices).

Caveats with Tags

The fields in Tags are not comprehensive.

Just because a field is missing from the Tags interface does not mean the field doesn't exist in the returned object. This library doesn't exclude unknown fields, in other words. It's up to you and your code to look for other fields you expect and cast to a more relevant interface.

Logging and events

To enable trace, debug, info, warning, or error logging from this library and the underlying batch-cluster library, provide a Logger instance to the ExifTool constructor options.

ExifTool instances emits many lifecycle and error events via batch-cluster.

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 is 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 primitives are supported as values to the object.

To 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" })

To 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" })

To write to a specific metadata group's tag, just prefix the tag name with the group. (TypeScript users: you'll need to cast to make this compile).

exiftool.write("path/to/file.jpg", {
  "IPTC:CopyrightNotice": "© 2021 PhotoStructure, Inc.",
})

To delete a tag, use null as the value.

exiftool.write("path/to/file.jpg", { UserComment: null })

The above example removes any value associated with the UserComment tag.

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")

ExifTool configuration support (.ExifTool_config)

ExifTool has an extensive user configuration system. There are several ways to use one:

  1. Place your user configuration file in your HOME directory
  2. Set the EXIFTOOL_HOME environment variable to the fully-qualified path that contains your user configuration.
  3. Specify the in the ExifTool constructor options:
new ExifTool({ exiftoolEnv: { EXIFTOOL_HOME: resolve("path", "to", "config", "dir") }

Resource hygiene

Call ExifTool.end() when you're done

You must explicitly call .end() on any used instance of ExifTool to allow node to exit gracefully.

ExifTool child processes consume system resources, and prevents node from exiting due to the way Node.js streams work.

Note that you can't call cannot be in a process.on("exit") hook, as the stdio streams attached to the child process cannot be unref'ed. (If there's a solution to this, please post to the above issue!)

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

The date metadata in all your images and videos are, most likely, underspecified.

Images and videos rarely specify a time zone in their dates. If all your files were captured in your current time zone, defaulting to the local time zone is a safe assumption, but if you have files that were captured in different parts of the world, this assumption will not be correct. Parsing the same file in different parts of the world result in different times for the same file.

Prior to version 7, heuristic 1 and 3 were applied.

As of version 7.0.0, exiftool-vendored uses the following heuristics. The highest-priority heuristic to return a value will be used as the timezone offset for all datetime tags that don't already have a specified timezone.

Heuristic 1: explicit metadata

If the EXIF TimeZoneOffset tag is present it will be applied as per the spec to DateTimeOriginal, and if there are two values, the ModifyDate tag as well. OffsetTime, OffsetTimeOriginal, and OffsetTimeDigitized are also respected, if present (but are very rarely set).

Heuristic 2: GPS location

If GPS latitude and longitude is present and valid (the value of 0, 0 is considered invalid), the tz-lookup library will be used to determine the time zone name for that location.

Heuristic 3: UTC timestamps

If GPSDateTime or DateTimeUTC is present, the delta with the dates found within the file, as long as the delta is valid, is used as the timezone offset. Deltas of > 14 hours are considered invalid.

ExifDate and ExifDateTime

Because date-times have this optionally-set timezone, and some tags only specify the date, this library returns classes that encode the date, the time of day, or both, with an optional timezone and an optional tzoffset: ExifDateTime and ExifTime. It's up to you, then, to determine what's correct for your situation.

Note also that some smartphones record timestamps with microsecond precision (not just milliseconds!), 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 auto-generated 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.

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 research to determine which tags are valid for your uses.

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

Serialization

The Tags object returned by .readTags() can be serialized to JSON with JSON.stringify.

To reconstitute, use the parseJSON() method.

import { exiftool, parseJSON } from "exiftool-vendored"

const tags: Tags = await exiftool.readTags("/path/to/file.jpg")
const str: string = JSON.stringify(tags)

// parseJSON doesn't validate the input, so we don't assert that it's a Tags
// instance, but you can cast it (unsafely...)

const tags2: Tags = parseJSON(str) as Tags

Performance

The default exiftool singleton is intentionally throttled. If full system utilization is acceptable:

  1. set maxProcs higher

  2. consider setting minDelayBetweenSpawnMillis to 0

  3. On a performant linux box, a smaller value of streamFlushMillis may work as well: if you see noTaskData events, you need to bump the value up.

Benchmarking

The yarn mktags ../path/to/examples target reads all tags found in a directory hierarchy of sample images and videos, and parses the results.

exiftool-vendored v16.0.0 on a 2019 AMD Ryzen 3900X running Ubuntu 20.04 on an SSD can process 20+ files per second per thread, or 500+ files per second when utilizing all CPU threads.

Batch mode

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

alextran1502 avatar amokrushin avatar apolkingg8 avatar atlas48 avatar circuit8 avatar davidmz avatar dependabot[bot] avatar mceachen avatar mesqueeb avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

exiftool-vendored.js's Issues

Support writing metadata to existing files

I was able to read the EXIF data successfully!
I am still a bit confused how to overwrite.

  1. Could you add an example to the docs how to e.g. change the exif orientation of a file?
  2. And if you have some spare time, a second example in the docs with the best/easiest way how to set a photo's date-taken to a different date, that would also be much appreciated.

Thank you very much!

This is what I have for the read part:

fs.readdir(dir, function (err, files) {
    files.forEach(function (file) {
    	exiftool
	    .read(dir+'/'+file)
	    .then((tags /*: Tags */) => {
            console.log(`【${file}】Orientation: ${tags.Orientation}`);
    });
});

Upgrade to exiftool v11.21

Hey Matthew short request, any chance of a version bump to the latest version of exiftool v11.21? I would make a PR myself but taking a look at the .exe and perl versions of your library I had no idea about how to go about adding the new version of exiftool to that, a little bit above my paygrade.

All the best,
Josh

Error: spawn /var/task/node_modules/exiftool-vendored.pl/bin/exiftool ENOENT

exiftool can not be spawned in aws lambda environment, getting below error stack:

2019-07-18T14:45:17.836Z	288aa49b-491d-5394-a451-f131c125cf30	Error: spawn /var/task/node_modules/exiftool-vendored.pl/bin/exiftool ENOENT
at _errnoException (util.js:1022:11)
at Process.ChildProcess._handle.onexit (internal/child_process.js:190:19)
at onErrorNT (internal/child_process.js:372:16)
at _combinedTickCallback (internal/process/next_tick.js:138:11)
at process._tickDomainCallback (internal/process/next_tick.js:218:9)

Using lambci/lambda:nodejs8.10 image (https://github.com/lambci/docker-lambda) the problem can be reproduced.
The error happens when initializing the below Metadata class

export default class Metadata {

    private static tool: ExifTool = Metadata.initTool();

    public static tmpDirectory = `${tmpdir()}/metadata`;

    private static initTool(): ExifTool {
        logger.debug("initializing exiftool...");
        const tool = new ExifTool();
        tool.version().then(version => logger.info(`ExifTool version ${version}`));
        return tool;
    }

Thanks for the great tool

FileModifyDate doesn't match exiftool's File Modification Date/Time

Note, this is on MacOS using exiftool v10.25

Exiftool's 'File Modification Date/Time' field appears to be the file's mtime or birthtime (inspected via lstat) - which is what I am expecting.

This exiftool package is returning what looks like atime or ctime for FileModifyDate.

Regardless of where it is derived, should these fields match?

EDIT: this was actually my issue - MacOS was preserving the birthtime when moved, but unix mv modifies it.

What is the correct way to use exiftool-vendored with Parallelism

The Question:

In the case of modifying 10,000+ photos: Do I have to manually create a throttling process to only process 1 photo with exiftool.write at the time and await each promise? Or does exiftool-vendored have auto queueing during exiftool.write on a large amount of photos?

The background & reason I can't use the Pearl CLI:

Since exiftool-vendored has maxprocs to help the CPU from being overloaded with Parallelism, I'm wondering how to correctly use exiftool-vendored.

I have a complicated process (where I need to look at about 500 folders in order, check the date of the first photo of the previous folder and apply changes depending on if this date is the same as the first photo of the next folder.)

Also, since I am only a NodeJS and JavaScript developer I was hoping to use this library instead of the pearl CLI.

In my case I am planning to write a script that does these things synchronously:

  1. do some date checking on relative sibling folders
  2. make async modifications (with exiftool.write) to photos in the target folder (depending on the result of the checking in prev step)
  3. await all these changes and go on to the next folder after

I don't anticipate a work overload since each folder doesn't have that many photos.

However, when there is a folder with a very large amount of photos to be modified in the above step 2, and my CPU is pushed to the max limit of the exiftool-vendored:

  • will it automatically start queueing the async exiftool.write calls I made and wait until the CPU has regained some breathing space?
  • Or will I have to manually also create a throttling process to only process 1 photo with exiftool.write at the time and await each modification?

Issue running tests with electron and mocha

Hey there,
Thanks again for your great work with this library.

Just having an issue with getting karma + mocha unit tests to run when I include Exiftool in a file.
I get the following error which I can't seem to figure out the cause of:

Electron 2.0.6 (Node 8.9.3) ERROR
  Uncaught Error: Cannot find module "."
  at webpack:///node_modules/exiftool-vendored/dist/ExifTool.js:30:0 <- index.js:14977

I have isolated the error in this github repository. Run yarn followed by yarn run unit to recreate the error.

Cheers

How to exclude or include specific tags while reading metadata

Here is code snippet to create an instance of exif tool. From this command, am expecting only format tag should be returned from the response. However, am getting all tags.

var exiftool_vendored = require("exiftool-vendored")
//const exifTool = new exiftool_vendored.ExifTool()
const exifTool = new exiftool_vendored.ExifTool({ exiftoolArgs: ["-stay_open", "True","-format","-@", "-"] });
console.log(exifTool.options)

However, am getting the response using Exiftool command:
Exiftool -stay_open True -format INDD file path
Response:
Format : application/x-indesign

I would like fetch only below metadata fields to avoid performance issues. I have tried passing only "format" attribute but that didn't work. can you let me know how to exclude or include specific tags?

var includeTags = ['subject',
'document_id',
'original_document_id',
'derived_from_document_id',
'derived_from_original_document_id',
'image*',
'format',
'thumbnail*',
'icc_profile_name',
'color*',
'file_size',
'file_type',
'creator*',
'drm*',
'x_resolution',
'y_resolution',
'file_type_extension',
'file_name']

Not fully compatible with yarn package manager

yarn add exiftool-vendored
node index.js
OK
yarn add anything-else
node index.js
Error: Cannot find module 'exiftool-vendored.pl'
    at Function.Module._resolveFilename (module.js:470:15)
    at Function.Module._load (module.js:418:25)
    at Module.require (module.js:498:17)
    at require (internal/module.js:20:19)
    at Object.<anonymous> (/srv/nodejs/test-exiftool/node_modules/exiftool-vendored/dist/ExifTool.js:17:20)
    at Module._compile (module.js:571:32)
    at Object.Module._extensions..js (module.js:580:10)
    at Module.load (module.js:488:32)
    at tryModuleLoad (module.js:447:12)
    at Function.Module._load (module.js:439:3)

index.js includes only import of exiftool-vendored module

Works ok only on clean install or if exiftool-vendored.pl explicitly added as a package dependency.

This does not cause much inconvenience in a case of exiftool-vendored is a direct dependency. But it is not so if there are intermediate dependencies.
For example module-a -> module-b -> exiftool-vendored. Whenever a module-a adds a new dependency, mobule-b will throw an error.

concerning -stay_open

Dear @mceachen

I'm really sorry to make another post, and I don't try to make you do free work for me.
In fact, if you have a paypal account or a bitcoin address, I'd be happy to tip you!!

You see, I'm having a problem understanding how to use -stay_open.
I read the official documentation about -stay_open but I'm afraid, it's really difficult to understand...

I have about 10,000 image paths that I want to edit with exiftool. I'm doing it like so:

imgPaths.forEach(imgPath => {
  // get the date from a json file
  let parentFolder = imgPath.split('/')[imgPath.split('/').length-2]
  let comment = folderInfo['keywords']
  let date = folderInfo['date']+' 12:00:00.000+01:00'
  // do the exiftool write
  exiftool
  .write(imgPath, {
    'MDItemFSCreationDate': date,
    'AllDates': date,
  })
  .then(suc => success(suc)).catch(err => catchErr(err))

But every time it hangs around 3000 images, so I think the memory is up. It's so bad I have to restart the computer after...

Do you have any advice on how to add -stay_open to this? I tried it as a third argument to the write function, but it didn't work.

Feel free to delete this thread if you want. I don't want to trouble you too much...
I'm so sorry, I don't know who else to ask.

Can't get this working with Electron Builder

Hello there @mceachen,

Excellent package, thanks a lot. I need to get this working with a multi-platform Electron Builder build, and am having no luck so far.

You mentioned in a previous issue that you had managed to get this working using a few tricks:

It took me a while to get the right combination of electron packaging (I am using electron-builder ), webpack config, asar exclusions, and __dirname workarounds to make everything work cross-platform.

Would you mind sharing exactly what you did?

Thanks again.

Request for a "repair" function

Extracted from #23

Tracks implementation of

/**
 * Attempt to fix metadata problems in JPEG images by deleting all metadata and rebuilding from 
 * scratch. After repairing an image you should be able to write to it without errors, but some 
 * metadata from the original image may be lost in the process.
 * 
 * This should only be applied as a last resort to images whose metadata is not readable via 
 * {@link .read()}.
 *
 * @param {string} inputFile the path to the problematic image
 * @param {string} outputFile the path to write the repaired image
 * @param {boolean} allowMakerNoteRepair if there are problems with MakerNote tags, allow
 * ExifTool to apply heuristics to recover corrupt tags. See exiftool's `-F` flag.
 * @return {Promise<void>} resolved when outputFile has been written. 
 */
rewriteAllTags(inputFile: string, outputFile: string, allowMakerNoteRepair: boolean = false)

[request] elaboration on `Timezones` documentation

From your docs:

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.

Is it possible to elaborate on which GPS timestamps we need to edit?

The reason being: I have a bunch of scanned photos I'm adding the date taken to manually.
At first I thought of just writing the dates as mentioned: exiftool.write("path/to/file.jpg", { AllDates: "2016-02-06T16:56:00" });
But after reading this I got a bit scared that wouldn't be enough.

[request] edit `MDItemFSCreationDate` tag example

Would it be possible to add an example how to edit the macOS "file creation date" ?
This is a special tag called MDItemFSCreationDate which needs a special option before it can be accessed through exiftool.

From the exiftool docs:

MDItem tags are extracted using the "mdls" utility. They are extracted if any "MDItem*" tag or the MacOS group is specifically requested, or by setting the MDItemTags API option to 1 or the RequestAll API option to 2 or higher.

e.g. -tagsfromfile @ -MDItemFSCreationDate

Node v4 support

I've noticed that there's a branch named node4 but it doesn't seems to work throwing the following error :

path/node_modules/exiftool-vendored/dist/exiftool.js:24
    constructor(maxProcs = 1) {
                         ^
SyntaxError: Unexpected token =
    at exports.runInThisContext (vm.js:53:16)
    at Module._compile (module.js:373:25)
    at Object.Module._extensions..js (module.js:416:10)
    at Module.load (module.js:343:32)
    at Function.Module._load (module.js:300:12)
    at Module.require (module.js:353:17)
    at require (internal/module.js:12:17)
    at Object.<anonymous> (/Users/claudiopetrini/Desktop/test/index-exiftools.js:1:80)
    at Module._compile (module.js:409:26)
    at Object.Module._extensions..js (module.js:416:10)

In the package.json the supported engine is still "node": ">= 6.4.0", is it just an old branch or is there a plan to support Node v4?

I just wanted to say...

... that i love You. You save my day.

Thank You for that module, i will try to help if will be able to.

You can remove this comment if You want.

exiftool fs and child_process not found.

I have installed laravel-mix to have a simple webpack wrapper.
I have added this script in package.json: "dev": "node node_modules/cross-env/dist/bin/cross-env.js NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",

When I try to run npm run dev, the only thing it should do is compile my JS file to include the top two lines of my js file:

let fs = require('fs');
import { exiftool } from "exiftool-vendored";

But I get the following error:

 Failed to compile with 3 errors

These dependencies were not found:

* fs in ./dev/run.js, ./~/exiftool-vendored/dist/exiftool_process.js
* child_process in ./~/exiftool-vendored/dist/exiftool_process.js

To install them, you can run: npm install --save fs child_process

Support for a "raw" result reading of exiftool output

Is your feature request related to a problem? Please describe.
I'm looking to extract the EXIF tags from a number of images and write the tags for each image into a separate XML file.

Describe the solution you'd like
A separate API like exiftool.readRaw(path[, options]) that allows for flags like -X to return just the RAW (or in this case, XML) output as a string/Buffer that could then be interacted with.

Describe alternatives you've considered

  1. Manually converting the Tags object to XML and writing that to a file, which has the downside of
    a. Overhead of exiftool-vendored.js parsing the JSON output, and
    b. Re-converting the Tags to XML and attempting to match the same structure exiftool.pl has
  2. Using a different NPM module, though I like the exiftool-vendored.js performance and handling of processes.
  3. Using exiftool.pl directly, either through exiftool-vendored.pl or a direct install, though I'd like to avoid re-inventing this module, and for the same reasons as above.

Miss sample DefaultExifToolOptions

Hi Thanks for your great Job

can you share me, how to using DefaultExifToolOptions ?

e.g to update taskTimeoutMillis: 2000 -> taskTimeoutMillis: 5000

thanks

Can't write to list tags

Hi there,

I can't seem to be able to write to list tags. See https://www.sno.phy.queensu.ca/~phil/exiftool/faq.html#Q17

When I do something along the lines of

exiftool.write({ SupplementalCategories: [1,2,3] })

The resultant metadata is

<photoshop:SupplementalCategories>
   <rdf:Bag>
    <rdf:li>1,2,3</rdf:li>
   </rdf:Bag>
  </photoshop:SupplementalCategories>
 </rdf:Description>

wheras it should be:

<photoshop:SupplementalCategories>
   <rdf:Bag>
    <rdf:li>1</rdf:li>
    <rdf:li>2</rdf:li>
    <rdf:li>3</rdf:li>
   </rdf:Bag>
  </photoshop:SupplementalCategories>
 </rdf:Description>

Exiftool automatically concatenates the list version from above and thus reports on both the same as follows:

Supplemental Categories  :  1,2,3

Thanks for your help.

Missing rejection from `.read()`

Hi there 🙂

First I'd like to thanks @mceachen & contributors of this lib which is great 👍

Then today I experienced a weird problem, here is the context :

  • I created a script that correct exif dates of my photos
  • It read with exiftool.read(filepath) .then(tags => ...)
  • And write new date like in documentation exiftool.write(filepath, { AllDates: newDateStr })

This script worked on multiple files before failing on a particular file.

The first problem here is that all my code is wrapped with catch and no error popped out, it just stops code execution after exiftool.write and never come into the then or catch

I managed to find the problem by using ExifTool via command line: Error reading ThumbnailImage data

So this is the error that should have appeared before and wasn't thrown.

Then I managed to found on the ExifTool author faq http://owl.phy.queensu.ca/~phil/exiftool/faq.html#Q20 that you can repair file exif with :
exiftool -all= -tagsfromfile @ -all:all -unsafe -icc_profile bad-file.jpg

So I would suggest implementing this repair ability as a method of this lib or as an option when writing :)

What do you think?

Process exiting on errors in ExifTool

Describe the bug

When I try to write tags to a non-existing file, the promise returned by exiftool.write
does not get rejected. Instead, the whole process seems to be killed.

To Reproduce

The following code tries to write a tag to a file abc.jpg that we assume not to exist.

const Exiftool = require("exiftool-vendored").ExifTool;
const exiftool = new Exiftool({});

(async () => {
  try {
    console.log("WRITING");
    await exiftool
      .write("abc.jpg", { AllDates: "2003-03-03-03-03-03" })
    console.log("DONE");
  } catch (err) {
    console.error("ERROR:", err);
  } finally {
    console.log("FINALLY");
  }
})();

Expected behavior

The promise returned by exiftool.write should be rejected, because the file abc.jpg does not exist.
The output should be

WRITING
ERROR: <something about the missing file>
FINALLY

The actual output is:

WRITING

which indicates that neither the catch-block, nor the line after the .write(), nor the finally block are executed.

Environment (please complete the following information):

  • Ubuntu 16.04.5 LTS
  • Node.JS version 8.12.0 and 10.11.0

moment().format() give one month later

with

ExifDateTime {
  year: 1907,
  month: 1,
  day: 1,
  hour: 0,
  minute: 0,
  second: 0,
  millisecond: 0,
  tzoffsetMinutes: 0,
  rawValue: '1907:01:01 00:00:00+00:00' }

code:

console.log (meta.DateTimeCreated) //result : 1907-01-01T00:00:00.000Z ok
console.log (meta.DateTimeCreated.toString()) //result : 1907-01-01T00:00:00.000Z ok
console.log (moment(meta.DateTimeCreated).format('DD/MM/YYYY HH:mm:ss')) //result : 01/02/1907 00:00:00 not ok

really strange!!

How to write \n (newline) to a tag value?

exiftool.write('path/to/image.jpg', {'Copyright': 'Agent Smith\n1999'})

Fails with a message that the file named "1999" doesn't exist (Error: File not found - 1999). How can I use newlines in a tag? Any help appreciated :)

How to catch errors, or remove them ?

I actually get an error, coming from a corrupted jpeg .

The problem is, I didn't find the way to catch the way to "catch" the error, and not display it to the console .

So, I get this error (on the console) :

BatchProcess(9328).onError() { source: 'stderr.data',
  task:
   '-AllDates=2018-08-14T12:26:58.000\n-overwrite_original\n-charset\nfilename=utf8\n-codedcharacterset=utf8\nC:\\Users\\thib3\\repos\\timer-correct\\photos\\test\\AFS2018-223.JPG\n-ignoreMinorErrors\n-execute\n',
  error:
   Error: stderr.data: Bad InteropIFD offset for InteropIndex - C:/Users/thib3/repos/timer-correct/photos/test/AFS2018-223.JPG
       at BatchProcess.<anonymous> (C:\Users\thib3\repos\timer-correct\node_modules\batch-cluster\dist\BatchProcess.js:312:25)
       at step (C:\Users\thib3\repos\timer-correct\node_modules\batch-cluster\dist\BatchProcess.js:32:23)
       at Object.next (C:\Users\thib3\repos\timer-correct\node_modules\batch-cluster\dist\BatchProcess.js:13:53)
       at C:\Users\thib3\repos\timer-correct\node_modules\batch-cluster\dist\BatchProcess.js:7:71
       at new Promise (<anonymous>)
       at __awaiter (C:\Users\thib3\repos\timer-correct\node_modules\batch-cluster\dist\BatchProcess.js:3:12)
       at BatchProcess.onError (C:\Users\thib3\repos\timer-correct\node_modules\batch-cluster\dist\BatchProcess.js:306:16)
       at Socket.<anonymous> (C:\Users\thib3\repos\timer-correct\node_modules\batch-cluster\dist\BatchProcess.js:81:26)
       at Socket.emit (events.js:182:13)
       at addChunk (_stream_readable.js:283:12) }
Task.reject() { cmd:
   '-AllDates=2018-08-14T12:26:58.000\n-overwrite_original\n-charset\nfilename=utf8\n-codedcharacterset=utf8\nC:\\Users\\thib3\\repos\\timer-correct\\photos\\test\\AFS2018-223.JPG\n-ignoreMinorErrors\n-execute\n',
  error:
   Bad InteropIFD offset for InteropIndex - C:/Users/thib3/repos/timer-correct/photos/test/AFS2018-223.JPG
       at Socket.<anonymous> (C:\Users\thib3\repos\timer-correct\node_modules\batch-cluster\dist\BatchProcess.js:81:49)
       at Socket.emit (events.js:182:13)
       at addChunk (_stream_readable.js:283:12)
       at readableAddChunk (_stream_readable.js:264:11)
       at Socket.Readable.push (_stream_readable.js:219:10)
       at Pipe.onread (net.js:635:20) }
file .\1532926361.jpg was corrected and moved to C:\Users\thib3\repos\timer-correct\photos\test\1532925761.jpg (3/4)
BatchProcess(12396).onError() { source: 'stderr.data',
  task:
   '-AllDates=2018-08-14T12:26:58.000\n-overwrite_original\n-charset\nfilename=utf8\n-codedcharacterset=utf8\nC:\\Users\\thib3\\repos\\timer-correct\\photos\\test\\AFS2018-223.JPG\n-ignoreMinorErrors\n-execute\n',
  error:
   Error: stderr.data: Bad InteropIFD offset for InteropIndex - C:/Users/thib3/repos/timer-correct/photos/test/AFS2018-223.JPG
       at BatchProcess.<anonymous> (C:\Users\thib3\repos\timer-correct\node_modules\batch-cluster\dist\BatchProcess.js:312:25)
       at step (C:\Users\thib3\repos\timer-correct\node_modules\batch-cluster\dist\BatchProcess.js:32:23)
       at Object.next (C:\Users\thib3\repos\timer-correct\node_modules\batch-cluster\dist\BatchProcess.js:13:53)
       at C:\Users\thib3\repos\timer-correct\node_modules\batch-cluster\dist\BatchProcess.js:7:71
       at new Promise (<anonymous>)
       at __awaiter (C:\Users\thib3\repos\timer-correct\node_modules\batch-cluster\dist\BatchProcess.js:3:12)
       at BatchProcess.onError (C:\Users\thib3\repos\timer-correct\node_modules\batch-cluster\dist\BatchProcess.js:306:16)
       at Socket.<anonymous> (C:\Users\thib3\repos\timer-correct\node_modules\batch-cluster\dist\BatchProcess.js:81:26)
       at Socket.emit (events.js:182:13)
       at addChunk (_stream_readable.js:283:12) }
Task.reject() { cmd:
   '-AllDates=2018-08-14T12:26:58.000\n-overwrite_original\n-charset\nfilename=utf8\n-codedcharacterset=utf8\nC:\\Users\\thib3\\repos\\timer-correct\\photos\\test\\AFS2018-223.JPG\n-ignoreMinorErrors\n-execute\n',
  error:
   Bad InteropIFD offset for InteropIndex - C:/Users/thib3/repos/timer-correct/photos/test/AFS2018-223.JPG
       at Socket.<anonymous> (C:\Users\thib3\repos\timer-correct\node_modules\batch-cluster\dist\BatchProcess.js:81:49)
       at Socket.emit (events.js:182:13)
       at addChunk (_stream_readable.js:283:12)
       at readableAddChunk (_stream_readable.js:264:11)
       at Socket.Readable.push (_stream_readable.js:219:10)
       at Pipe.onread (net.js:635:20) }

I tried some options :

let currExiftool = new ExifTool(Object.assign(exiftool.options, {
    exiftoolArgs      : ["overwrite_original"],
    minorErrorsRegExp: /InteropIFD/gi //this doesn't resolve the problem
}));
//this debugger is not called, so I think it's not called
currExiftool.rejectTaskOnStderr = () => {debugger; return true};
await currExiftool.write(file, {AllDates: DateTimeOriginal.toString()}, ["-overwrite_original"]).catch(err=>console.log("catched"));

Doesn't throw error, but log catched after the console.log .

So my question is :
How to get this error ? (not in the console), or how to hide this error please ?

Question about setting time with NPM exiftool.

Dear @mceachen ,
Can I use your NPM exiftool directly from the terminal in macOS?
How would select a folder on my computer and set the taken datetime for all photos inside to e.g. 1990-01-30?

It would be great if I could see a sample!

(I know it's originally a perl program, but I thought to try yours, because I only know javascript. I'm not sure if I should run it through my browser or in the command line, and how to target files on my computer though!)

-stay_open mode question

Are below essentially the same in terms of invocation? Essentially in both cases A. and B. exiftool-vendored is actually run in -stay_open mode and the only difference is ability to set custom args in A. with exiftoolArgs:

A.

const ExifTool = require('exiftool-vendored').ExifTool;
const exiftool = new ExifTool({exiftoolArgs: ['-stay_open', 'True', '-@', '-']}); 

(async () => {
   const meta = await exiftool.read('path/to/image.jpg');
   exiftool.end();
})();

B.

const exiftool = require('exiftool-vendored').exiftool

(async () => {
   const meta = await exiftool.read('path/to/image.jpg');
   exiftool.end();
})();

Or does -stay_open have to be explicitly set as per A.?

read args parm bug or clarification needed

Great contribution. Thank you!

AFAICT, should be able to scope query to return tags listed in read args array as shown in following example:

read('./image.jpg', ['-Model', '-Make', ...])

Is this unsupported, bug, or on me?

Thanks again,

-Roland.

Mention Perl dependency for Linux

I was using this in a Docker Alpine image and got this error:

throw er; // Unhandled 'error' event
^
Error: spawn /opt/bundle/bundle/programs/server/npm/node_modules/exiftool-vendored.pl/bin/exiftool ENOENT

The error was exiftool failing to start:

exiftool: /usr/bin/perl: bad interpreter: No such file or directory

Because Perl was missing. Alpine Linux aims to be as small as possible, and as such it doesn’t come with Perl installed. One needs to install it (apk add perl is all it takes).

This isn’t really particular to Alpine though, as anyone might happen to be in an environment that lacks Perl. You might want to mention in the README and/or the wiki that Perl is a dependency that won’t be installed by this package, that the user is responsible for ensuring is available in the environment. I see that the README mentions that Perl will be installed for Windows environments, but presumably that doesn’t happen for Linux.

Does't support -config option

When I run
exifTool.read(file, ['-config /path/to/exiftool.config', '-n'])`
get the error message: "Invalid TAG name: config"

weird issue where exiftool stops processing without error

I'm known to require a fairly complicated setup to organise my photo's, but I actually worked hard until I had a setup that's really straight forward and easy to reason about.

I just go through each folder synchronously and do each exiftool write also synchronously.
Meaning I await every single write.
Yet still my process gets cut off at around 30 folders (as seen in the screenshot below) but without any error!

Could you comment on my code how I should debug the exiftool.write, because I think I'm failing to log errors somewhere in the code.

First I wrapped exiftool.write into a writeDate function:

const { ExifTool } = require('exiftool-vendored')
const exiftool = new ExifTool()

export default function (path, date) {
  return new Promise((resolve, reject) => {
    exiftool
      .write(path, {
        'MDItemFSCreationDate': date,
        'AllDates': date
      })
      .then(resolve).catch(reject)
  })
}

Then I do my process:

const start = async () => {
  await asyncForEach(foldersByDate, async (date) => {
    console.log('=======', date, '========')
    const photoPaths = getFileList(ROOTPATH + '/' + date, true)
    await asyncForEach(photoPaths, async (photoPath) => {
      if (!photoPath.includes('.jpg')) return
      const photoName = photoPath.split('/').slice(-1)[0]
      const time = photoName.split(' ').slice(-1)[0].replace('.jpg', '').replace(/\./g, ':')
      await writeDate(photoPath, `${date}T${time}`).catch(console.error)
      // the catch.(console.error) should trigger on anything that goes wrong
    })
  })
  console.log('Finished!') // never reaches here
}
start()

Here down below you see the terminal console not showing any errors, but stopping mysteriously...

image

Any advice is much appreciated, and I'm sorry to always come to you for help!!!!

(PS, the asyncForEach function is inspired from this Medium post and works perfectly. The folders all have a few seconds in between them as they are logged in the console.)

Bug spawning new process with electron

Hi there,
First of all thanks for your work on exiftool-vendored, its a great library and a huge help to me!

So I'm using Electron and in development exiftool-vendored is working perfectly. However when I build for production and attempt to write to a file I'm getting the following errors in the console:

screenshot

I'm using exiftool-vendored version 4.18.1 and running on Ubuntu

Cheers

Support for streams/remote URLs

It would be really nice to be able to use a remote URLs instead of a local path so that nothing is persisted on the file system.

I'm not that into the source code, TypeScript and ExifTool to make a PR however.

Use without vendored

Is your feature request related to a problem? Please describe.

Ironically this library has the best JS wrapper API around Exiftool and I’d love to use it with pre-installed exiftool.

Describe the solution you'd like

The ability to install the library without also installing a vendored dependency of exiftool.

Additional context

I’m running this in Lambda and after attempting the solutions proposed in #53 with no luck I ended up creating my own Lambda layer. I can’t use this library now though because it expects exiftool-vendored.pl to be there.

Any way to get Node.js streams to work?

Having to manage and deal with temporary files all over the place (not to mention the *_original files) is kind of a pain. Being able to work with node streams directly would make this much easier.

For example, exiftool.read() could take a stream. Functions like extractPreview(filepath/inputstream) could take 1 argument (file or stream) and then process the output by either having .write(newfilepath) or .stream().pipe(outputstream). The gm package has a really nice way of handling this (https://github.com/aheckmann/gm)

Is there any way to work with streams currently or is it purely a feature that is not implemented yet? And if so, are there any plans to support streams in the future?

"Invalid unit tzoffsetMinutes" when using ExifDateTime.toDateTime()

I have a CreateDate that looks like this:

  CreateDate: 
   ExifDateTime {
     year: 2019,
     month: 3,
     day: 8,
     hour: 14,
     minute: 24,
     second: 54,
     millisecond: 0,
     tzoffsetMinutes: -480 }

When running toDateTime() on the ExifDateTime I am getting:

Error: Invalid unit tzoffsetMinutes
    at normalizeUnit (/Users/reinhard/Work/Open Source/dedupe-by-exif-date/node_modules/luxon/build/node/luxon.js:4954:26)
    at normalizeObject (/Users/reinhard/Work/Open Source/dedupe-by-exif-date/node_modules/luxon/build/node/luxon.js:264:18)
    at Function.fromObject (/Users/reinhard/Work/Open Source/dedupe-by-exif-date/node_modules/luxon/build/node/luxon.js:5273:24)
...

My goal was to convert the date to a timestamp via the DateTime instance. Here's my yarn.lock for any versions of things you might want to know: http://yo.bkwld.com/09c026aa1698.

Thanks!

Warn about timeout error in bigger images & better error handling session in readme

Is your feature request related to a problem? Please describe.
First of all, congratulations! I'm running this project on a migration script for my company and it's helping us to extract exifData from 300k+ images.

Problem: It's running on a aws batch script. It started to just stop, exiting with an 0 code and I though that it might be related to the cpu (I was only using 2 vcpus), memory and stuff related to machine limitation. Spent some time improving the script and running it on a docker container with limited resources to replicate the environment and nothing changed.
In the end, the problem was that the image was too big and would take more than 10 seconds to extract its exifData.

Describe the solution you'd like
Took a deeper dive on your readme today and saw the error handling session... I think it could have a code sample and some kind of highlight to warn the users to use it to get proper error logs. In my case, I had to throw the error on the node script so the aws batch could set it as failed instead of success. Also had to increase the timeout with the taskTimeoutMillis param.

I think this project should have some kind of warning to tell users that are dealing with bigger images that they probably would like to increase the task timeout. Also, warning them about the error logging and creating a code sample showing how to handle errors would be good.

I can open a PR if you guys are too busy.

Original Image Width/Height return undefined

Hi,

Thank you for this great tool.

Ran into this issue where running

exiftool ExifTool.jpg

gives 'Original Image Width/Height' to be 16. (ExifTool.jpg is a test image in the original exiftool distribution (Image-ExifTool-11.06.tar.gz) under t/images directory)

When running through exiftool-vendored getting 'undefined' for OriginalImageWidth/Height

Custom tags?

Hi, is there anything about adding custom tag definitions?

I have a set of custom XMP tags I use for catagorising images, is there a way to add their definitions so I can read them?

If so:

Could the documentation be updated to make this feature's use clearer if it's easy? and could you tell me how to do it?

If not:

I would like to see this feature implemented somehow. It might be a bit outside my wheelhouse, so I might not it myself.

Doc link broken

From Readme:

Feel free to review the ExifTool constructor parameters and override default values where appropriate if the defaults wont' work for you

The url to ExifTool constructor parameters is broken.

Writing ExifDateTime fails with an assertion error

Describe the bug
Writing ExifDateTime fails with an assertion error.

{ AssertionError [ERR_ASSERTION]: cannot encode {"year":2019,"month":1,"day":1,"hour":0,"minute":0,"second":0}
    at enc (...\node_modules\exiftool-vendored\dist\WriteTask.js:73:36)
...

To Reproduce

const exiftool = require("exiftool-vendored").exiftool;
const ExifDateTime = require("exiftool-vendored").ExifDateTime;

test().catch(e => { console.error(e); });

async function test() {
    try {
        await exiftool.write('test.jpg', {
            CreateDate: new ExifDateTime(2019, 1, 1, 0, 0, 0),
        });
    } finally {
        await exiftool.end();
    }
}

Environment (please complete the following information):
exiftool-vendored v8.12.0
node v10.10.0
Windows 10

Extract PreviewTIFF

At the moment depending on RAW file processed specific previews are available for extraction. Running exiftool -preview:all nikon_d850.nef we get 4x previous we can choose from:

Jpg From Raw -> exiftool.extractJpgFromRaw()                   
Other Image -> ?                    
Preview Image -> exiftool.extractPreview()                  
Thumbnail TIFF -> exiftool.extractThumbnail()                 

In some cases Preview is reported as PreviewTIFF and not as PreviewImage as per Hasselblad RAW file which seems to be impossible to extract via build in extractPreview() option but can be extracted directly with:

exiftool -PreviewTIFF -b B0000994.3FR > B0000994.JPG

It would be good to support this via extractPreview.

gps.toDate is not a function

Hello,

I am having trouble with the package. This is the issue I am getting when trying to read exif data:

TypeError: gps.toDate is not a function
    at TagsTask.extractTzoffset (E:\photos\node_modules\exiftool-vendored\dist\tags_task.js:64:41)
    at TagsTask.parseTags (E:\photos\node_modules\exiftool-vendored\dist\tags_task.js:72:14)
    at TagsTask.parse (E:\photos\node_modules\exiftool-vendored\dist\tags_task.js:46:21)
    at TagsTask.Task.onData (E:\photos\node_modules\exiftool-vendored\dist\task.js:26:31)
    at ExifToolProcess.onData (E:\photos\node_modules\exiftool-vendored\dist\exiftool_process.js:137:22)
    at Socket.<anonymous> (E:\photos\node_modules\exiftool-vendored\dist\exiftool_process.js:40:65)
    at emitOne (events.js:101:20)
    at Socket.emit (events.js:188:7)
    at readableAddChunk (_stream_readable.js:176:18)
    at Socket.Readable.push (_stream_readable.js:134:10)

I am on node 6.10.0.

Thanks a lot,
Christian

Cannot find module 'exiftool-vendored.pl' using exiftool with electron

Building an app with electron and react and keep getting this issue when using exiftool-vendored.

I have read the previous post on the matter and tried to add exiftool-vendored.pl to my dependencies manually and this only generates the following error

Capture

Also base issue
image

My package.json
{ "name": "photo-op", "version": "0.1.0", "private": true, "dependencies": { "@babel/register": "^7.4.0", "@material-ui/core": "^3.9.3", "@material-ui/icons": "^3.0.2", "exiftool-vendored": "^8.8.0", "react": "^16.8.6", "react-dom": "^16.8.6", "react-redux": "^7.0.2", "react-router": "^5.0.0", "react-router-dom": "^5.0.0", "react-scripts": "2.1.8", "recursive-readdir": "^2.2.2", "redux": "^4.0.1", "styled-components": "^4.2.0" }, "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject", "electron": "electron ./src/main.js" }, "eslintConfig": { "extends": "react-app" }, "browserslist": [ ">0.2%", "not dead", "not ie <= 11", "not op_mini all" ], "devDependencies": { "electron": "^4.1.4" } }

Strange chars in dist/ExifTool.d.ts

Hi, I found some strange chars in dist/ExifTool.d.ts:

/**
 * Use this singleton rather than instantiating new ExifTool instances in order
 * to leverage a single running ExifTool process. As of v3.0, its `maxProcs` is
 * set to the number of CPUs on the current system; no more than `maxProcs`
 * instances of `exiftool` will be spawned. You may want to experiment with
 * smaller or larger values for `maxProcs`, depending on CPU and disk speed of
 * your system and performance tradeoffs.
 *
 * Note that each child process consumes between 10 and 50 MB of RAM. If you
 * have limited system resources you may want to use a smaller `maxProcs` value.
 */
export declare const exiftool: ExifTool;
ol;  // <=This

I tried yarn cache clean and reinstall it, but it still exist.
The ol; seems like... I don't know, maybe your cat on keyboard 😆 ?

Error if IPTC ApplicationRecord Tags have a hyphen

MacOS 10.13.6 High Sierra

Reading IPTC tags from a .dng file and the hyphenated ones don't work
Code fragment -

     var reado = 
    `Make: ${tags.Make},
     Model: ${tags.Model}, 
     Sub-location: ${tags.Sub-location},
     City: ${tags.City},
     Province-State: ${tags.Province-State},
     Country-PrimaryLocationName: ${tags.Country-PrimaryLocationName},
     UserComment: ${tags.UserComment}`;

    console.log('READO ', reado);
    })
    .catch(err => console.error("Something terrible happened: ", err))

eg: typical error is -
Something terrible happened: ReferenceError: State is not defined at exiftool.read.then (app.js:730) etc

Sub-location - FAIL
City - OK
Province-State - FAIL
Country-PrimaryLocationName - FAIL

Cheers,
Blane

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.