diff --git a/crates/engine/src/cmd/face_recognize.rs b/crates/engine/src/cmd/face_recognize.rs index e3b385e2c..75f895f63 100644 --- a/crates/engine/src/cmd/face_recognize.rs +++ b/crates/engine/src/cmd/face_recognize.rs @@ -345,10 +345,12 @@ mod imp { current_with(s, cmd, true) } - /// Whether the background scan should look for faces in this photo: it is in the library, has no face regions at all - /// (nothing from XMP, nothing drawn or named, no earlier detection) and has not been searched yet. + /// Whether the background scan should look for faces in this photo: it is in the library, is not a video (the image + /// decoders can't read one, [`Photo::is_video`]), has no face regions at all (nothing from XMP, nothing drawn or + /// named, no earlier detection) and has not been searched yet. fn needs_search(s: &Session, photo: &Photo) -> bool { photo.in_library() + && !photo.is_video() && !photo.meta.regions.iter().any(|r| r.kind == RegionKind::Face) && !s.faces.scanned.contains(photo.id.0) && !s.faces.scan_failed.contains(&photo.id.0) @@ -971,6 +973,22 @@ mod imp { let _ = std::fs::remove_dir_all(&d); } + /// A video went to the image decoders to be searched for faces and failed, once each launch: it is skipped, as the + /// grid's thumbnails skip it (issue #2682 is about those). + #[test] + fn a_video_is_not_searched_for_faces() { + let (mut s, d) = loaded("video"); + let (a, _) = two_photos(&s); + let id = s.catalog.alloc_photo_id(); + let path = d.join("clip.mp4").to_string_lossy().into_owned(); + let clip = Photo::new(id, lightcraft_catalog::Source::File { path }, "clip.mp4", "VIDEO", 1920, 1080, "2026-10-24T00:00:00"); + s.catalog.apply(Op::AddPhoto { photo: Box::new(clip) }).unwrap(); + assert!(needs_search(&s, s.catalog.photo(a).unwrap()), "a photo is searched"); + assert!(!needs_search(&s, s.catalog.photo(id).unwrap())); + assert!(!pending(&s, &[], true).contains(&id)); + let _ = std::fs::remove_dir_all(&d); + } + #[test] fn only_the_background_scan_looks_for_faces_and_only_in_photos_without_any() { let (mut s, d) = loaded("search"); diff --git a/docs/whats-new.md b/docs/whats-new.md index b2fc44327..bb101d7b8 100644 --- a/docs/whats-new.md +++ b/docs/whats-new.md @@ -6,7 +6,8 @@ - A video in the library (an MP4 or MOV brought in from a Lightroom catalog) no longer asks the image decoders for a grid thumbnail (issue #2682). They can't read one, so each video failed with "unrecognised image format", showed a "!" and was tried again whenever the library changed, filling the log. Its cell now keeps the plain placeholder until - LightCraft can show video frames. A video is recognised by its type, by the format `VIDEO` that Lightroom catalogs + LightCraft can show video frames. The background face search skips videos too, instead of failing on each one at + every launch. A video is recognised by its type, by the format `VIDEO` that Lightroom catalogs give videos, or by its extension (`.mp4`, `.mov`, `.m4v`, `.avi`, `.mts`, `.m2ts`, `.3gp`, `.mkv`, `.webm`, `.wmv`, `.mpg`, `.mpeg`).