fix: face detection of edited assets (#31240)

This commit is contained in:
Daniel Dietzler
2026-09-03 15:40:30 +02:00
committed by GitHub
parent da8131d5c2
commit 399217bf5f
5 changed files with 65 additions and 12 deletions
@@ -2,14 +2,16 @@ import { Kysely } from 'kysely';
import { DateTime } from 'luxon';
import { AssetEditAction, MirrorAxis } from 'src/dtos/editing.dto';
import { AssetFaceCreateDto } from 'src/dtos/person.dto';
import { JobName } from 'src/enum';
import { AssetFileType, JobName } from 'src/enum';
import { AccessRepository } from 'src/repositories/access.repository';
import { AssetEditRepository } from 'src/repositories/asset-edit.repository';
import { AssetJobRepository } from 'src/repositories/asset-job.repository';
import { AssetRepository } from 'src/repositories/asset.repository';
import { ConfigRepository } from 'src/repositories/config.repository';
import { DatabaseRepository } from 'src/repositories/database.repository';
import { JobRepository } from 'src/repositories/job.repository';
import { LoggingRepository } from 'src/repositories/logging.repository';
import { MachineLearningRepository } from 'src/repositories/machine-learning.repository';
import { PersonRepository } from 'src/repositories/person.repository';
import { StorageRepository } from 'src/repositories/storage.repository';
import { SystemMetadataRepository } from 'src/repositories/system-metadata.repository';
@@ -26,6 +28,7 @@ const setup = (db?: Kysely<DB>) => {
database: db || defaultDatabase,
real: [
AccessRepository,
AssetJobRepository,
ConfigRepository,
DatabaseRepository,
PersonRepository,
@@ -33,7 +36,7 @@ const setup = (db?: Kysely<DB>) => {
AssetEditRepository,
SystemMetadataRepository,
],
mock: [JobRepository, LoggingRepository, StorageRepository],
mock: [JobRepository, LoggingRepository, StorageRepository, MachineLearningRepository],
});
};
@@ -99,6 +102,38 @@ describe(PersonService.name, () => {
});
});
describe('handleDetectFaces', () => {
it('should prefer an edited preview file', async () => {
const { sut, ctx } = setup();
const config = await ctx.getConfig();
const { user } = await ctx.newUser();
const { asset } = await ctx.newAsset({ ownerId: user.id });
await ctx.newExif({ assetId: asset.id, description: '' });
await ctx.newAssetFile({
assetId: asset.id,
type: AssetFileType.Preview,
isEdited: true,
path: 'edited_file.jpg',
});
await ctx.newAssetFile({
assetId: asset.id,
type: AssetFileType.Preview,
isEdited: false,
path: 'unedited_file.jpg',
});
ctx
.getMock(MachineLearningRepository)
.detectFaces.mockResolvedValue({ imageHeight: 42, imageWidth: 69, faces: [] });
await sut.handleDetectFaces({ id: asset.id });
expect(ctx.getMock(MachineLearningRepository).detectFaces).toHaveBeenCalledWith(
'edited_file.jpg',
config.machineLearning.facialRecognition,
);
});
});
describe('handleQueueRecognizeFaces', () => {
it('should delete all people and queue faces for recognition', async () => {
const { sut, ctx } = setup();