Fix video files with identical phashes being merged during scan (#5461)

* Change Fingerprints.Remove to return new instead of mutate current
* Match only by oshash and md5 when merging scenes during scan
This commit is contained in:
WithoutPants 2024-11-07 14:29:26 +11:00 committed by GitHub
parent 2a454e5a1e
commit 602f95dd29
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 25 additions and 5 deletions

View File

@ -1100,7 +1100,8 @@ func (s *scanJob) removeOutdatedFingerprints(existing models.File, fp models.Fin
// oshash has changed, MD5 is missing - remove MD5 from the existing fingerprints // oshash has changed, MD5 is missing - remove MD5 from the existing fingerprints
logger.Infof("Removing outdated checksum from %s", existing.Base().Path) logger.Infof("Removing outdated checksum from %s", existing.Base().Path)
existing.Base().Fingerprints.Remove(models.FingerprintTypeMD5) b := existing.Base()
b.Fingerprints = b.Fingerprints.Remove(models.FingerprintTypeMD5)
} }
// returns a file only if it was updated // returns a file only if it was updated

View File

@ -28,16 +28,31 @@ func (f *Fingerprint) Value() string {
type Fingerprints []Fingerprint type Fingerprints []Fingerprint
func (f *Fingerprints) Remove(type_ string) { func (f Fingerprints) Remove(type_ string) Fingerprints {
var ret Fingerprints var ret Fingerprints
for _, ff := range *f { for _, ff := range f {
if ff.Type != type_ { if ff.Type != type_ {
ret = append(ret, ff) ret = append(ret, ff)
} }
} }
*f = ret return ret
}
func (f Fingerprints) Filter(types ...string) Fingerprints {
var ret Fingerprints
for _, ff := range f {
for _, t := range types {
if ff.Type == t {
ret = append(ret, ff)
break
}
}
}
return ret
} }
// Equals returns true if the contents of this slice are equal to those in the other slice. // Equals returns true if the contents of this slice are equal to those in the other slice.

View File

@ -16,6 +16,10 @@ import (
var ( var (
ErrNotVideoFile = errors.New("not a video file") ErrNotVideoFile = errors.New("not a video file")
// fingerprint types to match with
// only try to match by data fingerprints, _not_ perceptual fingerprints
matchableFingerprintTypes = []string{models.FingerprintTypeOshash, models.FingerprintTypeMD5}
) )
type ScanCreatorUpdater interface { type ScanCreatorUpdater interface {
@ -87,7 +91,7 @@ func (h *ScanHandler) Handle(ctx context.Context, f models.File, oldFile models.
if len(existing) == 0 { if len(existing) == 0 {
// try also to match file by fingerprints // try also to match file by fingerprints
existing, err = h.CreatorUpdater.FindByFingerprints(ctx, videoFile.Fingerprints) existing, err = h.CreatorUpdater.FindByFingerprints(ctx, videoFile.Fingerprints.Filter(matchableFingerprintTypes...))
if err != nil { if err != nil {
return fmt.Errorf("finding existing scene by fingerprints: %w", err) return fmt.Errorf("finding existing scene by fingerprints: %w", err)
} }