iOS 0.5.46: do not live-trim F1/VOD HLS playlists (replay stalled after ~12s).

This commit is contained in:
Jos Vooges | STH 2026-09-28 00:37:59 +02:00
parent 622e2cdb56
commit 42c856eb47
3 changed files with 22 additions and 13 deletions

View file

@ -345,7 +345,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 58;
CURRENT_PROJECT_VERSION = 59;
DEVELOPMENT_TEAM = X25NYX3K49;
ENABLE_BITCODE = NO;
ENABLE_PREVIEWS = YES;
@ -360,7 +360,7 @@
"$(inherited)",
"@executable_path/Frameworks"
);
MARKETING_VERSION = 0.5.45;
MARKETING_VERSION = 0.5.46;
OTHER_LDFLAGS = ("$(inherited)", "-ObjC");
PRODUCT_BUNDLE_IDENTIFIER = nl.vonas.mediacluster.ios;
PRODUCT_NAME = "$(TARGET_NAME)";
@ -378,7 +378,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 58;
CURRENT_PROJECT_VERSION = 59;
DEVELOPMENT_TEAM = X25NYX3K49;
ENABLE_BITCODE = NO;
ENABLE_PREVIEWS = YES;
@ -393,7 +393,7 @@
"$(inherited)",
"@executable_path/Frameworks"
);
MARKETING_VERSION = 0.5.45;
MARKETING_VERSION = 0.5.46;
OTHER_LDFLAGS = ("$(inherited)", "-ObjC");
PRODUCT_BUNDLE_IDENTIFIER = nl.vonas.mediacluster.ios;
PRODUCT_NAME = "$(TARGET_NAME)";

View file

@ -674,6 +674,7 @@ final class ClearKeyDashProxy {
var mediaSequence: Int?
var targetDuration: Int = 6
var hasEndList = false
var playlistType: String?
for line in lines {
let trimmed = line.trimmingCharacters(in: .whitespaces)
@ -681,7 +682,8 @@ final class ClearKeyDashProxy {
continue
}
if trimmed.hasPrefix("#EXT-X-PLAYLIST-TYPE:") {
// EVENT met uren history → AVPlayer start verkeerd / audio-only. Behandel als live.
playlistType = trimmed.split(separator: ":").last
.map { String($0).trimmingCharacters(in: .whitespaces).uppercased() }
continue
}
if trimmed.hasPrefix("#EXT-X-MEDIA-SEQUENCE:") {
@ -727,27 +729,34 @@ final class ClearKeyDashProxy {
}
}
// Live-edge window: ~12–16 segmenten (±60–90s bij 5–6s ESPN, ±40–60s bij 3.8s).
// Live-edge alleen voor echte live (ESPN). F1-replays / VOD hebben ENDLIST of
// een lange statische lijst: trim + START=-12 + geen ENDLIST → ~12s beeld, dan vast.
let host = (playlistURL.host ?? "").lowercased()
let isComplete = hasEndList || playlistType == "VOD"
let isF1 = host.contains("formula1.com")
let keep = 14
let startIdx: Int
let seqBase = mediaSequence ?? 0
if !hasEndList, segments.count > keep {
startIdx = segments.count - keep
} else if segments.count > 40 {
// VOD/EVENT-achtig met enorme history: toch trimmen naar einde.
if isComplete || isF1 {
startIdx = 0
} else if segments.count > keep {
startIdx = segments.count - keep
} else {
startIdx = 0
}
let window = Array(segments.suffix(from: startIdx))
let seq = seqBase + startIdx
proxyLog.info("hls rewrite segs=\(segments.count, privacy: .public) keep=\(window.count, privacy: .public) endlist=\(hasEndList, privacy: .public) type=\(playlistType ?? "-", privacy: .public) f1=\(isF1, privacy: .public) startIdx=\(startIdx, privacy: .public)")
out.append("#EXTM3U")
out.append("#EXT-X-VERSION:7")
out.append("#EXT-X-TARGETDURATION:\(targetDuration)")
out.append("#EXT-X-MEDIA-SEQUENCE:\(seq)")
out.append("#EXT-X-INDEPENDENT-SEGMENTS")
// Live-achtig: start dicht bij einde.
if isComplete {
out.append("#EXT-X-PLAYLIST-TYPE:VOD")
}
// Live-achtig: start dicht bij einde. Nooit op een complete/F1-replay.
if startIdx > 0 {
out.append("#EXT-X-START:TIME-OFFSET=-12.0,PRECISE=YES")
}
@ -763,7 +772,7 @@ final class ClearKeyDashProxy {
let resolved = join(base: asDirectory(playlistURL.deletingLastPathComponent()), relative: seg.uri)
out.append(proxyAbsoluteURL(resolved, lane: lane))
}
if hasEndList && startIdx == 0 {
if isComplete {
out.append("#EXT-X-ENDLIST")
}
return out.joined(separator: "\n")

View file

@ -96,7 +96,7 @@ struct SettingsScreen: View {
Section("Info") {
LabeledContent("App", value: "VMC iOS")
LabeledContent("Versie", value: "0.5.45")
LabeledContent("Versie", value: "0.5.46")
LabeledContent("Live TV", value: app.iptvEnabled ? "Aan" : "Uit")
LabeledContent("Events", value: app.eventsEnabled ? "Aan" : "Uit")
}