exiftool-vendored
Version:
Efficient, cross-platform access to ExifTool
339 lines (338 loc) • 13.1 kB
TypeScript
import * as bc from "batch-cluster";
import { geoTz } from "./GeoTz";
import { Maybe } from "./Maybe";
import { Tags } from "./Tags";
/**
* Options for the {@link ExifTool} constructor.
*
* Defaults are defined in {@link DefaultExifToolOptions}.
*
* @see {@link Settings} for library-wide settings.
* @see {@link DefaultExifToolOptions} for default values.
*/
export interface ExifToolOptions extends bc.BatchClusterOptions, bc.BatchProcessOptions, bc.ChildProcessFactory {
/**
* The maximum number of ExifTool child processes to spawn when load merits.
*
* @default `Math.max(1, Math.floor(os.cpus().length / 4))`
*/
maxProcs: number;
/**
* The maximum number of requests a given ExifTool process will service
* before being retired.
*
* @default 500
*/
maxTasksPerProcess: number;
/**
* Spawning new ExifTool processes must not take longer than this before the
* child process is timed out and a new attempt is made. Be pessimistic
* here--windows can regularly take several seconds to spin up a process,
* thanks to antivirus shenanigans. This can't be set to a value less than
* 100ms.
*
* @default 30000 (30 seconds)
*/
spawnTimeoutMillis: number;
/**
* If requests to ExifTool take longer than this, presume the underlying
* process is dead and we should restart the task. This can't be set to a
* value less than 10ms, and really should be set to at more than a second
* unless `taskRetries` is sufficiently large or all writes will be to a
* fast local disk.
*
* @default 30000 (30 seconds)
*/
taskTimeoutMillis: number;
/**
* An interval timer is scheduled to do periodic maintenance of underlying
* child processes with this periodicity.
*
* @default 2000 (2 seconds)
*/
onIdleIntervalMillis: number;
/**
* The number of times a task can error or timeout and be retried.
*
* @default 1 (every task gets 2 chances)
*/
taskRetries: number;
/**
* Allows for non-standard paths to ExifTool.
*
* This must be the full path to `exiftool`, not just the directory.
*
* @default Path to vendored ExifTool binary
*/
exiftoolPath: string | Promise<string> | ((logger?: bc.Logger) => string | Promise<string>);
/**
* Args only passed to exiftool on launch. You probably don't need to change
* this from the default.
*
* @default `["-charset", "filename=utf8"]`
*/
exiftoolArgs: string[];
/**
* Environment variables passed to ExifTool (besides `EXIFTOOL_HOME`)
*
* @default `{}`
*/
exiftoolEnv: NodeJS.ProcessEnv;
/**
* Should ExifTool use MWG (Metadata Working Group) composite tags for
* reading and writing tags?
*
* ExifTool recommends this to be set to `true`. Note that this can result
* in many tag value differences from `ExifTool.read`, and makes
* `ExifTool.write` write to "synonymous" MWG tags automatically.
*
* @default true
* @see https://exiftool.org/TagNames/MWG.html for details
*/
useMWG: boolean;
/**
* Tag names (which can have '*' glob matchers) which you want numeric
* values, rather than ExifTool's "Print Conversion."
*
* If you're using tag values only for human consumption, you may want to
* leave this blank.
*
* @default `["*Duration*", "GPSAltitude", "GPSLatitude", "GPSLongitude", "GPSPosition", "GeolocationPosition", "Orientation"]`
*/
numericTags: string[];
/**
* If defined, ExifTool will attempt to calculate an "ImageDataHash" tag
* value with a checksum of image data.
*
* Note that as of 2022-04-12, ExifTool supports JPEG, TIFF, PNG, CRW, CR3,
* MRW, RAF, X3F, IIQ, JP2, JXL, HEIC and AVIF images, MOV/MP4 videos, and
* some RIFF-based files such as AVI, WAV and WEBP.
*
* @default false (disabled, as it adds ~20ms of overhead to every read)
*/
imageHashType: false | "MD5" | "SHA256" | "SHA512";
/**
* @deprecated Use `imageHashType` instead.
*/
includeImageDataMD5: boolean | undefined;
/**
* Video file dates are assumed to be in UTC, rather than using timezone
* inference used in images. To disable this default, set this to `false`.
*
* @default true
* @see https://github.com/photostructure/exiftool-vendored.js/issues/113
*/
defaultVideosToUTC: boolean;
/**
* Should we try to backfill timezones for date-times that don't have them?
* If set to `true`, and {@link defaultVideosToUTC} is also `true`, we'll
* try backfilling timezones for date-times that are UTC, as well.
*
* Setting this to `false` removes **all** timezone inference--only those
* date-times with an explicit offset will have a defined timezone.
*
* @default true
*/
backfillTimezones: boolean;
/**
* We always look at {@link Tags.TimeZone}, {@link Tags.OffsetTime},
* {@link Tags.TimeZoneOffset}, {@link Tags.OffsetTimeOriginal},
* {@link Tags.OffsetTimeDigitized}, and GPS metadata to infer the timezone.
*
* If these strategies fail, and this is enabled, we'll try to infer the
* timezone from non-UTC datestamps included in the
* {@link inferTimezoneFromDatestampTags} value.
*
* @default false (fewer "fuzzy" heuristics are enabled by default)
*/
inferTimezoneFromDatestamps: boolean;
/**
* This is the list of tag names that will be used to infer the timezone as
* a backstop, if no explicit timezone is found in metadata. Note that
* datestamps with UTC offsets are ignored, as they are frequently
* incorrectly set.
*
* This setting is only in play if {@link inferTimezoneFromDatestamps} has
* been overridden to be `true`.
*
* @default {@link CapturedAtTagNames}
*/
inferTimezoneFromDatestampTags: (keyof Tags)[];
/**
* Some cameras (Samsung Galaxy S7, for example) may not always include GPS
* metadata in photos if a fix can't be obtained. If this option is `true`,
* and GPS metadata is missing, we'll try to infer the timezone from the
* difference of the TimeStamp tag and the first defined tag value from
* {@link inferTimezoneFromDatestampTags}.
*
* This heuristic is pretty sketchy, and used as a last resort. You shouldn't
* enable it unless you have to.
*
* @default false
* @see https://github.com/photostructure/exiftool-vendored.js/issues/209
*/
inferTimezoneFromTimeStamp: boolean;
/**
* Some software uses a GPS position of (0,0) as a synonym for "unset". If
* this option is `true`, and GPSLatitude and GPSLongitude are both 0, then
* those values will be returned, but the TZ will not be inferred from that
* location.
*
* If both this and {@link geolocation} are `true`, we will _delete_ the
* Geolocation tags from the returned metadata object.
*
* @default true
* @see https://en.wikipedia.org/wiki/Null_Island
*/
ignoreZeroZeroLatLon: boolean;
/**
* Override the default geo-to-timezone lookup service. Note that if
* {@link geolocation} is enabled, we'll use {@link Tags.GeolocationTimeZone}
* if it's not blank.
*
* If your implementation throws an error, `ExifTool` will consider that
* given latitude/longitude as invalid.
*
* @default `@photostructure/tz-lookup` (consider `geo-tz` for more accuracy)
*
* @example
* ```js
* const geotz = require("geo-tz")
* const { ExifTool } = require("exiftool-vendored")
* const exiftool = new ExifTool({ geoTz: (lat, lon) => geotz.find(lat, lon)[0] })
* ```
*
* @see https://github.com/photostructure/tz-lookup
* @see https://github.com/evansiroky/node-geo-tz/
*/
geoTz: typeof geoTz;
/**
* When reading metadata, should we enable ExifTool's geolocation features?
* Note that this requires ExifTool version 12.78 or later.
*
* @default false
* @see https://exiftool.org/geolocation.html
* @see {@link GeolocationTags}
*/
geolocation: boolean;
/**
* Should we ignore minor errors when reading metadata?
*
* @default true (ExifTool can be quite chatty)
*/
ignoreMinorErrors: boolean;
/**
* When writing an extracted tag to a file, this will overwrite an existing
* file instead of throwing an error. Enabling this option is equivalent to
* `-w!` in ExifTool.
*
* @default false
*/
forceWrite: boolean;
/**
* `ExifTool` has a shebang line that assumes a valid `perl` is installed at
* `/usr/bin/perl`.
*
* Some environments may not include a valid `/usr/bin/perl` (like AWS
* Lambda), but `perl` may be available in your `PATH` some place else (like
* `/opt/bin/perl`), if you pull in a perl layer.
*
* Note that when enabled, `perl` will be spawned in a sub-shell.
*
* @default `true` on systems without `/usr/bin/perl`, `false` otherwise
*/
ignoreShebang: boolean;
/**
* Should we check for a readable and executable `perl` file in $PATH? Set
* this to `false` if you know perl is installed.
*
* @default `false` on Windows, `true` elsewhere
*/
checkPerl: boolean;
/**
* How should ExifTool handle nested structures?
*
* - `0` = Read/copy flattened tags
* - `1` = Read/copy structures
* - `2` = Read/copy both flattened and structured tags, but flag flattened
* tags as "unsafe" for copying
* - `"undef"` = Same as `0` for reading and `2` for copying
*
* @default 1
* @see https://exiftool.org/struct.html
*/
struct: "undef" | 0 | 1 | 2;
/**
* Any additional arguments that should be added by default to all read
* tasks, like `["-fast", "-api", "largefilesupport=1"]`. The value provided
* to the ExifTool constructor can be overridden in the call to
* {@link ExifTool.read}.
*
* @default `["-fast"]`
*/
readArgs: string[];
/**
* Any additional arguments that should be added by default to all write
* tasks, like `["-overwrite_original"]`. The value provided to the ExifTool
* constructor can be overridden in the call to {@link ExifTool.write}.
*
* @default `[]`
*/
writeArgs: string[];
/**
* The TimeZone tag normally represents the offset from UTC.
*
* Unfortunately, at least for some Nikon cameras, the TimeZone tag **and the
* DaylightSavings tag** must be taken into account to find the UTC offset.
*
* If you find other makes and models that need this treatment, please open a
* ticket on GitHub with example images or videos and we can update the
* default predicate.
*
* The return value is the number of minutes to adjust the timezone by.
*
* @default Returns 60 for Nikon cameras when `DaylightSavings` is `true`
* @see https://github.com/photostructure/exiftool-vendored.js/issues/215
*/
adjustTimeZoneIfDaylightSavings: (tags: Tags, tz: string) => Maybe<number>;
/**
* Timezone parsing requires a bunch of heuristics due to hardware and
* software companies not following metadata specifications similarly.
*
* If GPS metadata is trustworthy, set this to `true` to override explicit
* values assigned to {@link TimezoneOffsetTagnames}.
*
* Note that there **are** regions that have had their IANA timezone change
* over time--this will result in incorrect timezones.
*
* @default false
*/
preferTimezoneInferenceFromGps: boolean;
/**
* Should ExifTool keep times that are stored as seconds since UTC epoch as
* UTC times? If `false`, ExifTool will use local time instead of UTC/Zulu.
*
* Note: when trying to validate this option, we could not find a single
* example that had a unixtime-encoded datetime, so this is likely irrelevant
* for most use cases and files.
*
* @default true (to avoid unintentionally adopting local timezones)
* @see https://exiftool.org/ExifTool.html#KeepUTCTime
*/
keepUTCTime: boolean;
/**
* Timeout in milliseconds for synchronous disposal (using Symbol.dispose).
* If graceful cleanup takes longer than this, forceful cleanup is attempted.
*
* @default 1000 (1 second)
*/
disposalTimeoutMs?: number;
/**
* Timeout in milliseconds for asynchronous disposal (using Symbol.asyncDispose).
* If graceful cleanup takes longer than this, forceful cleanup is attempted.
*
* @default 5000 (5 seconds)
*/
asyncDisposalTimeoutMs?: number;
}
export declare function handleDeprecatedOptions<T extends Partial<Pick<ExifToolOptions, "includeImageDataMD5" | "imageHashType">>>(options: T): T;