refactor(server): decouple generated images from image formats (#8246)

* rename

thumbnail config

update target paths, fix tests

rename to image settings

replace legacy enum

better typing

update sql

update api

remove config option

fix

* update docs

* update other thumbnail configs in migration

* keep legacy enum for now

* fix jumbled job names

* fix jumbled job names in tests

* rename thumbhash job

* rename dto

* fix tests

* preserve order

* remove unused import

* keep old fields in dto, marked deprecated

* update sql

---------

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
This commit is contained in:
Mert 2024-04-02 00:56:56 -04:00 committed by GitHub
parent e520c0d1f5
commit 8edc2fb46f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
66 changed files with 916 additions and 547 deletions

View file

@ -4,6 +4,7 @@ import { SystemConfigCore } from 'src/cores/system-config.core';
import { AssetEntity } from 'src/entities/asset.entity';
import { AssetPathType, PathType, PersonPathType } from 'src/entities/move.entity';
import { PersonEntity } from 'src/entities/person.entity';
import { ImageFormat } from 'src/entities/system-config.entity';
import { IAssetRepository } from 'src/interfaces/asset.interface';
import { ICryptoRepository } from 'src/interfaces/crypto.interface';
import { IMoveRepository } from 'src/interfaces/move.interface';
@ -34,7 +35,8 @@ export interface MoveRequest {
};
}
type GeneratedAssetPath = AssetPathType.JPEG_THUMBNAIL | AssetPathType.WEBP_THUMBNAIL | AssetPathType.ENCODED_VIDEO;
export type GeneratedImageType = AssetPathType.PREVIEW | AssetPathType.THUMBNAIL;
export type GeneratedAssetType = GeneratedImageType | AssetPathType.ENCODED_VIDEO;
let instance: StorageCore | null;
@ -94,12 +96,8 @@ export class StorageCore {
return StorageCore.getNestedPath(StorageFolder.THUMBNAILS, person.ownerId, `${person.id}.jpeg`);
}
static getLargeThumbnailPath(asset: AssetEntity) {
return StorageCore.getNestedPath(StorageFolder.THUMBNAILS, asset.ownerId, `${asset.id}.jpeg`);
}
static getSmallThumbnailPath(asset: AssetEntity) {
return StorageCore.getNestedPath(StorageFolder.THUMBNAILS, asset.ownerId, `${asset.id}.webp`);
static getImagePath(asset: AssetEntity, type: GeneratedImageType, format: ImageFormat) {
return StorageCore.getNestedPath(StorageFolder.THUMBNAILS, asset.ownerId, `${asset.id}-${type}.${format}`);
}
static getEncodedVideoPath(asset: AssetEntity) {
@ -128,34 +126,23 @@ export class StorageCore {
return path.startsWith(THUMBNAIL_DIR) || path.startsWith(ENCODED_VIDEO_DIR);
}
async moveAssetFile(asset: AssetEntity, pathType: GeneratedAssetPath) {
const { id: entityId, resizePath, webpPath, encodedVideoPath } = asset;
switch (pathType) {
case AssetPathType.JPEG_THUMBNAIL: {
return this.moveFile({
entityId,
pathType,
oldPath: resizePath,
newPath: StorageCore.getLargeThumbnailPath(asset),
});
}
case AssetPathType.WEBP_THUMBNAIL: {
return this.moveFile({
entityId,
pathType,
oldPath: webpPath,
newPath: StorageCore.getSmallThumbnailPath(asset),
});
}
case AssetPathType.ENCODED_VIDEO: {
return this.moveFile({
entityId,
pathType,
oldPath: encodedVideoPath,
newPath: StorageCore.getEncodedVideoPath(asset),
});
}
}
async moveAssetImage(asset: AssetEntity, pathType: GeneratedImageType, format: ImageFormat) {
const { id: entityId, previewPath, thumbnailPath } = asset;
return this.moveFile({
entityId,
pathType,
oldPath: pathType === AssetPathType.PREVIEW ? previewPath : thumbnailPath,
newPath: StorageCore.getImagePath(asset, AssetPathType.THUMBNAIL, format),
});
}
async moveAssetVideo(asset: AssetEntity) {
return this.moveFile({
entityId: asset.id,
pathType: AssetPathType.ENCODED_VIDEO,
oldPath: asset.encodedVideoPath,
newPath: StorageCore.getEncodedVideoPath(asset),
});
}
async movePersonFile(person: PersonEntity, pathType: PersonPathType) {
@ -294,11 +281,11 @@ export class StorageCore {
case AssetPathType.ORIGINAL: {
return this.assetRepository.update({ id, originalPath: newPath });
}
case AssetPathType.JPEG_THUMBNAIL: {
return this.assetRepository.update({ id, resizePath: newPath });
case AssetPathType.PREVIEW: {
return this.assetRepository.update({ id, previewPath: newPath });
}
case AssetPathType.WEBP_THUMBNAIL: {
return this.assetRepository.update({ id, webpPath: newPath });
case AssetPathType.THUMBNAIL: {
return this.assetRepository.update({ id, thumbnailPath: newPath });
}
case AssetPathType.ENCODED_VIDEO: {
return this.assetRepository.update({ id, encodedVideoPath: newPath });

View file

@ -10,6 +10,7 @@ import {
AudioCodec,
CQMode,
Colorspace,
ImageFormat,
LogLevel,
SystemConfig,
SystemConfigEntity,
@ -112,9 +113,11 @@ export const defaults = Object.freeze<SystemConfig>({
hashVerificationEnabled: true,
template: '{{y}}/{{y}}-{{MM}}-{{dd}}/{{filename}}',
},
thumbnail: {
webpSize: 250,
jpegSize: 1440,
image: {
thumbnailFormat: ImageFormat.WEBP,
thumbnailSize: 250,
previewFormat: ImageFormat.JPEG,
previewSize: 1440,
quality: 80,
colorspace: Colorspace.P3,
},