- reload introdb API key on setting updates - support recap/preview markers in playback and next-episode flow - add profile defaults for recap and preview auto-play settings
110 lines
3.7 KiB
Go
110 lines
3.7 KiB
Go
package markers
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/Silo-Server/silo-server/internal/models"
|
|
)
|
|
|
|
// CanWriteMarker reports whether a new marker write should be accepted given
|
|
// the existing source/confidence. A strictly higher-priority source always
|
|
// wins; an equal-priority source wins only if its confidence is strictly
|
|
// higher than what's already stored. Unknown/empty existing source is treated
|
|
// as priority zero so any defined source can replace it.
|
|
func CanWriteMarker(existingSource *string, existingConfidence *float64, newSource string, newConfidence *float64) bool {
|
|
currentSource := ""
|
|
if existingSource != nil {
|
|
currentSource = *existingSource
|
|
}
|
|
existingPriority := models.MarkerSourcePriority(currentSource)
|
|
newPriority := models.MarkerSourcePriority(newSource)
|
|
if newPriority > existingPriority {
|
|
return true
|
|
}
|
|
if newPriority < existingPriority {
|
|
return false
|
|
}
|
|
if existingConfidence != nil && newConfidence != nil {
|
|
return *newConfidence > *existingConfidence
|
|
}
|
|
return false
|
|
}
|
|
|
|
// MarkerUpdatePayload is the storage-agnostic shape produced from a provider
|
|
// Result. Repositories convert it into their concrete write column set.
|
|
// Pointer fields are nil when the result didn't carry that segment kind.
|
|
type MarkerUpdatePayload struct {
|
|
IntroStart, IntroEnd *float64
|
|
CreditsStart, CreditsEnd *float64
|
|
RecapStart, RecapEnd *float64
|
|
PreviewStart, PreviewEnd *float64
|
|
Source string
|
|
Provider *string
|
|
Confidence *float64
|
|
Algorithm string
|
|
}
|
|
|
|
// HasAnySegment reports whether the payload carries at least one segment
|
|
// range. Callers can short-circuit empty writes without touching the DB.
|
|
func (p MarkerUpdatePayload) HasAnySegment() bool {
|
|
return p.IntroStart != nil || p.IntroEnd != nil ||
|
|
p.CreditsStart != nil || p.CreditsEnd != nil ||
|
|
p.RecapStart != nil || p.RecapEnd != nil ||
|
|
p.PreviewStart != nil || p.PreviewEnd != nil
|
|
}
|
|
|
|
// BuildUpdatePayload converts a provider Result into the storage payload.
|
|
// All four segment kinds in the result map to the corresponding *Start/*End
|
|
// pointer pair; absent kinds remain nil. The Result's Algorithm field is
|
|
// authoritative; the falls back to `external:<source>` if absent so writes
|
|
// always carry an algorithm tag for provenance.
|
|
//
|
|
// Confidence: the highest per-marker confidence in the result is promoted to
|
|
// the shared write-time confidence. Per-segment confidence values are not
|
|
// preserved individually — the write path uses a single confidence per
|
|
// upsert, and providers today return uniform confidence across all segments
|
|
// of a single fetch.
|
|
func BuildUpdatePayload(result Result) MarkerUpdatePayload {
|
|
payload := MarkerUpdatePayload{
|
|
Source: result.SourceClass,
|
|
Algorithm: result.Algorithm,
|
|
}
|
|
if payload.Algorithm == "" && payload.Source != "" {
|
|
payload.Algorithm = "external:" + payload.Source
|
|
}
|
|
if provider := strings.TrimSpace(result.ProviderID); provider != "" {
|
|
payload.Provider = &provider
|
|
}
|
|
|
|
var maxConfidence float64
|
|
for _, m := range result.Markers {
|
|
start := m.Start.Seconds()
|
|
end := m.End.Seconds()
|
|
if end <= start {
|
|
continue
|
|
}
|
|
startPtr, endPtr := start, end
|
|
switch m.Kind {
|
|
case MarkerKindIntro:
|
|
payload.IntroStart = &startPtr
|
|
payload.IntroEnd = &endPtr
|
|
case MarkerKindCredits:
|
|
payload.CreditsStart = &startPtr
|
|
payload.CreditsEnd = &endPtr
|
|
case MarkerKindRecap:
|
|
payload.RecapStart = &startPtr
|
|
payload.RecapEnd = &endPtr
|
|
case MarkerKindPreview:
|
|
payload.PreviewStart = &startPtr
|
|
payload.PreviewEnd = &endPtr
|
|
}
|
|
if m.Confidence > maxConfidence {
|
|
maxConfidence = m.Confidence
|
|
}
|
|
}
|
|
if maxConfidence > 0 {
|
|
payload.Confidence = &maxConfidence
|
|
}
|
|
return payload
|
|
}
|