Skip to content

Commit

Permalink
Fix video files with identical phashes being merged during scan (#5461)
Browse files Browse the repository at this point in the history
* Change Fingerprints.Remove to return new instead of mutate current
* Match only by oshash and md5 when merging scenes during scan
  • Loading branch information
WithoutPants authored Nov 7, 2024
1 parent 2a454e5 commit 602f95d
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 5 deletions.
3 changes: 2 additions & 1 deletion pkg/file/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
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
Expand Down
21 changes: 18 additions & 3 deletions pkg/models/fingerprint.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,31 @@ func (f *Fingerprint) Value() string {

type Fingerprints []Fingerprint

func (f *Fingerprints) Remove(type_ string) {
func (f Fingerprints) Remove(type_ string) Fingerprints {
var ret Fingerprints

for _, ff := range *f {
for _, ff := range f {
if ff.Type != type_ {
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.
Expand Down
6 changes: 5 additions & 1 deletion pkg/scene/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ import (

var (
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 {
Expand Down Expand Up @@ -87,7 +91,7 @@ func (h *ScanHandler) Handle(ctx context.Context, f models.File, oldFile models.

if len(existing) == 0 {
// 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 {
return fmt.Errorf("finding existing scene by fingerprints: %w", err)
}
Expand Down

0 comments on commit 602f95d

Please sign in to comment.