forked from Cutlery/immich
update target paths, fix tests
This commit is contained in:
parent
35a2aa472a
commit
a9b90787b2
@ -4,6 +4,7 @@ import { SystemConfigCore } from 'src/cores/system-config.core';
|
|||||||
import { AssetEntity } from 'src/entities/asset.entity';
|
import { AssetEntity } from 'src/entities/asset.entity';
|
||||||
import { AssetPathType, PathType, PersonPathType } from 'src/entities/move.entity';
|
import { AssetPathType, PathType, PersonPathType } from 'src/entities/move.entity';
|
||||||
import { PersonEntity } from 'src/entities/person.entity';
|
import { PersonEntity } from 'src/entities/person.entity';
|
||||||
|
import { ImageFormat } from 'src/entities/system-config.entity';
|
||||||
import { IAssetRepository } from 'src/interfaces/asset.interface';
|
import { IAssetRepository } from 'src/interfaces/asset.interface';
|
||||||
import { ICryptoRepository } from 'src/interfaces/crypto.interface';
|
import { ICryptoRepository } from 'src/interfaces/crypto.interface';
|
||||||
import { IMoveRepository } from 'src/interfaces/move.interface';
|
import { IMoveRepository } from 'src/interfaces/move.interface';
|
||||||
@ -95,8 +96,8 @@ export class StorageCore {
|
|||||||
return StorageCore.getNestedPath(StorageFolder.THUMBNAILS, person.ownerId, `${person.id}.jpeg`);
|
return StorageCore.getNestedPath(StorageFolder.THUMBNAILS, person.ownerId, `${person.id}.jpeg`);
|
||||||
}
|
}
|
||||||
|
|
||||||
static getImagePath(asset: AssetEntity, type: GeneratedImageType) {
|
static getImagePath(asset: AssetEntity, type: GeneratedImageType, format: ImageFormat) {
|
||||||
return StorageCore.getNestedPath(StorageFolder.THUMBNAILS, asset.ownerId, `${asset.id}.${type}`);
|
return StorageCore.getNestedPath(StorageFolder.THUMBNAILS, asset.ownerId, `${asset.id}-${type}.${format}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
static getEncodedVideoPath(asset: AssetEntity) {
|
static getEncodedVideoPath(asset: AssetEntity) {
|
||||||
@ -119,34 +120,23 @@ export class StorageCore {
|
|||||||
return path.startsWith(THUMBNAIL_DIR) || path.startsWith(ENCODED_VIDEO_DIR);
|
return path.startsWith(THUMBNAIL_DIR) || path.startsWith(ENCODED_VIDEO_DIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
async moveAssetFile(asset: AssetEntity, pathType: GeneratedAssetType) {
|
async moveAssetImage(asset: AssetEntity, pathType: GeneratedAssetType, format: ImageFormat) {
|
||||||
const { id: entityId, previewPath, thumbnailPath, encodedVideoPath } = asset;
|
const { id: entityId, previewPath, thumbnailPath } = asset;
|
||||||
switch (pathType) {
|
return this.moveFile({
|
||||||
case AssetPathType.PREVIEW: {
|
entityId,
|
||||||
return this.moveFile({
|
pathType,
|
||||||
entityId,
|
oldPath: pathType === AssetPathType.PREVIEW ? previewPath : thumbnailPath,
|
||||||
pathType,
|
newPath: StorageCore.getImagePath(asset, AssetPathType.THUMBNAIL, format),
|
||||||
oldPath: previewPath,
|
});
|
||||||
newPath: StorageCore.getImagePath(asset, AssetPathType.PREVIEW),
|
}
|
||||||
});
|
|
||||||
}
|
async moveAssetVideo(asset: AssetEntity) {
|
||||||
case AssetPathType.THUMBNAIL: {
|
return this.moveFile({
|
||||||
return this.moveFile({
|
entityId: asset.id,
|
||||||
entityId,
|
pathType: AssetPathType.ENCODED_VIDEO,
|
||||||
pathType,
|
oldPath: asset.encodedVideoPath,
|
||||||
oldPath: thumbnailPath,
|
newPath: StorageCore.getEncodedVideoPath(asset),
|
||||||
newPath: StorageCore.getImagePath(asset, AssetPathType.THUMBNAIL),
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
case AssetPathType.ENCODED_VIDEO: {
|
|
||||||
return this.moveFile({
|
|
||||||
entityId,
|
|
||||||
pathType,
|
|
||||||
oldPath: encodedVideoPath,
|
|
||||||
newPath: StorageCore.getEncodedVideoPath(asset),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async movePersonFile(person: PersonEntity, pathType: PersonPathType) {
|
async movePersonFile(person: PersonEntity, pathType: PersonPathType) {
|
||||||
|
@ -4,6 +4,7 @@ import { ExifEntity } from 'src/entities/exif.entity';
|
|||||||
import {
|
import {
|
||||||
AudioCodec,
|
AudioCodec,
|
||||||
Colorspace,
|
Colorspace,
|
||||||
|
ImageFormat,
|
||||||
SystemConfigKey,
|
SystemConfigKey,
|
||||||
ToneMapping,
|
ToneMapping,
|
||||||
TranscodeHWAccel,
|
TranscodeHWAccel,
|
||||||
@ -214,15 +215,19 @@ describe(MediaService.name, () => {
|
|||||||
await sut.handleGeneratePreview({ id: assetStub.image.id });
|
await sut.handleGeneratePreview({ id: assetStub.image.id });
|
||||||
|
|
||||||
expect(storageMock.mkdirSync).toHaveBeenCalledWith('upload/thumbs/user-id/as/se');
|
expect(storageMock.mkdirSync).toHaveBeenCalledWith('upload/thumbs/user-id/as/se');
|
||||||
expect(mediaMock.resize).toHaveBeenCalledWith('/original/path.jpg', 'upload/thumbs/user-id/as/se/asset-id.jpeg', {
|
expect(mediaMock.resize).toHaveBeenCalledWith(
|
||||||
size: 1440,
|
'/original/path.jpg',
|
||||||
format: 'jpeg',
|
'upload/thumbs/user-id/as/se/asset-id-preview.jpeg',
|
||||||
quality: 80,
|
{
|
||||||
colorspace: Colorspace.SRGB,
|
size: 1440,
|
||||||
});
|
format: ImageFormat.JPEG,
|
||||||
|
quality: 80,
|
||||||
|
colorspace: Colorspace.SRGB,
|
||||||
|
},
|
||||||
|
);
|
||||||
expect(assetMock.update).toHaveBeenCalledWith({
|
expect(assetMock.update).toHaveBeenCalledWith({
|
||||||
id: 'asset-id',
|
id: 'asset-id',
|
||||||
previewPath: 'upload/thumbs/user-id/as/se/asset-id.jpeg',
|
previewPath: 'upload/thumbs/user-id/as/se/asset-id-preview.jpeg',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -233,15 +238,19 @@ describe(MediaService.name, () => {
|
|||||||
await sut.handleGeneratePreview({ id: assetStub.image.id });
|
await sut.handleGeneratePreview({ id: assetStub.image.id });
|
||||||
|
|
||||||
expect(storageMock.mkdirSync).toHaveBeenCalledWith('upload/thumbs/user-id/as/se');
|
expect(storageMock.mkdirSync).toHaveBeenCalledWith('upload/thumbs/user-id/as/se');
|
||||||
expect(mediaMock.resize).toHaveBeenCalledWith('/original/path.jpg', 'upload/thumbs/user-id/as/se/asset-id.jpeg', {
|
expect(mediaMock.resize).toHaveBeenCalledWith(
|
||||||
size: 1440,
|
'/original/path.jpg',
|
||||||
format: 'jpeg',
|
'upload/thumbs/user-id/as/se/asset-id-preview.jpeg',
|
||||||
quality: 80,
|
{
|
||||||
colorspace: Colorspace.P3,
|
size: 1440,
|
||||||
});
|
format: ImageFormat.JPEG,
|
||||||
|
quality: 80,
|
||||||
|
colorspace: Colorspace.P3,
|
||||||
|
},
|
||||||
|
);
|
||||||
expect(assetMock.update).toHaveBeenCalledWith({
|
expect(assetMock.update).toHaveBeenCalledWith({
|
||||||
id: 'asset-id',
|
id: 'asset-id',
|
||||||
previewPath: 'upload/thumbs/user-id/as/se/asset-id.jpeg',
|
previewPath: 'upload/thumbs/user-id/as/se/asset-id-preview.jpeg',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -253,7 +262,7 @@ describe(MediaService.name, () => {
|
|||||||
expect(storageMock.mkdirSync).toHaveBeenCalledWith('upload/thumbs/user-id/as/se');
|
expect(storageMock.mkdirSync).toHaveBeenCalledWith('upload/thumbs/user-id/as/se');
|
||||||
expect(mediaMock.transcode).toHaveBeenCalledWith(
|
expect(mediaMock.transcode).toHaveBeenCalledWith(
|
||||||
'/original/path.ext',
|
'/original/path.ext',
|
||||||
'upload/thumbs/user-id/as/se/asset-id.jpeg',
|
'upload/thumbs/user-id/as/se/asset-id-preview.jpeg',
|
||||||
{
|
{
|
||||||
inputOptions: ['-ss 00:00:00', '-sws_flags accurate_rnd+bitexact+full_chroma_int'],
|
inputOptions: ['-ss 00:00:00', '-sws_flags accurate_rnd+bitexact+full_chroma_int'],
|
||||||
outputOptions: [
|
outputOptions: [
|
||||||
@ -266,7 +275,7 @@ describe(MediaService.name, () => {
|
|||||||
);
|
);
|
||||||
expect(assetMock.update).toHaveBeenCalledWith({
|
expect(assetMock.update).toHaveBeenCalledWith({
|
||||||
id: 'asset-id',
|
id: 'asset-id',
|
||||||
previewPath: 'upload/thumbs/user-id/as/se/asset-id.jpeg',
|
previewPath: 'upload/thumbs/user-id/as/se/asset-id-preview.jpeg',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -278,7 +287,7 @@ describe(MediaService.name, () => {
|
|||||||
expect(storageMock.mkdirSync).toHaveBeenCalledWith('upload/thumbs/user-id/as/se');
|
expect(storageMock.mkdirSync).toHaveBeenCalledWith('upload/thumbs/user-id/as/se');
|
||||||
expect(mediaMock.transcode).toHaveBeenCalledWith(
|
expect(mediaMock.transcode).toHaveBeenCalledWith(
|
||||||
'/original/path.ext',
|
'/original/path.ext',
|
||||||
'upload/thumbs/user-id/as/se/asset-id.jpeg',
|
'upload/thumbs/user-id/as/se/asset-id-preview.jpeg',
|
||||||
{
|
{
|
||||||
inputOptions: ['-ss 00:00:00', '-sws_flags accurate_rnd+bitexact+full_chroma_int'],
|
inputOptions: ['-ss 00:00:00', '-sws_flags accurate_rnd+bitexact+full_chroma_int'],
|
||||||
outputOptions: [
|
outputOptions: [
|
||||||
@ -291,7 +300,7 @@ describe(MediaService.name, () => {
|
|||||||
);
|
);
|
||||||
expect(assetMock.update).toHaveBeenCalledWith({
|
expect(assetMock.update).toHaveBeenCalledWith({
|
||||||
id: 'asset-id',
|
id: 'asset-id',
|
||||||
previewPath: 'upload/thumbs/user-id/as/se/asset-id.jpeg',
|
previewPath: 'upload/thumbs/user-id/as/se/asset-id-preview.jpeg',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -306,7 +315,7 @@ describe(MediaService.name, () => {
|
|||||||
|
|
||||||
expect(mediaMock.transcode).toHaveBeenCalledWith(
|
expect(mediaMock.transcode).toHaveBeenCalledWith(
|
||||||
'/original/path.ext',
|
'/original/path.ext',
|
||||||
'upload/thumbs/user-id/as/se/asset-id.jpeg',
|
'upload/thumbs/user-id/as/se/asset-id-preview.jpeg',
|
||||||
{
|
{
|
||||||
inputOptions: ['-ss 00:00:00', '-sws_flags accurate_rnd+bitexact+full_chroma_int'],
|
inputOptions: ['-ss 00:00:00', '-sws_flags accurate_rnd+bitexact+full_chroma_int'],
|
||||||
outputOptions: [
|
outputOptions: [
|
||||||
@ -337,15 +346,19 @@ describe(MediaService.name, () => {
|
|||||||
assetMock.getByIds.mockResolvedValue([assetStub.image]);
|
assetMock.getByIds.mockResolvedValue([assetStub.image]);
|
||||||
await sut.handleGenerateThumbnail({ id: assetStub.image.id });
|
await sut.handleGenerateThumbnail({ id: assetStub.image.id });
|
||||||
|
|
||||||
expect(mediaMock.resize).toHaveBeenCalledWith('/original/path.jpg', 'upload/thumbs/user-id/as/se/asset-id.webp', {
|
expect(mediaMock.resize).toHaveBeenCalledWith(
|
||||||
format: 'webp',
|
'/original/path.jpg',
|
||||||
size: 250,
|
'upload/thumbs/user-id/as/se/asset-id-thumbnail.webp',
|
||||||
quality: 80,
|
{
|
||||||
colorspace: Colorspace.SRGB,
|
format: ImageFormat.WEBP,
|
||||||
});
|
size: 250,
|
||||||
|
quality: 80,
|
||||||
|
colorspace: Colorspace.SRGB,
|
||||||
|
},
|
||||||
|
);
|
||||||
expect(assetMock.update).toHaveBeenCalledWith({
|
expect(assetMock.update).toHaveBeenCalledWith({
|
||||||
id: 'asset-id',
|
id: 'asset-id',
|
||||||
thumbnailPath: 'upload/thumbs/user-id/as/se/asset-id.webp',
|
thumbnailPath: 'upload/thumbs/user-id/as/se/asset-id-thumbnail.webp',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -357,15 +370,19 @@ describe(MediaService.name, () => {
|
|||||||
await sut.handleGenerateThumbnail({ id: assetStub.image.id });
|
await sut.handleGenerateThumbnail({ id: assetStub.image.id });
|
||||||
|
|
||||||
expect(storageMock.mkdirSync).toHaveBeenCalledWith('upload/thumbs/user-id/as/se');
|
expect(storageMock.mkdirSync).toHaveBeenCalledWith('upload/thumbs/user-id/as/se');
|
||||||
expect(mediaMock.resize).toHaveBeenCalledWith('/original/path.jpg', 'upload/thumbs/user-id/as/se/asset-id.webp', {
|
expect(mediaMock.resize).toHaveBeenCalledWith(
|
||||||
format: 'webp',
|
'/original/path.jpg',
|
||||||
size: 250,
|
'upload/thumbs/user-id/as/se/asset-id-thumbnail.webp',
|
||||||
quality: 80,
|
{
|
||||||
colorspace: Colorspace.P3,
|
format: ImageFormat.WEBP,
|
||||||
});
|
size: 250,
|
||||||
|
quality: 80,
|
||||||
|
colorspace: Colorspace.P3,
|
||||||
|
},
|
||||||
|
);
|
||||||
expect(assetMock.update).toHaveBeenCalledWith({
|
expect(assetMock.update).toHaveBeenCalledWith({
|
||||||
id: 'asset-id',
|
id: 'asset-id',
|
||||||
thumbnailPath: 'upload/thumbs/user-id/as/se/asset-id.webp',
|
thumbnailPath: 'upload/thumbs/user-id/as/se/asset-id-thumbnail.webp',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -153,14 +153,15 @@ export class MediaService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async handleAssetMigration({ id }: IEntityJob): Promise<JobStatus> {
|
async handleAssetMigration({ id }: IEntityJob): Promise<JobStatus> {
|
||||||
|
const { thumbnail } = await this.configCore.getConfig();
|
||||||
const [asset] = await this.assetRepository.getByIds([id]);
|
const [asset] = await this.assetRepository.getByIds([id]);
|
||||||
if (!asset) {
|
if (!asset) {
|
||||||
return JobStatus.FAILED;
|
return JobStatus.FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.storageCore.moveAssetFile(asset, AssetPathType.PREVIEW);
|
await this.storageCore.moveAssetImage(asset, AssetPathType.PREVIEW, thumbnail.previewFormat);
|
||||||
await this.storageCore.moveAssetFile(asset, AssetPathType.THUMBNAIL);
|
await this.storageCore.moveAssetImage(asset, AssetPathType.THUMBNAIL, thumbnail.thumbnailFormat);
|
||||||
await this.storageCore.moveAssetFile(asset, AssetPathType.ENCODED_VIDEO);
|
await this.storageCore.moveAssetVideo(asset);
|
||||||
|
|
||||||
return JobStatus.SUCCESS;
|
return JobStatus.SUCCESS;
|
||||||
}
|
}
|
||||||
@ -179,7 +180,7 @@ export class MediaService {
|
|||||||
private async generateThumbnail(asset: AssetEntity, type: GeneratedImageType, format: ImageFormat) {
|
private async generateThumbnail(asset: AssetEntity, type: GeneratedImageType, format: ImageFormat) {
|
||||||
const { thumbnail, ffmpeg } = await this.configCore.getConfig();
|
const { thumbnail, ffmpeg } = await this.configCore.getConfig();
|
||||||
const size = type === AssetPathType.PREVIEW ? thumbnail.previewSize : thumbnail.thumbnailSize;
|
const size = type === AssetPathType.PREVIEW ? thumbnail.previewSize : thumbnail.thumbnailSize;
|
||||||
const path = StorageCore.getImagePath(asset, type);
|
const path = StorageCore.getImagePath(asset, type, format);
|
||||||
this.storageCore.ensureFolders(path);
|
this.storageCore.ensureFolders(path);
|
||||||
|
|
||||||
switch (asset.type) {
|
switch (asset.type) {
|
||||||
|
@ -4,6 +4,7 @@ import {
|
|||||||
AudioCodec,
|
AudioCodec,
|
||||||
CQMode,
|
CQMode,
|
||||||
Colorspace,
|
Colorspace,
|
||||||
|
ImageFormat,
|
||||||
LogLevel,
|
LogLevel,
|
||||||
SystemConfig,
|
SystemConfig,
|
||||||
SystemConfigEntity,
|
SystemConfigEntity,
|
||||||
@ -120,8 +121,10 @@ const updatedConfig = Object.freeze<SystemConfig>({
|
|||||||
template: '{{y}}/{{y}}-{{MM}}-{{dd}}/{{filename}}',
|
template: '{{y}}/{{y}}-{{MM}}-{{dd}}/{{filename}}',
|
||||||
},
|
},
|
||||||
thumbnail: {
|
thumbnail: {
|
||||||
webpSize: 250,
|
thumbnailFormat: ImageFormat.WEBP,
|
||||||
jpegSize: 1440,
|
thumbnailSize: 250,
|
||||||
|
previewFormat: ImageFormat.JPEG,
|
||||||
|
previewSize: 1440,
|
||||||
quality: 80,
|
quality: 80,
|
||||||
colorspace: Colorspace.P3,
|
colorspace: Colorspace.P3,
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user