I
Immich•3y ago
rardxyz

Incorrect date shown

Immich is incorrectly showing the date of the photos. It is adding 8 hours on the date it was taken. How do I correctly set this up?
date shown in immich
date originally taken
87 Replies
Alex Tran
Alex Tran•3y ago
We are aware of the issue and we planned to fix it. Timing is one of the hardest things in Computer Science šŸ˜›
rardxyz
rardxyzOP•3y ago
that's okay! I thought I missed something in the setup. thanks
Alex Tran
Alex Tran•3y ago
Yep, apologize for the inconvenience, we will communicate with the users clearly when we have it fixed
Kryptonian
Kryptonian•3y ago
Is it currently known why it manages to use wrong dates as same seems to happen to videos and images?
Alex Tran
Alex Tran•3y ago
because of the timezone
Kryptonian
Kryptonian•3y ago
Timezone of the container?
Alex Tran
Alex Tran•3y ago
date is correct, just the timezone translation is incorrect
Kryptonian
Kryptonian•3y ago
Is it a frontend issue or is the API itself returning the wrong date for the assets?
Alex Tran
Alex Tran•3y ago
It is the exif extraction issue since timezone not always include in exif
Kryptonian
Kryptonian•3y ago
Oh, yeah i can see that being an issue. :D
Alex Tran
Alex Tran•3y ago
We have a path to fix it but not having the resource to work on it yet Google Photos also got a lot of time zone incorrectly šŸ˜› time is a hard issue especially dealing with different device that register the exif, some use gps and if gps isn't available, you lose that piece of info or photos with a camera without timezone info
Kryptonian
Kryptonian•3y ago
Hmm, I believe that the date the photo was taken is always included in the photo itself, no? So one could potentially add an failback to the exif extraction that's global to the immich instance which timezone to use.
Alex Tran
Alex Tran•3y ago
Timestamp, yes but timezone isn't always there and some camera have timestamp as UTC
Kryptonian
Kryptonian•3y ago
Yes, thus failback.
Alex Tran
Alex Tran•3y ago
so you will need to know which timezone need to be translated to yes that is the plan
Kryptonian
Kryptonian•3y ago
Of course some camera does it differently.
Alex Tran
Alex Tran•3y ago
Correct
Kryptonian
Kryptonian•3y ago
A lot of the incorrects in my case are from a bulk upload from CLI. :(
Alex Tran
Alex Tran•3y ago
We are planning to use this tool to fix https://photostructure.github.io/exiftool-vendored.js/
exiftool-vendored
Documentation for exiftool-vendored
Alex Tran
Alex Tran•3y ago
if you have time/effort you can try to open a PR to help fix the issue
Kryptonian
Kryptonian•3y ago
Is it the server/microservices containers that do the exif extraction?
Alex Tran
Alex Tran•3y ago
No description
Kryptonian
Kryptonian•3y ago
Okay, I can see how easilly it can fail currently. Okay, I'm working on trying to get the parsing better, but I'm little confused as to what decides this Postgres query?
immich_postgres | 2023-01-14 21:25:07.846 UTC [132] ERROR: invalid input syntax for type timestamp with time zone: "{"_ctor":"ExifDateTime","year":2021,"month":6,"day":27,"hour":13,"minute":36,"second":2,"millisecond":0,"tzoffsetMinutes":180,"rawValue":"2021:06:27 13:36:02","zoneName":"Europe/Helsinki"}"
immich_postgres | 2023-01-14 21:25:07.846 UTC [132] CONTEXT: unnamed portal parameter $7 = '...'
immich_postgres | 2023-01-14 21:25:07.846 UTC [132] STATEMENT: INSERT INTO "exif"("assetId", "description", "exifImageWidth", "exifImageHeight", "fileSizeInByte", "orientation", "dateTimeOriginal", "modifyDate", "latitude", "longitude", "city", "state", "country", "make", "model", "imageName", "lensModel", "fNumber", "focalLength", "iso", "exposureTime", "fps", "exifTextSearchableColumn") VALUES ($1, DEFAULT, $2, $3, $4, $5, $6, $7, $8, $9, DEFAULT, DEFAULT, DEFAULT, $10, $11, $12, $13, $14, $15, $16, $17, DEFAULT, DEFAULT) RETURNING "id", "description"
immich_postgres | 2023-01-14 21:25:07.846 UTC [132] ERROR: invalid input syntax for type timestamp with time zone: "{"_ctor":"ExifDateTime","year":2021,"month":6,"day":27,"hour":13,"minute":36,"second":2,"millisecond":0,"tzoffsetMinutes":180,"rawValue":"2021:06:27 13:36:02","zoneName":"Europe/Helsinki"}"
immich_postgres | 2023-01-14 21:25:07.846 UTC [132] CONTEXT: unnamed portal parameter $7 = '...'
immich_postgres | 2023-01-14 21:25:07.846 UTC [132] STATEMENT: INSERT INTO "exif"("assetId", "description", "exifImageWidth", "exifImageHeight", "fileSizeInByte", "orientation", "dateTimeOriginal", "modifyDate", "latitude", "longitude", "city", "state", "country", "make", "model", "imageName", "lensModel", "fNumber", "focalLength", "iso", "exposureTime", "fps", "exifTextSearchableColumn") VALUES ($1, DEFAULT, $2, $3, $4, $5, $6, $7, $8, $9, DEFAULT, DEFAULT, DEFAULT, $10, $11, $12, $13, $14, $15, $16, $17, DEFAULT, DEFAULT) RETURNING "id", "description"
Alex Tran
Alex Tran•3y ago
what did you try?
Kryptonian
Kryptonian•3y ago
exiftool is smart enough so that it will extract timezone from GPS coordinates automatically and that timezone is correct and was automatically parsed. Currently I have done the following:
@Process(exifExtractionProcessorName)
async extractExifInfo(job: Job<IExifExtractionProcessor>) {
try {
const { asset, fileName }: { asset: AssetEntity; fileName: string } = job.data;
const exiftool = require("exiftool-vendored").exiftool;
await exiftool.version().then((version: any) => Logger.log(`We are running ExifTool v${version}`))
const exifData = await exiftool.read(asset.originalPath);
Logger.log(exifData);

if (!exifData) {
throw new Error(`can not parse exif data from file ${asset.originalPath}`);
}

const createdAt = new Date(exifData.DateTimeOriginal || exifData.CreateDate || new Date(asset.createdAt));
Logger.log("Hmm", createdAt);
const fileStats = fs.statSync(asset.originalPath);
const fileSizeInBytes = fileStats.size;
const newExif = new ExifEntity();
newExif.assetId = asset.id;
newExif.make = exifData['Make'] || null;
newExif.model = exifData['Model'] || null;
newExif.imageName = path.parse(fileName).name || null;
newExif.exifImageHeight = exifData['ExifImageHeight'] || exifData['ImageHeight'] || null;
newExif.exifImageWidth = exifData['ExifImageWidth'] || exifData['ImageWidth'] || null;
newExif.fileSizeInByte = fileSizeInBytes || null;
newExif.orientation = exifData['Orientation'] || null;
newExif.dateTimeOriginal = createdAt;
newExif.modifyDate = exifData['ModifyDate'] || null;
newExif.lensModel = exifData['LensModel'] || null;
newExif.fNumber = exifData['FNumber'] || null;
newExif.focalLength = exifData['FocalLength'] || null;
newExif.iso = exifData['ISO'] || null;
newExif.exposureTime = exifData['ExposureTime'] || null;
newExif.latitude = exifData['latitude'] || null;
newExif.longitude = exifData['longitude'] || null;
@Process(exifExtractionProcessorName)
async extractExifInfo(job: Job<IExifExtractionProcessor>) {
try {
const { asset, fileName }: { asset: AssetEntity; fileName: string } = job.data;
const exiftool = require("exiftool-vendored").exiftool;
await exiftool.version().then((version: any) => Logger.log(`We are running ExifTool v${version}`))
const exifData = await exiftool.read(asset.originalPath);
Logger.log(exifData);

if (!exifData) {
throw new Error(`can not parse exif data from file ${asset.originalPath}`);
}

const createdAt = new Date(exifData.DateTimeOriginal || exifData.CreateDate || new Date(asset.createdAt));
Logger.log("Hmm", createdAt);
const fileStats = fs.statSync(asset.originalPath);
const fileSizeInBytes = fileStats.size;
const newExif = new ExifEntity();
newExif.assetId = asset.id;
newExif.make = exifData['Make'] || null;
newExif.model = exifData['Model'] || null;
newExif.imageName = path.parse(fileName).name || null;
newExif.exifImageHeight = exifData['ExifImageHeight'] || exifData['ImageHeight'] || null;
newExif.exifImageWidth = exifData['ExifImageWidth'] || exifData['ImageWidth'] || null;
newExif.fileSizeInByte = fileSizeInBytes || null;
newExif.orientation = exifData['Orientation'] || null;
newExif.dateTimeOriginal = createdAt;
newExif.modifyDate = exifData['ModifyDate'] || null;
newExif.lensModel = exifData['LensModel'] || null;
newExif.fNumber = exifData['FNumber'] || null;
newExif.focalLength = exifData['FocalLength'] || null;
newExif.iso = exifData['ISO'] || null;
newExif.exposureTime = exifData['ExposureTime'] || null;
newExif.latitude = exifData['latitude'] || null;
newExif.longitude = exifData['longitude'] || null;
That hmm logger shows up as Sun Jun 27 2021 10:36:02 GMT+0000 (Coordinated Universal Time) which is correct.
Alex Tran
Alex Tran•3y ago
try newExif.dateTimeOriginal = createdAt.toISOString(); Since const createdAt = new Date(exifData.DateTimeOriginal || exifData.CreateDate || new Date(asset.createdAt)); create the Date object the database expects the string
Kryptonian
Kryptonian•3y ago
I feel like it's failing in the else for timezone converting: That else is probably one of the issues.
if (newExif.longitude && newExif.latitude) {
const tz = find(newExif.latitude, newExif.longitude)[0];
const localTimeWithTimezone = createdAt.toISOString();

if (localTimeWithTimezone.length == 24) {
// Remove the last character
const localTimeWithoutTimezone = localTimeWithTimezone.slice(0, -1);
const correctUTCTime = luxon.DateTime.fromISO(localTimeWithoutTimezone, { zone: tz }).toUTC().toISO();
newExif.dateTimeOriginal = new Date(correctUTCTime);
await this.assetRepository.save({
id: asset.id,
createdAt: correctUTCTime,
});
}
} else {
await this.assetRepository.save({
id: asset.id,
createdAt: createdAt.toISOString(),
});
}
if (newExif.longitude && newExif.latitude) {
const tz = find(newExif.latitude, newExif.longitude)[0];
const localTimeWithTimezone = createdAt.toISOString();

if (localTimeWithTimezone.length == 24) {
// Remove the last character
const localTimeWithoutTimezone = localTimeWithTimezone.slice(0, -1);
const correctUTCTime = luxon.DateTime.fromISO(localTimeWithoutTimezone, { zone: tz }).toUTC().toISO();
newExif.dateTimeOriginal = new Date(correctUTCTime);
await this.assetRepository.save({
id: asset.id,
createdAt: correctUTCTime,
});
}
} else {
await this.assetRepository.save({
id: asset.id,
createdAt: createdAt.toISOString(),
});
}
Alex Tran
Alex Tran•3y ago
if the new library handle the timezone correctly, this block of code can be removed
Kryptonian
Kryptonian•3y ago
That newExif.dateTimeOriginal should be a string, not Date.
Alex Tran
Alex Tran•3y ago
Correct, but you assign the Date object to it through this line const createdAt = new Date(exifData.DateTimeOriginal || exifData.CreateDate || new Date(asset.createdAt));
Kryptonian
Kryptonian•3y ago
I'm not sure if I'm following as Type 'string' is not assignable to type 'Date'.
Alex Tran
Alex Tran•3y ago
Please make sure to check the type correct for the value you assign to the variable There is also the problem with thisline const createdAt = new Date(exifData.DateTimeOriginal || exifData.CreateDate || new Date(asset.createdAt)); I believe the new Date() takes in a string but you evaluate new Date(asset.createdAt) at the third case which might throw an error
Kryptonian
Kryptonian•3y ago
That line wasn't changed as if those exifData.DateTimeOriginal nor exifData.CreateDate doesn't exist in the data, it probably should use the asset's creation date.
Alex Tran
Alex Tran•3y ago
Maybe open a PR and we can help take a look at it, it would be better for us to checkout the branch and help you debug as well šŸ™‚
Kryptonian
Kryptonian•3y ago
There: https://github.com/immich-app/immich/pull/1326/ The Postgres error seems to come from when it tries to save the exif data, which makes sense if it's not in the right format it expects. @Alex Tran I figured out that it was complaining about modifyDate one. But shouldn't this be accepted?
immich_postgres | 2023-01-14 22:47:54.609 UTC [305] ERROR: invalid input syntax for type double precision: "14.0 mm"
immich_postgres | 2023-01-14 22:47:54.609 UTC [305] CONTEXT: unnamed portal parameter $15 = '...'
immich_postgres | 2023-01-14 22:47:54.609 UTC [305] STATEMENT: INSERT INTO "exif"("assetId", "description", "exifImageWidth", "exifImageHeight", "fileSizeInByte", "orientation", "dateTimeOriginal", "modifyDate", "latitude", "longitude", "city", "state", "country", "make", "model", "imageName", "lensModel", "fNumber", "focalLength", "iso", "exposureTime", "fps", "exifTextSearchableColumn") VALUES ($1, DEFAULT, $2, $3, $4, $5, $6, $7, $8, $9, DEFAULT, DEFAULT, DEFAULT, $10, $11, $12, $13, $14, $15, $16, $17, DEFAULT, DEFAULT) RETURNING "id", "description"
immich_microservices | [Nest] 2265 - 01/14/2023, 10:47:54 PM ERROR [MetadataExtractionProcessor] Error extracting EXIF QueryFailedError: invalid input syntax for type double precision: "14.0 mm"
immich_microservices | QueryFailedError: invalid input syntax for type double precision: "14.0 mm"
immich_microservices | at PostgresQueryRunner.query (/usr/src/app/src/driver/postgres/PostgresQueryRunner.ts:299:19)
immich_microservices | at processTicksAndRejections (node:internal/process/task_queues:96:5)
immich_microservices | at InsertQueryBuilder.execute (/usr/src/app/src/query-builder/InsertQueryBuilder.ts:163:33)
immich_microservices | at SubjectExecutor.executeInsertOperations (/usr/src/app/src/persistence/SubjectExecutor.ts:428:42)
immich_microservices | at SubjectExecutor.execute (/usr/src/app/src/persistence/SubjectExecutor.ts:137:9)
immich_microservices | at EntityPersistExecutor.execute (/usr/src/app/src/persistence/EntityPersistExecutor.ts:197:21)
immich_microservices | at MetadataExtractionProcessor.extractExifInfo (/usr/src/app/apps/microservices/src/processors/metadata-extraction.processor.ts:213:7)
immich_postgres | 2023-01-14 22:47:54.609 UTC [305] ERROR: invalid input syntax for type double precision: "14.0 mm"
immich_postgres | 2023-01-14 22:47:54.609 UTC [305] CONTEXT: unnamed portal parameter $15 = '...'
immich_postgres | 2023-01-14 22:47:54.609 UTC [305] STATEMENT: INSERT INTO "exif"("assetId", "description", "exifImageWidth", "exifImageHeight", "fileSizeInByte", "orientation", "dateTimeOriginal", "modifyDate", "latitude", "longitude", "city", "state", "country", "make", "model", "imageName", "lensModel", "fNumber", "focalLength", "iso", "exposureTime", "fps", "exifTextSearchableColumn") VALUES ($1, DEFAULT, $2, $3, $4, $5, $6, $7, $8, $9, DEFAULT, DEFAULT, DEFAULT, $10, $11, $12, $13, $14, $15, $16, $17, DEFAULT, DEFAULT) RETURNING "id", "description"
immich_microservices | [Nest] 2265 - 01/14/2023, 10:47:54 PM ERROR [MetadataExtractionProcessor] Error extracting EXIF QueryFailedError: invalid input syntax for type double precision: "14.0 mm"
immich_microservices | QueryFailedError: invalid input syntax for type double precision: "14.0 mm"
immich_microservices | at PostgresQueryRunner.query (/usr/src/app/src/driver/postgres/PostgresQueryRunner.ts:299:19)
immich_microservices | at processTicksAndRejections (node:internal/process/task_queues:96:5)
immich_microservices | at InsertQueryBuilder.execute (/usr/src/app/src/query-builder/InsertQueryBuilder.ts:163:33)
immich_microservices | at SubjectExecutor.executeInsertOperations (/usr/src/app/src/persistence/SubjectExecutor.ts:428:42)
immich_microservices | at SubjectExecutor.execute (/usr/src/app/src/persistence/SubjectExecutor.ts:137:9)
immich_microservices | at EntityPersistExecutor.execute (/usr/src/app/src/persistence/EntityPersistExecutor.ts:197:21)
immich_microservices | at MetadataExtractionProcessor.extractExifInfo (/usr/src/app/apps/microservices/src/processors/metadata-extraction.processor.ts:213:7)
Yay! I got it working. :)
Alex Tran
Alex Tran•3y ago
Thank you, I will take a look at the PR later and add some feedback
jrasm91
jrasm91•3y ago
We should still save the created date back to the original asset, yes? Created date is passed in from the client and might not match the actual date here. The asset shows up in the timeline based on asset.createdAt and they both need to be the same.
Kryptonian
Kryptonian•3y ago
Are you thinking of the case when there's no exif data or am I missing something?
jrasm91
jrasm91•3y ago
What do you mean?
Kryptonian
Kryptonian•3y ago
I think you mean just to preserve:
await this.assetRepository.save({
id: asset.id,
createdAt: createdAt?.toISOString(),
});
await this.assetRepository.save({
id: asset.id,
createdAt: createdAt?.toISOString(),
});
Right?
jrasm91
jrasm91•3y ago
If, for some reason the mobile app, cli, or other client sends the wrong created at date or if it's different from what exif returns the asset will show up in the wrong place in the timeline. It's not so much about if there is exif or not, it's about the date used in the timeline being potentially different than the created date extracted from exif. Yes
Kryptonian
Kryptonian•3y ago
Ah, yeah. I can see now what you mean. Also could these be the result of my changes or something else?
immich_machine_learning | Error reading file TypeError: Cannot read properties of undefined (reading 'classify')
immich_machine_learning | at ImageClassifierService.tagImage (/usr/src/app/src/image-classifier/image-classifier.service.ts:34:55)
immich_machine_learning | at ImageClassifierController.tagImage (/usr/src/app/src/image-classifier/image-classifier.controller.ts:12:46)
immich_machine_learning | at /usr/src/app/node_modules/@nestjs/core/router/router-execution-context.js:38:29
immich_machine_learning | at processTicksAndRejections (node:internal/process/task_queues:96:5)
immich_machine_learning | at /usr/src/app/node_modules/@nestjs/core/router/router-execution-context.js:46:28
immich_machine_learning | at /usr/src/app/node_modules/@nestjs/core/router/router-proxy.js:9:17
immich_machine_learning | Error reading file TypeError: Cannot read properties of undefined (reading 'detect')
immich_machine_learning | at ObjectDetectionService.detectObject (/usr/src/app/src/object-detection/object-detection.service.ts:24:53)
immich_machine_learning | at ObjectDetectionController.detectObject (/usr/src/app/src/object-detection/object-detection.controller.ts:13:46)
immich_machine_learning | at /usr/src/app/node_modules/@nestjs/core/router/router-execution-context.js:38:29
immich_machine_learning | at processTicksAndRejections (node:internal/process/task_queues:96:5)
immich_machine_learning | at /usr/src/app/node_modules/@nestjs/core/router/router-execution-context.js:46:28
immich_machine_learning | at /usr/src/app/node_modules/@nestjs/core/router/router-proxy.js:9:17
immich_machine_learning | Error reading file TypeError: Cannot read properties of undefined (reading 'classify')
immich_machine_learning | at ImageClassifierService.tagImage (/usr/src/app/src/image-classifier/image-classifier.service.ts:34:55)
immich_machine_learning | at ImageClassifierController.tagImage (/usr/src/app/src/image-classifier/image-classifier.controller.ts:12:46)
immich_machine_learning | at /usr/src/app/node_modules/@nestjs/core/router/router-execution-context.js:38:29
immich_machine_learning | at processTicksAndRejections (node:internal/process/task_queues:96:5)
immich_machine_learning | at /usr/src/app/node_modules/@nestjs/core/router/router-execution-context.js:46:28
immich_machine_learning | at /usr/src/app/node_modules/@nestjs/core/router/router-proxy.js:9:17
immich_machine_learning | Error reading file TypeError: Cannot read properties of undefined (reading 'detect')
immich_machine_learning | at ObjectDetectionService.detectObject (/usr/src/app/src/object-detection/object-detection.service.ts:24:53)
immich_machine_learning | at ObjectDetectionController.detectObject (/usr/src/app/src/object-detection/object-detection.controller.ts:13:46)
immich_machine_learning | at /usr/src/app/node_modules/@nestjs/core/router/router-execution-context.js:38:29
immich_machine_learning | at processTicksAndRejections (node:internal/process/task_queues:96:5)
immich_machine_learning | at /usr/src/app/node_modules/@nestjs/core/router/router-execution-context.js:46:28
immich_machine_learning | at /usr/src/app/node_modules/@nestjs/core/router/router-proxy.js:9:17
Also why does the vercel code-coverage fail? I cannot see it so please: https://vercel.com/immich/immich-code-coverage/HSfdiaaDmXMh4kfSX4jF4mfuniTT
jrasm91
jrasm91•3y ago
This looks like a runtime thing - the ml model hasn't been loaded yet when this code runs. Either that or there's an error loading the model. I don't have access, but it runs the server tests and deploys the coverage report. Possibly code coverage dropped (although you mostly removed code? Lol). You can connect to the server container locally and run all the checks to make sure they're still passing.
Kryptonian
Kryptonian•3y ago
I think something needs to be done about the libs/common/src/utils/time-utils.ts:1:19 as it's using the exifr lib too.
Alex Tran
Alex Tran•3y ago
You can substitute the new library to do the same thing, correct?
Kryptonian
Kryptonian•3y ago
Should be able to yes, but I'm banging my head against the types as it's Maybe<String> :D Gave it the same treatment and pushed my changes. :) We both seem to be working too fast for our own good kinda with the PR. :D
Alex Tran
Alex Tran•3y ago
Thank you for the PR, this is quality change šŸ™‚ I forgot to attach the issue that this PR resolves so I have to go find it šŸ˜›
jrasm91
jrasm91•3y ago
I was just looking through the code, are we changing the behavior of exif when a file is missing the info?
Alex Tran
Alex Tran•3y ago
Not really, it still records as much data as possible
jrasm91
jrasm91•3y ago
Specifically, we used to throw an error when exif parsing failed, now we're going to create smart asset info regardless if it fails or not, ri ght?
Alex Tran
Alex Tran•3y ago
Smart asset info are tags that coming from Machine Learning
jrasm91
jrasm91•3y ago
sorry, I mean the asset exif record
Alex Tran
Alex Tran•3y ago
So then yes With this library we can add functionality to write EXIF to the file
jrasm91
jrasm91•3y ago
OK, but just clarifying - we did not use to always create a exif record, but now we have decided to always make a record regardless if exif parsing failed or not?
Alex Tran
Alex Tran•3y ago
Ah I believe so, it should have been this way from the start.
jrasm91
jrasm91•3y ago
Why is parseStringToNumber async?
Alex Tran
Alex Tran•3y ago
I am fixing that part
jrasm91
jrasm91•3y ago
How come exifData is only closed (exiftool.end() if the file has DateTimeOriginal? It seems like it should be closed always (in the time-utils)
Alex Tran
Alex Tran•3y ago
Also fixing this part
Kryptonian
Kryptonian•3y ago
Small nits were missed it seems, but I'm also not sure if that end is even needed in time-utils anymore. šŸ¤” It does work though as is.
jrasm91
jrasm91•3y ago
Right, but is it causing memory leaks?
Kryptonian
Kryptonian•3y ago
That's a very good question which I don't know.
Alex Tran
Alex Tran•3y ago
Tested and didn't see memory leaked
jrasm91
jrasm91•3y ago
Did you test parsing file without exif data?
Kryptonian
Kryptonian•3y ago
Yes
jrasm91
jrasm91•3y ago
I mean specifically for memory leaks
Alex Tran
Alex Tran•3y ago
Nope, I tested with not closing the exif instance
jrasm91
jrasm91•3y ago
Yeah, it looks like you aren't supposed to use the import from exitfool-vendored.pl, but if you use the exiftool singleton you don't need to call end().
Kryptonian
Kryptonian•3y ago
Yes, and if you use it the other way, tests are not happy.
jrasm91
jrasm91•3y ago
What exactly about the test is not happy?
Kryptonian
Kryptonian•3y ago
Not finding vendored-exiftool despite it being there. Probably jest config issue
jrasm91
jrasm91•3y ago
Do you have an actual error message?
Kryptonian
Kryptonian•3y ago
GitHub
Bug: jest and vendored-exiftool doesn't seem to like each other Ā· I...
Describe the bug For unknown reason, I&#39;m getting the Vendored ExifTool does not exist error despite it existing at /usr/src/app/node_modules/exiftool-vendored.pl/bin/exiftool on Alpine. To ...
JD
JD•3y ago
On a Pixel 7 Pro, I was also facing the images being marked with incorrect timestamps, although only the ones with location data. This is fixed in the latest update, thanks! Had to delete and re-upload the images to trigger the exif extraction again. Is there no way to delete exif data for all images and run it again?
Alex Tran
Alex Tran•3y ago
We are planning to add a job to rescan all EXIF
Kryptonian
Kryptonian•3y ago
@Alex Tran We might want to add some logic to the exif parsing for not respecting the DateTimeOriginal if it's in the future, like "DateTimeOriginal": "2033:07:21 14:31:35":D Same goes for CreateDate, and modify date.
Alex Tran
Alex Tran•3y ago
What do you mean?
Kryptonian
Kryptonian•3y ago
I mean if the exif data is incorrect in a way that the dates are 1-5+ years into the future, I don't think those should be respected but rather try to figure out if any of them are at all less than 1 year into the future.
Alex Tran
Alex Tran•3y ago
No description
Kryptonian
Kryptonian•3y ago
Example exif data:
[{
"SourceFile": "<not-important so snipped>",
"ExifToolVersion": 12.42,
"FileName": "<not-important so snipped>",
"Directory": ".",
"FileSize": "2.1 MB",
"FileModifyDate": "2020:02:20 07:30:07+02:00",
"FileAccessDate": "2023:01:19 18:03:29+02:00",
"FileInodeChangeDate": "2020:02:20 07:30:07+02:00",
"FilePermissions": "-rwxr-xr-x",
"FileType": "JPEG",
"FileTypeExtension": "jpg",
"MIMEType": "image/jpeg",
"ExifByteOrder": "Little-endian (Intel, II)",
"ImageDescription": "<Digimax S500 / Kenox S500 / Digimax Cyber 530>",
"Make": "Samsung Techwin",
"Model": "<Digimax S500 / Kenox S500 / Digimax Cyber 530>",
"Orientation": "Horizontal (normal)",
"XResolution": 96,
"YResolution": 96,
"ResolutionUnit": "inches",
"Software": 608201,
"ModifyDate": "2033:07:21 14:31:35",
"YCbCrPositioning": "Co-sited",
"Copyright": "COPYRIGHT, 2006",
"ExposureTime": "1/45",
"FNumber": 2.8,
"ExposureProgram": "Program AE",
"ISO": 100,
"ExifVersion": "0220",
"DateTimeOriginal": "2033:07:21 14:31:35",
"CreateDate": "2033:07:21 14:31:35",
"ComponentsConfiguration": "Y, Cb, Cr, -",
"CompressedBitsPerPixel": 3.397613932,
"ShutterSpeedValue": "1/45",
"ApertureValue": 2.8,
"ExposureCompensation": 0,
"MaxApertureValue": 2.8,
"MeteringMode": "Multi-segment",
"LightSource": "Unknown",
"Flash": "Auto, Fired, Red-eye reduction",
"FocalLength": "5.8 mm",
"PreviewImage": "(Binary data 40960 bytes, use -b option to extract)",
"FlashpixVersion": "0100",
"ColorSpace": "sRGB",
"ExifImageWidth": 2560,
"ExifImageHeight": 1920,
"RelatedSoundFile": "RelatedSound",
"InteropIndex": "R98 - DCF basic file (sRGB)",
"InteropVersion": "0100",
"ExposureIndex": 1,
"SensingMethod": "One-chip color area",
"FileSource": "Digital Camera",
"SceneType": "Directly photographed",
"ExposureMode": "Auto",
"WhiteBalance": "Auto",
"DigitalZoomRatio": 1,
"FocalLengthIn35mmFormat": "35 mm",
"SceneCaptureType": "Standard",
"Saturation": "Normal",
"Sharpness": "Normal",
"Compression": "JPEG (old-style)",
"ThumbnailOffset": 41998,
"ThumbnailLength": 3889,
"ImageWidth": 2560,
"ImageHeight": 1920,
"EncodingProcess": "Baseline DCT, Huffman coding",
"BitsPerSample": 8,
"ColorComponents": 3,
"YCbCrSubSampling": "YCbCr4:2:2 (2 1)",
"Aperture": 2.8,
"ImageSize": "2560x1920",
"Megapixels": 4.9,
"ScaleFactor35efl": 6.0,
"ShutterSpeed": "1/45",
"ThumbnailImage": "(Binary data 3889 bytes, use -b option to extract)",
"CircleOfConfusion": "0.005 mm",
"FOV": "54.4 deg",
"FocalLength35efl": "5.8 mm (35 mm equivalent: 35.0 mm)",
"HyperfocalDistance": "2.41 m",
"LightValue": 8.5
}]
[{
"SourceFile": "<not-important so snipped>",
"ExifToolVersion": 12.42,
"FileName": "<not-important so snipped>",
"Directory": ".",
"FileSize": "2.1 MB",
"FileModifyDate": "2020:02:20 07:30:07+02:00",
"FileAccessDate": "2023:01:19 18:03:29+02:00",
"FileInodeChangeDate": "2020:02:20 07:30:07+02:00",
"FilePermissions": "-rwxr-xr-x",
"FileType": "JPEG",
"FileTypeExtension": "jpg",
"MIMEType": "image/jpeg",
"ExifByteOrder": "Little-endian (Intel, II)",
"ImageDescription": "<Digimax S500 / Kenox S500 / Digimax Cyber 530>",
"Make": "Samsung Techwin",
"Model": "<Digimax S500 / Kenox S500 / Digimax Cyber 530>",
"Orientation": "Horizontal (normal)",
"XResolution": 96,
"YResolution": 96,
"ResolutionUnit": "inches",
"Software": 608201,
"ModifyDate": "2033:07:21 14:31:35",
"YCbCrPositioning": "Co-sited",
"Copyright": "COPYRIGHT, 2006",
"ExposureTime": "1/45",
"FNumber": 2.8,
"ExposureProgram": "Program AE",
"ISO": 100,
"ExifVersion": "0220",
"DateTimeOriginal": "2033:07:21 14:31:35",
"CreateDate": "2033:07:21 14:31:35",
"ComponentsConfiguration": "Y, Cb, Cr, -",
"CompressedBitsPerPixel": 3.397613932,
"ShutterSpeedValue": "1/45",
"ApertureValue": 2.8,
"ExposureCompensation": 0,
"MaxApertureValue": 2.8,
"MeteringMode": "Multi-segment",
"LightSource": "Unknown",
"Flash": "Auto, Fired, Red-eye reduction",
"FocalLength": "5.8 mm",
"PreviewImage": "(Binary data 40960 bytes, use -b option to extract)",
"FlashpixVersion": "0100",
"ColorSpace": "sRGB",
"ExifImageWidth": 2560,
"ExifImageHeight": 1920,
"RelatedSoundFile": "RelatedSound",
"InteropIndex": "R98 - DCF basic file (sRGB)",
"InteropVersion": "0100",
"ExposureIndex": 1,
"SensingMethod": "One-chip color area",
"FileSource": "Digital Camera",
"SceneType": "Directly photographed",
"ExposureMode": "Auto",
"WhiteBalance": "Auto",
"DigitalZoomRatio": 1,
"FocalLengthIn35mmFormat": "35 mm",
"SceneCaptureType": "Standard",
"Saturation": "Normal",
"Sharpness": "Normal",
"Compression": "JPEG (old-style)",
"ThumbnailOffset": 41998,
"ThumbnailLength": 3889,
"ImageWidth": 2560,
"ImageHeight": 1920,
"EncodingProcess": "Baseline DCT, Huffman coding",
"BitsPerSample": 8,
"ColorComponents": 3,
"YCbCrSubSampling": "YCbCr4:2:2 (2 1)",
"Aperture": 2.8,
"ImageSize": "2560x1920",
"Megapixels": 4.9,
"ScaleFactor35efl": 6.0,
"ShutterSpeed": "1/45",
"ThumbnailImage": "(Binary data 3889 bytes, use -b option to extract)",
"CircleOfConfusion": "0.005 mm",
"FOV": "54.4 deg",
"FocalLength35efl": "5.8 mm (35 mm equivalent: 35.0 mm)",
"HyperfocalDistance": "2.41 m",
"LightValue": 8.5
}]
That check only check if it's completely out of whack which that one for example is not.
Alex Tran
Alex Tran•3y ago
Tough case, and edge case the user have to edit this then
Kryptonian
Kryptonian•3y ago
It would be nice if there was the ability to edit it.
jrasm91
jrasm91•3y ago
Sounds like the edit exif issue from github šŸ˜„
Alex Tran
Alex Tran•3y ago
GitHub
[Feature]: Metadata Editor Ā· Issue #232 Ā· immich-app/immich
Feature detail Hello, A metadata editor could be very cool feature, with update of metadata directly on file For fixing date/time of files or gps coordinate etc ... Platform Web
Kryptonian
Kryptonian•3y ago
Just about to ask if that's the one. :D

Did you find this page helpful?