import { CronExpression } from '@nestjs/schedule'; import { AudioCodec, Colorspace, CQMode, ImageFormat, LogLevel, ToneMapping, TranscodeHWAccel, TranscodePolicy, VideoCodec, VideoContainer, } from 'src/enum'; import { ConcurrentQueueName, QueueName } from 'src/interfaces/job.interface'; import { ImageOptions } from 'src/interfaces/media.interface'; export interface SystemConfig { backup: { database: { enabled: boolean; cronExpression: string; keepLastAmount: number; }; }; ffmpeg: { crf: number; threads: number; preset: string; targetVideoCodec: VideoCodec; acceptedVideoCodecs: VideoCodec[]; targetAudioCodec: AudioCodec; acceptedAudioCodecs: AudioCodec[]; acceptedContainers: VideoContainer[]; targetResolution: string; maxBitrate: string; bframes: number; refs: number; gopSize: number; temporalAQ: boolean; cqMode: CQMode; twoPass: boolean; preferredHwDevice: string; transcode: TranscodePolicy; accel: TranscodeHWAccel; accelDecode: boolean; tonemap: ToneMapping; }; job: Record; logging: { enabled: boolean; level: LogLevel; }; machineLearning: { enabled: boolean; url: string; clip: { enabled: boolean; modelName: string; }; duplicateDetection: { enabled: boolean; maxDistance: number; }; facialRecognition: { enabled: boolean; modelName: string; minScore: number; minFaces: number; maxDistance: number; }; }; map: { enabled: boolean; lightStyle: string; darkStyle: string; }; reverseGeocoding: { enabled: boolean; }; metadata: { faces: { import: 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; profileSigningAlgorithm: string; storageLabelClaim: string; storageQuotaClaim: string; }; passwordLogin: { enabled: boolean; }; storageTemplate: { enabled: boolean; hashVerificationEnabled: boolean; template: string; }; image: { thumbnail: ImageOptions; preview: ImageOptions; 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({ backup: { database: { enabled: true, cronExpression: CronExpression.EVERY_DAY_AT_2AM, keepLastAmount: 14, }, }, ffmpeg: { crf: 23, threads: 0, preset: 'ultrafast', targetVideoCodec: VideoCodec.H264, acceptedVideoCodecs: [VideoCodec.H264], targetAudioCodec: AudioCodec.AAC, acceptedAudioCodecs: [AudioCodec.AAC, AudioCodec.MP3, AudioCodec.LIBOPUS, AudioCodec.PCMS16LE], acceptedContainers: [VideoContainer.MOV, VideoContainer.OGG, VideoContainer.WEBM], targetResolution: '720', maxBitrate: '0', bframes: -1, refs: 0, gopSize: 0, temporalAQ: false, cqMode: CQMode.AUTO, twoPass: false, preferredHwDevice: 'auto', transcode: TranscodePolicy.REQUIRED, tonemap: ToneMapping.HABLE, accel: TranscodeHWAccel.DISABLED, accelDecode: false, }, 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: 3 }, [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', }, duplicateDetection: { enabled: true, maxDistance: 0.01, }, facialRecognition: { enabled: true, modelName: 'buffalo_l', minScore: 0.7, maxDistance: 0.5, minFaces: 3, }, }, map: { enabled: true, lightStyle: 'https://tiles.immich.cloud/v1/style/light.json', darkStyle: 'https://tiles.immich.cloud/v1/style/dark.json', }, reverseGeocoding: { enabled: true, }, metadata: { faces: { import: false, }, }, 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', profileSigningAlgorithm: 'none', storageLabelClaim: 'preferred_username', storageQuotaClaim: 'immich_quota', }, passwordLogin: { enabled: true, }, storageTemplate: { enabled: false, hashVerificationEnabled: true, template: '{{y}}/{{y}}-{{MM}}-{{dd}}/{{filename}}', }, image: { thumbnail: { format: ImageFormat.WEBP, size: 250, quality: 80, }, preview: { format: ImageFormat.JPEG, size: 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, }, });