mirror of
https://github.com/immich-app/immich.git
synced 2026-01-13 05:26:35 -08:00
* feat: add OCR functionality and related configurations * chore: update labeler configuration for machine learning files * feat(i18n): enhance OCR model descriptions and add orientation classification and unwarping features * chore: update Dockerfile to include ccache for improved build performance * feat(ocr): enhance OCR model configuration with orientation classification and unwarping options, update PaddleOCR integration, and improve response structure * refactor(ocr): remove OCR_CLEANUP job from enum and type definitions * refactor(ocr): remove obsolete OCR entity and migration files, and update asset job status and schema to accommodate new OCR table structure * refactor(ocr): update OCR schema and response structure to use individual coordinates instead of bounding box, and adjust related service and repository files * feat: enhance OCR configuration and functionality - Updated OCR settings to include minimum detection box score, minimum detection score, and minimum recognition score. - Refactored PaddleOCRecognizer to utilize new scoring parameters. - Introduced new database tables for asset OCR data and search functionality. - Modified related services and repositories to support the new OCR features. - Updated translations for improved clarity in settings UI. * sql changes * use rapidocr * change dto * update web * update lock * update api * store positions as normalized floats * match column order in db * update admin ui settings descriptions fix max resolution key set min threshold to 0.1 fix bind * apply config correctly, adjust defaults * unnecessary model type * unnecessary sources * fix(ocr): switch RapidOCR lang type from LangDet to LangRec * fix(ocr): expose lang_type (LangRec.CH) and font_path on OcrOptions for RapidOCR * fix(ocr): make OCR text search case- and accent-insensitive using ILIKE + unaccent * fix(ocr): add OCR search fields * fix: Add OCR database migration and update ML prediction logic. * trigrams are already case insensitive * add tests * format * update migrations * wrong uuid function * linting * maybe fix medium tests * formatting * fix weblate check * openapi * sql * minor fixes * maybe fix medium tests part 2 * passing medium tests * format web * readd sql * format dart * disabled in e2e * chore: translation ordering --------- Co-authored-by: mertalev <101130780+mertalev@users.noreply.github.com> Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
392 lines
8.6 KiB
TypeScript
392 lines
8.6 KiB
TypeScript
import { CronExpression } from '@nestjs/schedule';
|
|
import {
|
|
AudioCodec,
|
|
Colorspace,
|
|
CQMode,
|
|
ImageFormat,
|
|
LogLevel,
|
|
OAuthTokenEndpointAuthMethod,
|
|
QueueName,
|
|
ToneMapping,
|
|
TranscodeHardwareAcceleration,
|
|
TranscodePolicy,
|
|
VideoCodec,
|
|
VideoContainer,
|
|
} from 'src/enum';
|
|
import { ConcurrentQueueName, FullsizeImageOptions, ImageOptions } from 'src/types';
|
|
|
|
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: TranscodeHardwareAcceleration;
|
|
accelDecode: boolean;
|
|
tonemap: ToneMapping;
|
|
};
|
|
job: Record<ConcurrentQueueName, { concurrency: number }>;
|
|
logging: {
|
|
enabled: boolean;
|
|
level: LogLevel;
|
|
};
|
|
machineLearning: {
|
|
enabled: boolean;
|
|
urls: string[];
|
|
availabilityChecks: {
|
|
enabled: boolean;
|
|
timeout: number;
|
|
interval: number;
|
|
};
|
|
clip: {
|
|
enabled: boolean;
|
|
modelName: string;
|
|
};
|
|
duplicateDetection: {
|
|
enabled: boolean;
|
|
maxDistance: number;
|
|
};
|
|
facialRecognition: {
|
|
enabled: boolean;
|
|
modelName: string;
|
|
minScore: number;
|
|
minFaces: number;
|
|
maxDistance: number;
|
|
};
|
|
ocr: {
|
|
enabled: boolean;
|
|
modelName: string;
|
|
minDetectionScore: number;
|
|
minRecognitionScore: number;
|
|
maxResolution: 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 | null;
|
|
enabled: boolean;
|
|
issuerUrl: string;
|
|
mobileOverrideEnabled: boolean;
|
|
mobileRedirectUri: string;
|
|
scope: string;
|
|
signingAlgorithm: string;
|
|
profileSigningAlgorithm: string;
|
|
tokenEndpointAuthMethod: OAuthTokenEndpointAuthMethod;
|
|
timeout: number;
|
|
storageLabelClaim: string;
|
|
storageQuotaClaim: string;
|
|
roleClaim: string;
|
|
};
|
|
passwordLogin: {
|
|
enabled: boolean;
|
|
};
|
|
storageTemplate: {
|
|
enabled: boolean;
|
|
hashVerificationEnabled: boolean;
|
|
template: string;
|
|
};
|
|
image: {
|
|
thumbnail: ImageOptions;
|
|
preview: ImageOptions;
|
|
colorspace: Colorspace;
|
|
extractEmbedded: boolean;
|
|
fullsize: FullsizeImageOptions;
|
|
};
|
|
newVersionCheck: {
|
|
enabled: boolean;
|
|
};
|
|
nightlyTasks: {
|
|
startTime: string;
|
|
databaseCleanup: boolean;
|
|
missingThumbnails: boolean;
|
|
clusterNewFaces: boolean;
|
|
generateMemories: boolean;
|
|
syncQuotaUsage: 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;
|
|
secure: boolean;
|
|
username: string;
|
|
password: string;
|
|
};
|
|
};
|
|
};
|
|
templates: {
|
|
email: {
|
|
welcomeTemplate: string;
|
|
albumInviteTemplate: string;
|
|
albumUpdateTemplate: string;
|
|
};
|
|
};
|
|
server: {
|
|
externalDomain: string;
|
|
loginPageMessage: string;
|
|
publicUsers: boolean;
|
|
};
|
|
user: {
|
|
deleteDelay: number;
|
|
};
|
|
}
|
|
|
|
export type MachineLearningConfig = SystemConfig['machineLearning'];
|
|
|
|
export const defaults = Object.freeze<SystemConfig>({
|
|
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],
|
|
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: TranscodeHardwareAcceleration.Disabled,
|
|
accelDecode: false,
|
|
},
|
|
job: {
|
|
[QueueName.BackgroundTask]: { concurrency: 5 },
|
|
[QueueName.SmartSearch]: { concurrency: 2 },
|
|
[QueueName.MetadataExtraction]: { concurrency: 5 },
|
|
[QueueName.FaceDetection]: { concurrency: 2 },
|
|
[QueueName.Search]: { concurrency: 5 },
|
|
[QueueName.Sidecar]: { concurrency: 5 },
|
|
[QueueName.Library]: { concurrency: 5 },
|
|
[QueueName.Migration]: { concurrency: 5 },
|
|
[QueueName.ThumbnailGeneration]: { concurrency: 3 },
|
|
[QueueName.VideoConversion]: { concurrency: 1 },
|
|
[QueueName.Notification]: { concurrency: 5 },
|
|
[QueueName.Ocr]: { concurrency: 1 },
|
|
},
|
|
logging: {
|
|
enabled: true,
|
|
level: LogLevel.Log,
|
|
},
|
|
machineLearning: {
|
|
enabled: process.env.IMMICH_MACHINE_LEARNING_ENABLED !== 'false',
|
|
urls: [process.env.IMMICH_MACHINE_LEARNING_URL || 'http://immich-machine-learning:3003'],
|
|
availabilityChecks: {
|
|
enabled: true,
|
|
timeout: Number(process.env.IMMICH_MACHINE_LEARNING_PING_TIMEOUT) || 2000,
|
|
interval: 30_000,
|
|
},
|
|
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,
|
|
},
|
|
ocr: {
|
|
enabled: true,
|
|
modelName: 'PP-OCRv5_mobile',
|
|
minDetectionScore: 0.5,
|
|
minRecognitionScore: 0.8,
|
|
maxResolution: 736,
|
|
},
|
|
},
|
|
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: null,
|
|
enabled: false,
|
|
issuerUrl: '',
|
|
mobileOverrideEnabled: false,
|
|
mobileRedirectUri: '',
|
|
scope: 'openid email profile',
|
|
signingAlgorithm: 'RS256',
|
|
profileSigningAlgorithm: 'none',
|
|
storageLabelClaim: 'preferred_username',
|
|
storageQuotaClaim: 'immich_quota',
|
|
roleClaim: 'immich_role',
|
|
tokenEndpointAuthMethod: OAuthTokenEndpointAuthMethod.ClientSecretPost,
|
|
timeout: 30_000,
|
|
},
|
|
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,
|
|
fullsize: {
|
|
enabled: false,
|
|
format: ImageFormat.Jpeg,
|
|
quality: 80,
|
|
},
|
|
},
|
|
newVersionCheck: {
|
|
enabled: true,
|
|
},
|
|
nightlyTasks: {
|
|
startTime: '00:00',
|
|
databaseCleanup: true,
|
|
generateMemories: true,
|
|
syncQuotaUsage: true,
|
|
missingThumbnails: true,
|
|
clusterNewFaces: true,
|
|
},
|
|
trash: {
|
|
enabled: true,
|
|
days: 30,
|
|
},
|
|
theme: {
|
|
customCss: '',
|
|
},
|
|
library: {
|
|
scan: {
|
|
enabled: true,
|
|
cronExpression: CronExpression.EVERY_DAY_AT_MIDNIGHT,
|
|
},
|
|
watch: {
|
|
enabled: false,
|
|
},
|
|
},
|
|
server: {
|
|
externalDomain: '',
|
|
loginPageMessage: '',
|
|
publicUsers: true,
|
|
},
|
|
notifications: {
|
|
smtp: {
|
|
enabled: false,
|
|
from: '',
|
|
replyTo: '',
|
|
transport: {
|
|
ignoreCert: false,
|
|
host: '',
|
|
port: 587,
|
|
secure: false,
|
|
username: '',
|
|
password: '',
|
|
},
|
|
},
|
|
},
|
|
templates: {
|
|
email: {
|
|
welcomeTemplate: '',
|
|
albumInviteTemplate: '',
|
|
albumUpdateTemplate: '',
|
|
},
|
|
},
|
|
user: {
|
|
deleteDelay: 7,
|
|
},
|
|
});
|