diff --git a/transcoder/migrations/000005_fingerprints.up.sql b/transcoder/migrations/000005_fingerprints.up.sql index e95c45f5..81c1b229 100644 --- a/transcoder/migrations/000005_fingerprints.up.sql +++ b/transcoder/migrations/000005_fingerprints.up.sql @@ -8,12 +8,6 @@ create table gocoder.fingerprints( end_data text not null ); -create table gocoder.chapterprints( - id serial primary key, - data text not null -); - -alter table gocoder.chapters add column fingerprint_id integer references gocoder.chapterprints(id) on delete set null; alter table gocoder.chapters add column match_accuracy integer; commit; diff --git a/transcoder/src/chapters.go b/transcoder/src/chapters.go index aeb8b90d..3d93f535 100644 --- a/transcoder/src/chapters.go +++ b/transcoder/src/chapters.go @@ -45,10 +45,6 @@ func (s *MetadataService) IdentifyChapters(ctx context.Context, info *MediaInfo, return } - if err := s.DeleteFingerprint(ctx, info.Id); err != nil { - slog.WarnContext(ctx, "failed to delete fingerprint", "path", info.Path, "err", err) - } - _, err = s.Database.Exec(ctx, `update gocoder.info set ver_fingerprint = $2 where id = $1`, info.Id, FingerprintVersion, @@ -73,79 +69,6 @@ func (s *MetadataService) compareWithOther( return nil, fmt.Errorf("failed to get metadata for %s: %w", otherPath, err) } - hasChapterprints := false - for _, c := range otherInfo.Chapters { - if c.FingerprintId != nil { - hasChapterprints = true - break - } - } - - if hasChapterprints { - return s.matchByChapterprints(ctx, info, fingerprint, otherInfo) - } - - return s.matchByOverlap(ctx, info, fingerprint, otherInfo) -} - -func (s *MetadataService) matchByChapterprints( - ctx context.Context, - info *MediaInfo, - fingerprint *Fingerprint, - otherInfo *MediaInfo, -) ([]Chapter, error) { - var candidates []Chapter - - for _, ch := range otherInfo.Chapters { - if ch.FingerprintId == nil { - continue - } - if ch.Type == Content { - continue - } - - needle, err := s.GetChapterprint(ctx, *ch.FingerprintId) - if err != nil { - slog.WarnContext(ctx, "failed to get chapterprint", "chapterprintId", *ch.FingerprintId, "err", err) - continue - } - - fp := fingerprint.Start - startOffset := 0.0 - if ch.Type == Credits { - fp = fingerprint.End - startOffset = max(info.Duration-FpEndDuration, 0) - } - - match, err := FpFindContain(ctx, fp, needle) - if err != nil { - slog.WarnContext(ctx, "failed to find chapterprint in fingerprint", "err", err) - continue - } - if match == nil { - continue - } - - candidates = append(candidates, Chapter{ - Id: info.Id, - StartTime: float32(startOffset + match.Start), - EndTime: float32(startOffset + match.Start + match.Duration), - Name: "", - Type: ch.Type, - FingerprintId: ch.FingerprintId, - MatchAccuracy: new(int32(match.Accuracy)), - }) - } - - return candidates, nil -} - -func (s *MetadataService) matchByOverlap( - ctx context.Context, - info *MediaInfo, - fingerprint *Fingerprint, - otherInfo *MediaInfo, -) ([]Chapter, error) { otherPrint, err := s.ComputeFingerprint(ctx, otherInfo) if err != nil { return nil, fmt.Errorf("failed to compute fingerprint for %s: %w", otherInfo.Path, err) @@ -173,7 +96,6 @@ func (s *MetadataService) matchByOverlap( EndTime: float32(intro.StartFirst + intro.Duration), Name: "", Type: Intro, - Fingerprint: fingerprint.Start, MatchAccuracy: new(int32(intro.Accuracy)), }) } @@ -182,14 +104,12 @@ func (s *MetadataService) matchByOverlap( endOffset := info.Duration - samplesToSec(len(fingerprint.End)) slog.InfoContext(ctx, "Identified credits", "start", endOffset+cred.StartFirst, "duration", cred.Duration, "end_offset", endOffset) candidates = append(candidates, Chapter{ - Id: info.Id, - StartTime: float32(endOffset + cred.StartFirst), - EndTime: float32(endOffset + cred.StartFirst + cred.Duration), - Name: "", - Type: Credits, - Fingerprint: fingerprint.End, - FingerprintOffset: endOffset, - MatchAccuracy: new(int32(cred.Accuracy)), + Id: info.Id, + StartTime: float32(endOffset + cred.StartFirst), + EndTime: float32(endOffset + cred.StartFirst + cred.Duration), + Name: "", + Type: Credits, + MatchAccuracy: new(int32(cred.Accuracy)), }) } @@ -216,9 +136,6 @@ func mergeChapters(info *MediaInfo, candidates []Chapter) []Chapter { if chapters[i].Type == Content { chapters[i].Type = cand.Type } - chapters[i].Fingerprint = cand.Fingerprint - chapters[i].FingerprintOffset = cand.FingerprintOffset - chapters[i].FingerprintId = cand.FingerprintId chapters[i].MatchAccuracy = cand.MatchAccuracy merged = true break @@ -238,9 +155,6 @@ func mergeChapters(info *MediaInfo, candidates []Chapter) []Chapter { EndTime: cand.EndTime, Name: "", Type: cand.Type, - Fingerprint: cand.Fingerprint, - FingerprintOffset: cand.FingerprintOffset, - FingerprintId: cand.FingerprintId, MatchAccuracy: cand.MatchAccuracy, }, info.Duration) } @@ -326,34 +240,10 @@ func (s *MetadataService) saveChapters(ctx context.Context, infoId int32, chapte } for _, c := range chapters { - if c.FingerprintId == nil && c.Fingerprint != nil { - fp, err := ExtractSegment( - c.Fingerprint, - float64(c.StartTime)-c.FingerprintOffset, - float64(c.EndTime)-c.FingerprintOffset, - ) - slog.InfoContext( - ctx, - "extracting chapterprint", - "start", float64(c.StartTime)-c.FingerprintOffset, - "end", float64(c.EndTime)-c.FingerprintOffset, - ) - if err != nil { - slog.WarnContext(ctx, "failed to extract chapter segment", "err", err) - continue - } - - fpId, err := s.StoreChapterprint(ctx, fp) - if err != nil { - slog.WarnContext(ctx, "failed to store intro chapterprint", "err", err) - } else { - c.FingerprintId = new(fpId) - } - } _, err = tx.Exec(ctx, - `insert into gocoder.chapters(id, start_time, end_time, name, type, fingerprint_id, match_accuracy) - values ($1, $2, $3, $4, $5, $6, $7)`, - infoId, c.StartTime, c.EndTime, c.Name, c.Type, c.FingerprintId, c.MatchAccuracy, + `insert into gocoder.chapters(id, start_time, end_time, name, type, match_accuracy) + values ($1, $2, $3, $4, $5, $6)`, + infoId, c.StartTime, c.EndTime, c.Name, c.Type, c.MatchAccuracy, ) if err != nil { return fmt.Errorf("failed to insert chapter: %w", err) diff --git a/transcoder/src/fingerprints.go b/transcoder/src/fingerprints.go index 0780b629..52a684e2 100644 --- a/transcoder/src/fingerprints.go +++ b/transcoder/src/fingerprints.go @@ -154,37 +154,3 @@ func (s *MetadataService) DeleteFingerprint(ctx context.Context, infoID int32) e ) return err } - -func (s *MetadataService) GetChapterprint(ctx context.Context, id int32) ([]uint32, error) { - var data string - err := s.Database.QueryRow(ctx, - `select data from gocoder.chapterprints where id = $1`, - id, - ).Scan(&data) - if err != nil { - return nil, fmt.Errorf("failed to get chapterprint %d: %w", id, err) - } - - fingerprint, err := DecompressFingerprint(data) - if err != nil { - return nil, fmt.Errorf("failed to decompress chapterprint %d: %w", id, err) - } - return fingerprint, nil -} - -func (s *MetadataService) StoreChapterprint(ctx context.Context, fp []uint32) (int32, error) { - data, err := CompressFingerprint(fp) - if err != nil { - return 0, fmt.Errorf("failed to compress chapterprint: %w", err) - } - - var id int32 - err = s.Database.QueryRow(ctx, - `insert into gocoder.chapterprints(data) values ($1) returning id`, - data, - ).Scan(&id) - if err != nil { - return 0, fmt.Errorf("failed to store chapterprint: %w", err) - } - return id, nil -} diff --git a/transcoder/src/fingerprints_compare.go b/transcoder/src/fingerprints_compare.go index 2f6cb95d..e4393867 100644 --- a/transcoder/src/fingerprints_compare.go +++ b/transcoder/src/fingerprints_compare.go @@ -242,22 +242,3 @@ func FpFindOverlap(ctx context.Context, fp1 []uint32, fp2 []uint32) ([]Overlap, runs := findMatchingRuns(a1, a2, s1, s2) return runs, nil } - -func FpFindContain(ctx context.Context, haystack []uint32, needle []uint32) (*Match, error) { - offset := findBestOffset(ctx, haystack, needle) - if offset == nil || *offset < 0 || *offset+len(needle) < len(haystack) { - return nil, nil - } - - corr := segmentCorrelation(haystack[*offset:*offset+len(needle)], needle) - if corr < MatchThreshold { - return nil, nil - } - - accuracy := min(int(corr*100), 100) - return &Match{ - Start: samplesToSec(*offset), - Duration: samplesToSec(len(needle)), - Accuracy: accuracy, - }, nil -} diff --git a/transcoder/src/fingerprints_utils.go b/transcoder/src/fingerprints_utils.go index 80f14a24..2978de00 100644 --- a/transcoder/src/fingerprints_utils.go +++ b/transcoder/src/fingerprints_utils.go @@ -75,22 +75,3 @@ func DecompressFingerprint(compressed string) ([]uint32, error) { return result, nil } - -func ExtractSegment(fp []uint32, startSec, endSec float64) ([]uint32, error) { - startIdx := secToSamples(startSec) - endIdx := secToSamples(endSec) - - if startIdx < 0 { - startIdx = 0 - } - if endIdx > len(fp) { - endIdx = len(fp) - } - if startIdx >= endIdx { - return nil, fmt.Errorf("invalid segment range: %f-%f", startSec, endSec) - } - - segment := make([]uint32, endIdx-startIdx) - copy(segment, fp[startIdx:endIdx]) - return segment, nil -} diff --git a/transcoder/src/info.go b/transcoder/src/info.go index 282ed39f..c4e1c9f3 100644 --- a/transcoder/src/info.go +++ b/transcoder/src/info.go @@ -155,12 +155,6 @@ type Chapter struct { Name string `json:"name" db:"name"` /// The type value is used to mark special chapters (opening/credits...) Type ChapterType `json:"type" db:"type"` - /// Reference to the chapterprint used for fingerprint matching. - FingerprintId *int32 `json:"-" db:"fingerprint_id"` - /// Only used internally, never fetched from db. - Fingerprint []uint32 `json:"-" db:"-"` - /// Only used internally, never fetched from db - FingerprintOffset float64 `json:"-" db:"-"` /// Accuracy of the fingerprint match (0-100). MatchAccuracy *int32 `json:"matchAccuracy,omitempty" db:"match_accuracy"` }