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:
parent
5a7ef02387
commit
29182cfc9a
3 changed files with 62 additions and 3 deletions
|
@ -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', () => {
|
||||||
|
|
|
@ -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');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in a new issue