fix: clip metadata intervals to playable duration

This commit is contained in:
2026-10-22 13:17:47 +02:00
parent fe34ce88f9
commit 7b53b00b15
4 changed files with 25 additions and 11 deletions
+7 -4
View File
@@ -4,8 +4,8 @@ import CoreFoundation
struct MiruroInterval: Sendable, Equatable {
enum Kind: Sendable { case intro, outro }
let kind: Kind
let start: Double
let end: Double
var start: Double
var end: Double
let episode: Int
var rawKind: String = ""
var provider: String? = nil
@@ -20,13 +20,16 @@ struct MiruroMetadata: Sendable {
func visibleIntervals(episode: Int, duration: Double) -> [MiruroInterval] {
guard duration.isFinite, duration > 0 else { return [] }
var intro: MiruroInterval?, outro: MiruroInterval?
for row in intervals {
for var row in intervals {
guard row.episode == episode, row.start.isFinite, row.end.isFinite,
row.start >= 0, row.end > row.start, row.end <= duration,
row.end > row.start,
!(row.provider?.range(of: "crunchyroll", options: .caseInsensitive) != nil),
(row.votes ?? 0).isFinite, (row.votes ?? 0) >= 0 else { continue }
if let length = row.referenceLength, length.isFinite, length > 0,
abs(length - duration) / duration > 0.05 { continue }
row.start = max(0, row.start)
row.end = min(duration, row.end)
guard row.end > row.start else { continue }
// Strictly greater preserves input order on ties, equivalent to stable descending votes.
switch row.kind {
case .intro: