Repository navigation
Realtime Seam Jump Policy
A realtime query (see Realtime Query Command) fingerprints a stream in consecutive chunks, queries each chunk, and stitches the chunks that match the same track into one result entry. Between two chunks there is a seam. At every seam the library knows two things: how far the stream advanced, and where the new chunk matched inside the track. When the two agree, the match continues. When the track position jumped ahead of where the stream advance puts it, the library takes one decision: is this still the same playing of the track? RealtimeQueryConfiguration.SeamJumpPolicy answers it.
config.SeamJumpPolicy = SeamJumpPolicy.Stitch; // default: the same playing, stitch whatever the jump
config.SeamJumpPolicy = SeamJumpPolicy.SourceSkip; // the source seeks: stitch and book the skipped track time into the query length
config.SeamJumpPolicy = SeamJumpPolicy.NewOccurrenceAbove(120); // a continuous source: stitch a jump up to 120 s, start a new match above itThe historical behavior. Consecutive chunks that match the same track are stitched whatever the jump. This is correct when every track occurs once in the stream and the source does not seek. Jumps backwards are never stitched: a chunk that re-matches audio behind the accumulated coverage always starts a new result entry (self-similar audio, or the same track playing again).
For a source that seeks, such as an audio or video player under user control. A jump ahead is the listener skipping forward inside the same playing, so the match continues and the skipped track time is booked into the query length of the resulting ResultEntry. Query and track gaps are then reported correctly for the skipped region. A jump backwards is a seek back: the two entries are reordered and stitched. This mode was formerly enabled with AutomaticSkipDetection = true; that flag is now an obsolete shorthand for this policy.
For a continuous source, such as a broadcast, matched against tracks that can repeat their own audio. A jump up to the ceiling is an edit or a glitch of the same playing and the match continues; the permitted gap is added as alignment slack. A larger jump is another occurrence of the audio and the incoming chunk starts a new result entry.
Why this exists. A 28-minute paid program contains its 30, 60 and 120 second advertising spots several times. When one spot airs on its own, consecutive chunks of that airing match copies of the spot that are minutes apart inside the program. Under Stitch they are stitched into one result entry whose track span covers minutes of content that never aired; a 35 second airing reported a track span of 1,495 seconds. Worse, a real airing of the program that reaches a repeated region can jump to a late copy near the end of the track, after which every later chunk falls inside the accumulated coverage and is swallowed: in a replay of the full program against itself, the default policy registered 217 seconds of 1,709.
Choosing the ceiling. The ceiling should be the longest jump that an edit of the same creative can explain. For advertising, a cut longer than a whole standard spot (120 seconds) is not an edit of the same creative, so 120 is the value used by the broadcast monitoring agents. Measured on a day of broadcast matches against standard spots, the track position ran ahead of the stream by more than 10 seconds in 0.9% of matches and by more than 60 seconds in 0.2%; all of those were cut-down edits, and all stay under a 120 second ceiling.
The policy works together with a selection rule in the realtime aggregator that is always active. When one chunk matches the same track at several positions, the aggregator previously kept the candidate with the most coverage. It now prefers, among the candidates that the policy allows to continue the tracked entry, the one whose track advance matches the stream advance (the smallest seam drift, ties broken by coverage). A real playing therefore keeps accumulating through repeated regions instead of hopping to a copy, and the policy only has to judge the chunks that have no continuing candidate. In the replay of the full program against itself, the combination produced one result entry covering 1,708.5 of 1,709 seconds; the selection rule alone produced 27 fragments, and the default policy alone produced the 217 seconds described above.
- Jumps backwards are not governed by the policy. They are handled before it: a chunk that rewinds behind the accumulated coverage by more than one fingerprint plus the permitted gap starts a new result entry.
- The policy decides per seam. It does not merge result entries after the fact.