mirror of
https://github.com/immich-app/immich
synced 2025-11-07 17:27:20 +00:00
refactor(server): system config (#9484)
This commit is contained in:
parent
42d0fc85ca
commit
7b1112f3e3
24 changed files with 379 additions and 397 deletions
|
|
@ -1,12 +1,344 @@
|
|||
import { RegisterQueueOptions } from '@nestjs/bullmq';
|
||||
import { ConfigModuleOptions } from '@nestjs/config';
|
||||
import { CronExpression } from '@nestjs/schedule';
|
||||
import { QueueOptions } from 'bullmq';
|
||||
import { Request, Response } from 'express';
|
||||
import { RedisOptions } from 'ioredis';
|
||||
import Joi from 'joi';
|
||||
import { CLS_ID, ClsModuleOptions } from 'nestjs-cls';
|
||||
import { LogLevel } from 'src/entities/system-config.entity';
|
||||
import { QueueName } from 'src/interfaces/job.interface';
|
||||
import { ConcurrentQueueName, QueueName } from 'src/interfaces/job.interface';
|
||||
|
||||
export enum TranscodePolicy {
|
||||
ALL = 'all',
|
||||
OPTIMAL = 'optimal',
|
||||
BITRATE = 'bitrate',
|
||||
REQUIRED = 'required',
|
||||
DISABLED = 'disabled',
|
||||
}
|
||||
|
||||
export enum TranscodeTarget {
|
||||
NONE,
|
||||
AUDIO,
|
||||
VIDEO,
|
||||
ALL,
|
||||
}
|
||||
|
||||
export enum VideoCodec {
|
||||
H264 = 'h264',
|
||||
HEVC = 'hevc',
|
||||
VP9 = 'vp9',
|
||||
AV1 = 'av1',
|
||||
}
|
||||
|
||||
export enum AudioCodec {
|
||||
MP3 = 'mp3',
|
||||
AAC = 'aac',
|
||||
LIBOPUS = 'libopus',
|
||||
}
|
||||
|
||||
export enum TranscodeHWAccel {
|
||||
NVENC = 'nvenc',
|
||||
QSV = 'qsv',
|
||||
VAAPI = 'vaapi',
|
||||
RKMPP = 'rkmpp',
|
||||
DISABLED = 'disabled',
|
||||
}
|
||||
|
||||
export enum ToneMapping {
|
||||
HABLE = 'hable',
|
||||
MOBIUS = 'mobius',
|
||||
REINHARD = 'reinhard',
|
||||
DISABLED = 'disabled',
|
||||
}
|
||||
|
||||
export enum CQMode {
|
||||
AUTO = 'auto',
|
||||
CQP = 'cqp',
|
||||
ICQ = 'icq',
|
||||
}
|
||||
|
||||
export enum Colorspace {
|
||||
SRGB = 'srgb',
|
||||
P3 = 'p3',
|
||||
}
|
||||
|
||||
export enum ImageFormat {
|
||||
JPEG = 'jpeg',
|
||||
WEBP = 'webp',
|
||||
}
|
||||
|
||||
export enum LogLevel {
|
||||
VERBOSE = 'verbose',
|
||||
DEBUG = 'debug',
|
||||
LOG = 'log',
|
||||
WARN = 'warn',
|
||||
ERROR = 'error',
|
||||
FATAL = 'fatal',
|
||||
}
|
||||
|
||||
export interface SystemConfig {
|
||||
ffmpeg: {
|
||||
crf: number;
|
||||
threads: number;
|
||||
preset: string;
|
||||
targetVideoCodec: VideoCodec;
|
||||
acceptedVideoCodecs: VideoCodec[];
|
||||
targetAudioCodec: AudioCodec;
|
||||
acceptedAudioCodecs: AudioCodec[];
|
||||
targetResolution: string;
|
||||
maxBitrate: string;
|
||||
bframes: number;
|
||||
refs: number;
|
||||
gopSize: number;
|
||||
npl: number;
|
||||
temporalAQ: boolean;
|
||||
cqMode: CQMode;
|
||||
twoPass: boolean;
|
||||
preferredHwDevice: string;
|
||||
transcode: TranscodePolicy;
|
||||
accel: TranscodeHWAccel;
|
||||
tonemap: ToneMapping;
|
||||
};
|
||||
job: Record<ConcurrentQueueName, { concurrency: number }>;
|
||||
logging: {
|
||||
enabled: boolean;
|
||||
level: LogLevel;
|
||||
};
|
||||
machineLearning: {
|
||||
enabled: boolean;
|
||||
url: string;
|
||||
clip: {
|
||||
enabled: boolean;
|
||||
modelName: string;
|
||||
};
|
||||
facialRecognition: {
|
||||
enabled: boolean;
|
||||
modelName: string;
|
||||
minScore: number;
|
||||
minFaces: number;
|
||||
maxDistance: number;
|
||||
};
|
||||
};
|
||||
map: {
|
||||
enabled: boolean;
|
||||
lightStyle: string;
|
||||
darkStyle: string;
|
||||
};
|
||||
reverseGeocoding: {
|
||||
enabled: boolean;
|
||||
};
|
||||
oauth: {
|
||||
autoLaunch: boolean;
|
||||
autoRegister: boolean;
|
||||
buttonText: string;
|
||||
clientId: string;
|
||||
clientSecret: string;
|
||||
defaultStorageQuota: number;
|
||||
enabled: boolean;
|
||||
issuerUrl: string;
|
||||
mobileOverrideEnabled: boolean;
|
||||
mobileRedirectUri: string;
|
||||
scope: string;
|
||||
signingAlgorithm: string;
|
||||
storageLabelClaim: string;
|
||||
storageQuotaClaim: string;
|
||||
};
|
||||
passwordLogin: {
|
||||
enabled: boolean;
|
||||
};
|
||||
storageTemplate: {
|
||||
enabled: boolean;
|
||||
hashVerificationEnabled: boolean;
|
||||
template: string;
|
||||
};
|
||||
image: {
|
||||
thumbnailFormat: ImageFormat;
|
||||
thumbnailSize: number;
|
||||
previewFormat: ImageFormat;
|
||||
previewSize: number;
|
||||
quality: number;
|
||||
colorspace: Colorspace;
|
||||
extractEmbedded: boolean;
|
||||
};
|
||||
newVersionCheck: {
|
||||
enabled: boolean;
|
||||
};
|
||||
trash: {
|
||||
enabled: boolean;
|
||||
days: number;
|
||||
};
|
||||
theme: {
|
||||
customCss: string;
|
||||
};
|
||||
library: {
|
||||
scan: {
|
||||
enabled: boolean;
|
||||
cronExpression: string;
|
||||
};
|
||||
watch: {
|
||||
enabled: boolean;
|
||||
};
|
||||
};
|
||||
notifications: {
|
||||
smtp: {
|
||||
enabled: boolean;
|
||||
from: string;
|
||||
replyTo: string;
|
||||
transport: {
|
||||
ignoreCert: boolean;
|
||||
host: string;
|
||||
port: number;
|
||||
username: string;
|
||||
password: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
server: {
|
||||
externalDomain: string;
|
||||
loginPageMessage: string;
|
||||
};
|
||||
user: {
|
||||
deleteDelay: number;
|
||||
};
|
||||
}
|
||||
|
||||
export const defaults = Object.freeze<SystemConfig>({
|
||||
ffmpeg: {
|
||||
crf: 23,
|
||||
threads: 0,
|
||||
preset: 'ultrafast',
|
||||
targetVideoCodec: VideoCodec.H264,
|
||||
acceptedVideoCodecs: [VideoCodec.H264],
|
||||
targetAudioCodec: AudioCodec.AAC,
|
||||
acceptedAudioCodecs: [AudioCodec.AAC, AudioCodec.MP3, AudioCodec.LIBOPUS],
|
||||
targetResolution: '720',
|
||||
maxBitrate: '0',
|
||||
bframes: -1,
|
||||
refs: 0,
|
||||
gopSize: 0,
|
||||
npl: 0,
|
||||
temporalAQ: false,
|
||||
cqMode: CQMode.AUTO,
|
||||
twoPass: false,
|
||||
preferredHwDevice: 'auto',
|
||||
transcode: TranscodePolicy.REQUIRED,
|
||||
tonemap: ToneMapping.HABLE,
|
||||
accel: TranscodeHWAccel.DISABLED,
|
||||
},
|
||||
job: {
|
||||
[QueueName.BACKGROUND_TASK]: { concurrency: 5 },
|
||||
[QueueName.SMART_SEARCH]: { concurrency: 2 },
|
||||
[QueueName.METADATA_EXTRACTION]: { concurrency: 5 },
|
||||
[QueueName.FACE_DETECTION]: { concurrency: 2 },
|
||||
[QueueName.SEARCH]: { concurrency: 5 },
|
||||
[QueueName.SIDECAR]: { concurrency: 5 },
|
||||
[QueueName.LIBRARY]: { concurrency: 5 },
|
||||
[QueueName.MIGRATION]: { concurrency: 5 },
|
||||
[QueueName.THUMBNAIL_GENERATION]: { concurrency: 5 },
|
||||
[QueueName.VIDEO_CONVERSION]: { concurrency: 1 },
|
||||
[QueueName.NOTIFICATION]: { concurrency: 5 },
|
||||
},
|
||||
logging: {
|
||||
enabled: true,
|
||||
level: LogLevel.LOG,
|
||||
},
|
||||
machineLearning: {
|
||||
enabled: process.env.IMMICH_MACHINE_LEARNING_ENABLED !== 'false',
|
||||
url: process.env.IMMICH_MACHINE_LEARNING_URL || 'http://immich-machine-learning:3003',
|
||||
clip: {
|
||||
enabled: true,
|
||||
modelName: 'ViT-B-32__openai',
|
||||
},
|
||||
facialRecognition: {
|
||||
enabled: true,
|
||||
modelName: 'buffalo_l',
|
||||
minScore: 0.7,
|
||||
maxDistance: 0.5,
|
||||
minFaces: 3,
|
||||
},
|
||||
},
|
||||
map: {
|
||||
enabled: true,
|
||||
lightStyle: '',
|
||||
darkStyle: '',
|
||||
},
|
||||
reverseGeocoding: {
|
||||
enabled: true,
|
||||
},
|
||||
oauth: {
|
||||
autoLaunch: false,
|
||||
autoRegister: true,
|
||||
buttonText: 'Login with OAuth',
|
||||
clientId: '',
|
||||
clientSecret: '',
|
||||
defaultStorageQuota: 0,
|
||||
enabled: false,
|
||||
issuerUrl: '',
|
||||
mobileOverrideEnabled: false,
|
||||
mobileRedirectUri: '',
|
||||
scope: 'openid email profile',
|
||||
signingAlgorithm: 'RS256',
|
||||
storageLabelClaim: 'preferred_username',
|
||||
storageQuotaClaim: 'immich_quota',
|
||||
},
|
||||
passwordLogin: {
|
||||
enabled: true,
|
||||
},
|
||||
storageTemplate: {
|
||||
enabled: false,
|
||||
hashVerificationEnabled: true,
|
||||
template: '{{y}}/{{y}}-{{MM}}-{{dd}}/{{filename}}',
|
||||
},
|
||||
image: {
|
||||
thumbnailFormat: ImageFormat.WEBP,
|
||||
thumbnailSize: 250,
|
||||
previewFormat: ImageFormat.JPEG,
|
||||
previewSize: 1440,
|
||||
quality: 80,
|
||||
colorspace: Colorspace.P3,
|
||||
extractEmbedded: false,
|
||||
},
|
||||
newVersionCheck: {
|
||||
enabled: true,
|
||||
},
|
||||
trash: {
|
||||
enabled: true,
|
||||
days: 30,
|
||||
},
|
||||
theme: {
|
||||
customCss: '',
|
||||
},
|
||||
library: {
|
||||
scan: {
|
||||
enabled: true,
|
||||
cronExpression: CronExpression.EVERY_DAY_AT_MIDNIGHT,
|
||||
},
|
||||
watch: {
|
||||
enabled: false,
|
||||
},
|
||||
},
|
||||
server: {
|
||||
externalDomain: '',
|
||||
loginPageMessage: '',
|
||||
},
|
||||
notifications: {
|
||||
smtp: {
|
||||
enabled: false,
|
||||
from: '',
|
||||
replyTo: '',
|
||||
transport: {
|
||||
ignoreCert: false,
|
||||
host: '',
|
||||
port: 587,
|
||||
username: '',
|
||||
password: '',
|
||||
},
|
||||
},
|
||||
},
|
||||
user: {
|
||||
deleteDelay: 7,
|
||||
},
|
||||
});
|
||||
|
||||
const WHEN_DB_URL_SET = Joi.when('DB_URL', {
|
||||
is: Joi.exist(),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue