mirror of
				https://github.com/immich-app/immich.git
				synced 2025-11-04 03:39:37 -05:00 
			
		
		
		
	chore(server): update exiftool and migrate off deprecated method signatures (#10367)
* chore(server): update exiftool and migrate off deprecated method signatures * chore(server): update exiftool-vendored to 27.0.0 * chore(server): switch away from deprecated exiftool method signatures - options now includes read/writeArgs making the deprecated signatures with args array redundant - switch read call from file,args,options to file,options - switch write call from file,tags,args to file,tags,options * chore(server): move largefilesupport flags into exiftool constructor - options now includes read/writeArgs making it available to be set globally in constructor - switches back to instantiating an instance of exiftool * chore(server): consolidate exiftool config into constructor along with writeArgs * chore(server): move exiftool instantiation into MetadataRepository constructor
This commit is contained in:
		
							parent
							
								
									38e26fd67c
								
							
						
					
					
						commit
						1b67ea2d91
					
				
							
								
								
									
										15
									
								
								server/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										15
									
								
								server/package-lock.json
									
									
									
										generated
									
									
									
								
							@ -34,7 +34,7 @@
 | 
				
			|||||||
        "class-transformer": "^0.5.1",
 | 
					        "class-transformer": "^0.5.1",
 | 
				
			||||||
        "class-validator": "^0.14.0",
 | 
					        "class-validator": "^0.14.0",
 | 
				
			||||||
        "cookie-parser": "^1.4.6",
 | 
					        "cookie-parser": "^1.4.6",
 | 
				
			||||||
        "exiftool-vendored": "~26.2.0",
 | 
					        "exiftool-vendored": "~27.0.0",
 | 
				
			||||||
        "fast-glob": "^3.3.2",
 | 
					        "fast-glob": "^3.3.2",
 | 
				
			||||||
        "fluent-ffmpeg": "^2.1.2",
 | 
					        "fluent-ffmpeg": "^2.1.2",
 | 
				
			||||||
        "geo-tz": "^8.0.0",
 | 
					        "geo-tz": "^8.0.0",
 | 
				
			||||||
@ -9127,9 +9127,10 @@
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/exiftool-vendored": {
 | 
					    "node_modules/exiftool-vendored": {
 | 
				
			||||||
      "version": "26.2.0",
 | 
					      "version": "27.0.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/exiftool-vendored/-/exiftool-vendored-26.2.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/exiftool-vendored/-/exiftool-vendored-27.0.0.tgz",
 | 
				
			||||||
      "integrity": "sha512-7P6jQ944or7ic2SJzW+uaWK4TLDXlaCppHrBayl4MpIrVcEeQjiQTez4/oOH0wULIRu4j4H6Xruz4SLrDaafUg==",
 | 
					      "integrity": "sha512-/jHX8Jjadj0YJzpqnuBo1Yy2ln2hnRbBIc+3jcVOLQ6qhHEKsLRlfJ145Ghn7k/EcnfpDzVX3V8AUCTC8juTow==",
 | 
				
			||||||
 | 
					      "license": "MIT",
 | 
				
			||||||
      "dependencies": {
 | 
					      "dependencies": {
 | 
				
			||||||
        "@photostructure/tz-lookup": "^10.0.0",
 | 
					        "@photostructure/tz-lookup": "^10.0.0",
 | 
				
			||||||
        "@types/luxon": "^3.4.2",
 | 
					        "@types/luxon": "^3.4.2",
 | 
				
			||||||
@ -22600,9 +22601,9 @@
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "exiftool-vendored": {
 | 
					    "exiftool-vendored": {
 | 
				
			||||||
      "version": "26.2.0",
 | 
					      "version": "27.0.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/exiftool-vendored/-/exiftool-vendored-26.2.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/exiftool-vendored/-/exiftool-vendored-27.0.0.tgz",
 | 
				
			||||||
      "integrity": "sha512-7P6jQ944or7ic2SJzW+uaWK4TLDXlaCppHrBayl4MpIrVcEeQjiQTez4/oOH0wULIRu4j4H6Xruz4SLrDaafUg==",
 | 
					      "integrity": "sha512-/jHX8Jjadj0YJzpqnuBo1Yy2ln2hnRbBIc+3jcVOLQ6qhHEKsLRlfJ145Ghn7k/EcnfpDzVX3V8AUCTC8juTow==",
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "@photostructure/tz-lookup": "^10.0.0",
 | 
					        "@photostructure/tz-lookup": "^10.0.0",
 | 
				
			||||||
        "@types/luxon": "^3.4.2",
 | 
					        "@types/luxon": "^3.4.2",
 | 
				
			||||||
 | 
				
			|||||||
@ -60,7 +60,7 @@
 | 
				
			|||||||
    "class-transformer": "^0.5.1",
 | 
					    "class-transformer": "^0.5.1",
 | 
				
			||||||
    "class-validator": "^0.14.0",
 | 
					    "class-validator": "^0.14.0",
 | 
				
			||||||
    "cookie-parser": "^1.4.6",
 | 
					    "cookie-parser": "^1.4.6",
 | 
				
			||||||
    "exiftool-vendored": "~26.2.0",
 | 
					    "exiftool-vendored": "~27.0.0",
 | 
				
			||||||
    "fast-glob": "^3.3.2",
 | 
					    "fast-glob": "^3.3.2",
 | 
				
			||||||
    "fluent-ffmpeg": "^2.1.2",
 | 
					    "fluent-ffmpeg": "^2.1.2",
 | 
				
			||||||
    "geo-tz": "^8.0.0",
 | 
					    "geo-tz": "^8.0.0",
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
import { Inject, Injectable } from '@nestjs/common';
 | 
					import { Inject, Injectable } from '@nestjs/common';
 | 
				
			||||||
import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
 | 
					import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
 | 
				
			||||||
import { DefaultReadTaskOptions, Tags, exiftool } from 'exiftool-vendored';
 | 
					import { DefaultReadTaskOptions, ExifTool, Tags } from 'exiftool-vendored';
 | 
				
			||||||
import geotz from 'geo-tz';
 | 
					import geotz from 'geo-tz';
 | 
				
			||||||
import { DummyValue, GenerateSql } from 'src/decorators';
 | 
					import { DummyValue, GenerateSql } from 'src/decorators';
 | 
				
			||||||
import { ExifEntity } from 'src/entities/exif.entity';
 | 
					import { ExifEntity } from 'src/entities/exif.entity';
 | 
				
			||||||
@ -20,19 +20,7 @@ export class MetadataRepository implements IMetadataRepository {
 | 
				
			|||||||
    @Inject(ILoggerRepository) private logger: ILoggerRepository,
 | 
					    @Inject(ILoggerRepository) private logger: ILoggerRepository,
 | 
				
			||||||
  ) {
 | 
					  ) {
 | 
				
			||||||
    this.logger.setContext(MetadataRepository.name);
 | 
					    this.logger.setContext(MetadataRepository.name);
 | 
				
			||||||
  }
 | 
					    this.exiftool = new ExifTool({
 | 
				
			||||||
 | 
					 | 
				
			||||||
  async teardown() {
 | 
					 | 
				
			||||||
    await exiftool.end();
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  readTags(path: string): Promise<ImmichTags | null> {
 | 
					 | 
				
			||||||
    return exiftool
 | 
					 | 
				
			||||||
      .read(path, undefined, {
 | 
					 | 
				
			||||||
        ...DefaultReadTaskOptions,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Enable exiftool LFS to parse metadata for files larger than 2GB.
 | 
					 | 
				
			||||||
        optionalArgs: ['-api', 'largefilesupport=1'],
 | 
					 | 
				
			||||||
      defaultVideosToUTC: true,
 | 
					      defaultVideosToUTC: true,
 | 
				
			||||||
      backfillTimezones: true,
 | 
					      backfillTimezones: true,
 | 
				
			||||||
      inferTimezoneFromDatestamps: true,
 | 
					      inferTimezoneFromDatestamps: true,
 | 
				
			||||||
@ -40,20 +28,31 @@ export class MetadataRepository implements IMetadataRepository {
 | 
				
			|||||||
      numericTags: [...DefaultReadTaskOptions.numericTags, 'FocalLength'],
 | 
					      numericTags: [...DefaultReadTaskOptions.numericTags, 'FocalLength'],
 | 
				
			||||||
      /* eslint unicorn/no-array-callback-reference: off, unicorn/no-array-method-this-argument: off */
 | 
					      /* eslint unicorn/no-array-callback-reference: off, unicorn/no-array-method-this-argument: off */
 | 
				
			||||||
      geoTz: (lat, lon) => geotz.find(lat, lon)[0],
 | 
					      geoTz: (lat, lon) => geotz.find(lat, lon)[0],
 | 
				
			||||||
      })
 | 
					      // Enable exiftool LFS to parse metadata for files larger than 2GB.
 | 
				
			||||||
      .catch((error) => {
 | 
					      readArgs: ['-api', 'largefilesupport=1'],
 | 
				
			||||||
 | 
					      writeArgs: ['-api', 'largefilesupport=1', '-overwrite_original'],
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  private exiftool: ExifTool;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  async teardown() {
 | 
				
			||||||
 | 
					    await this.exiftool.end();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  readTags(path: string): Promise<ImmichTags | null> {
 | 
				
			||||||
 | 
					    return this.exiftool.read(path).catch((error) => {
 | 
				
			||||||
      this.logger.warn(`Error reading exif data (${path}): ${error}`, error?.stack);
 | 
					      this.logger.warn(`Error reading exif data (${path}): ${error}`, error?.stack);
 | 
				
			||||||
      return null;
 | 
					      return null;
 | 
				
			||||||
    }) as Promise<ImmichTags | null>;
 | 
					    }) as Promise<ImmichTags | null>;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  extractBinaryTag(path: string, tagName: string): Promise<Buffer> {
 | 
					  extractBinaryTag(path: string, tagName: string): Promise<Buffer> {
 | 
				
			||||||
    return exiftool.extractBinaryTagToBuffer(tagName, path);
 | 
					    return this.exiftool.extractBinaryTagToBuffer(tagName, path);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async writeTags(path: string, tags: Partial<Tags>): Promise<void> {
 | 
					  async writeTags(path: string, tags: Partial<Tags>): Promise<void> {
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      await exiftool.write(path, tags, ['-overwrite_original']);
 | 
					      await this.exiftool.write(path, tags);
 | 
				
			||||||
    } catch (error) {
 | 
					    } catch (error) {
 | 
				
			||||||
      this.logger.warn(`Error writing exif data (${path}): ${error}`);
 | 
					      this.logger.warn(`Error writing exif data (${path}): ${error}`);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user