forked from dark_thunder/immich
fix(server): extract duration from video as ISO time (#6863)
* fix(server): extract duration from video as ISO time * feedback and add test * fix test
This commit is contained in:
@ -547,6 +547,22 @@ describe(MetadataService.name, () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should handle duration in ISO time string', async () => {
|
||||||
|
assetMock.getByIds.mockResolvedValue([assetStub.image]);
|
||||||
|
metadataMock.readTags.mockResolvedValue({ Duration: '00:00:08.41' });
|
||||||
|
|
||||||
|
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:08.410',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should handle duration as an object without Scale', async () => {
|
it('should handle duration as an object without Scale', async () => {
|
||||||
assetMock.getByIds.mockResolvedValue([assetStub.image]);
|
assetMock.getByIds.mockResolvedValue([assetStub.image]);
|
||||||
metadataMock.readTags.mockResolvedValue({ Duration: { Value: 6.2 } });
|
metadataMock.readTags.mockResolvedValue({ Duration: { Value: 6.2 } });
|
||||||
|
@ -12,7 +12,6 @@ import { IBaseJob, IEntityJob, ISidecarWriteJob, JOBS_ASSET_PAGINATION_SIZE, Job
|
|||||||
import {
|
import {
|
||||||
ClientEvent,
|
ClientEvent,
|
||||||
DatabaseLock,
|
DatabaseLock,
|
||||||
ExifDuration,
|
|
||||||
IAlbumRepository,
|
IAlbumRepository,
|
||||||
IAssetRepository,
|
IAssetRepository,
|
||||||
ICommunicationRepository,
|
ICommunicationRepository,
|
||||||
@ -555,11 +554,15 @@ export class MetadataService {
|
|||||||
return bitsPerSample;
|
return bitsPerSample;
|
||||||
}
|
}
|
||||||
|
|
||||||
private getDuration(seconds?: number | ExifDuration): string {
|
private getDuration(seconds?: ImmichTags['Duration']): string {
|
||||||
let _seconds = seconds as number;
|
let _seconds = seconds as number;
|
||||||
|
|
||||||
if (typeof seconds === 'object') {
|
if (typeof seconds === 'object') {
|
||||||
_seconds = seconds.Value * (seconds?.Scale || 1);
|
_seconds = seconds.Value * (seconds?.Scale || 1);
|
||||||
|
} else if (typeof seconds === 'string') {
|
||||||
|
_seconds = Duration.fromISOTime(seconds).as('seconds');
|
||||||
}
|
}
|
||||||
|
|
||||||
return Duration.fromObject({ seconds: _seconds }).toFormat('hh:mm:ss.SSS');
|
return Duration.fromObject({ seconds: _seconds }).toFormat('hh:mm:ss.SSS');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ export interface ImmichTags extends Omit<Tags, 'FocalLength' | 'Duration'> {
|
|||||||
MediaGroupUUID?: string;
|
MediaGroupUUID?: string;
|
||||||
ImagePixelDepth?: string;
|
ImagePixelDepth?: string;
|
||||||
FocalLength?: number;
|
FocalLength?: number;
|
||||||
Duration?: number | ExifDuration;
|
Duration?: number | string | ExifDuration;
|
||||||
EmbeddedVideoType?: string;
|
EmbeddedVideoType?: string;
|
||||||
EmbeddedVideoFile?: BinaryField;
|
EmbeddedVideoFile?: BinaryField;
|
||||||
MotionPhotoVideo?: BinaryField;
|
MotionPhotoVideo?: BinaryField;
|
||||||
|
Reference in New Issue
Block a user