1
0
Fork 0
mirror of https://github.com/immich-app/immich.git synced 2025-01-06 03:46:47 +01:00

fix(server): exif duration with scale (#4541)

This commit is contained in:
Jason Rasmussen 2023-10-19 14:51:56 -04:00 committed by GitHub
parent 5a7ef02387
commit 29182cfc9a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 62 additions and 3 deletions

View file

@ -409,6 +409,54 @@ describe(MetadataService.name, () => {
localDateTime: new Date('1970-01-01'), localDateTime: new Date('1970-01-01'),
}); });
}); });
it('should handle duration', async () => {
assetMock.getByIds.mockResolvedValue([assetStub.image]);
metadataMock.getExifTags.mockResolvedValue({ Duration: 6.21 });
await sut.handleMetadataExtraction({ id: assetStub.image.id });
expect(assetMock.getByIds).toHaveBeenCalledWith([assetStub.image.id]);
expect(assetMock.upsertExif).toHaveBeenCalled();
expect(assetMock.save).toHaveBeenCalledWith(
expect.objectContaining({
id: assetStub.image.id,
duration: '00:00:06.210',
}),
);
});
it('should handle duration as an object without Scale', async () => {
assetMock.getByIds.mockResolvedValue([assetStub.image]);
metadataMock.getExifTags.mockResolvedValue({ Duration: { Value: 6.2 } });
await sut.handleMetadataExtraction({ id: assetStub.image.id });
expect(assetMock.getByIds).toHaveBeenCalledWith([assetStub.image.id]);
expect(assetMock.upsertExif).toHaveBeenCalled();
expect(assetMock.save).toHaveBeenCalledWith(
expect.objectContaining({
id: assetStub.image.id,
duration: '00:00:06.200',
}),
);
});
it('should handle duration with scale', async () => {
assetMock.getByIds.mockResolvedValue([assetStub.image]);
metadataMock.getExifTags.mockResolvedValue({ Duration: { Scale: 1.11111111111111e-5, Value: 558720 } });
await sut.handleMetadataExtraction({ id: assetStub.image.id });
expect(assetMock.getByIds).toHaveBeenCalledWith([assetStub.image.id]);
expect(assetMock.upsertExif).toHaveBeenCalled();
expect(assetMock.save).toHaveBeenCalledWith(
expect.objectContaining({
id: assetStub.image.id,
duration: '00:00:06.207',
}),
);
});
}); });
describe('handleQueueSidecar', () => { describe('handleQueueSidecar', () => {

View file

@ -7,6 +7,7 @@ import { Duration } from 'luxon';
import { usePagination } from '../domain.util'; import { usePagination } from '../domain.util';
import { IBaseJob, IEntityJob, JOBS_ASSET_PAGINATION_SIZE, JobName, QueueName } from '../job'; import { IBaseJob, IEntityJob, JOBS_ASSET_PAGINATION_SIZE, JobName, QueueName } from '../job';
import { import {
ExifDuration,
IAlbumRepository, IAlbumRepository,
IAssetRepository, IAssetRepository,
ICryptoRepository, ICryptoRepository,
@ -398,7 +399,11 @@ export class MetadataService {
return bitsPerSample; return bitsPerSample;
} }
private getDuration(seconds?: number): string { private getDuration(seconds?: number | ExifDuration): string {
return Duration.fromObject({ seconds }).toFormat('hh:mm:ss.SSS'); let _seconds = seconds as number;
if (typeof seconds === 'object') {
_seconds = seconds.Value * (seconds?.Scale || 1);
}
return Duration.fromObject({ seconds: _seconds }).toFormat('hh:mm:ss.SSS');
} }
} }

View file

@ -14,7 +14,12 @@ export interface ReverseGeocodeResult {
city: string | null; city: string | null;
} }
export interface ImmichTags extends Omit<Tags, 'FocalLength'> { export interface ExifDuration {
Value: number;
Scale?: number;
}
export interface ImmichTags extends Omit<Tags, 'FocalLength' | 'Duration'> {
ContentIdentifier?: string; ContentIdentifier?: string;
MotionPhoto?: number; MotionPhoto?: number;
MotionPhotoVersion?: number; MotionPhotoVersion?: number;
@ -22,6 +27,7 @@ export interface ImmichTags extends Omit<Tags, 'FocalLength'> {
MediaGroupUUID?: string; MediaGroupUUID?: string;
ImagePixelDepth?: string; ImagePixelDepth?: string;
FocalLength?: number; FocalLength?: number;
Duration?: number | ExifDuration;
} }
export interface IMetadataRepository { export interface IMetadataRepository {