Improve stream quality: stop capping resolution, allow AVPlayer to ramp
SingleStream: pass preserveServerResolutionWhenBest=false so "best" always reaches the server for a full multi-variant manifest. Increase buffer to 8s and enable automaticallyWaitsToMinimizeStalling so AVPlayer can measure bandwidth and select higher variants. Add quality monitor that nudges AVPlayer if observed bandwidth far exceeds indicated bitrate. MultiStream: remove broken URL-param resolution detection that falsely skipped upgrades, log actual indicatedBitrate instead. Extend upgrade check windows from [2,4,7]s to [2,4,7,15,30]s for slow-to-stabilize streams. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -702,7 +702,7 @@ private struct MultiStreamTile: View {
|
||||
let streamID = stream.id
|
||||
let label = stream.label
|
||||
qualityUpgradeTask = Task { @MainActor in
|
||||
let checkDelays: [Double] = [2.0, 4.0, 7.0]
|
||||
let checkDelays: [Double] = [2.0, 4.0, 7.0, 15.0, 30.0]
|
||||
|
||||
for delay in checkDelays {
|
||||
try? await Task.sleep(for: .seconds(delay))
|
||||
@@ -715,20 +715,15 @@ private struct MultiStreamTile: View {
|
||||
let itemStatus = multiViewItemStatusDescription(player.currentItem?.status ?? .unknown)
|
||||
let likelyToKeepUp = player.currentItem?.isPlaybackLikelyToKeepUp ?? false
|
||||
let bufferEmpty = player.currentItem?.isPlaybackBufferEmpty ?? false
|
||||
let currentResolution = currentStreamResolution(for: player) ?? "unknown"
|
||||
let indicatedBitrate = player.currentItem?.accessLog()?.events.last?.indicatedBitrate ?? 0
|
||||
let stable = (itemStatus == "readyToPlay" || likelyToKeepUp) && !bufferEmpty
|
||||
|
||||
logMultiView(
|
||||
"qualityUpgrade check id=\(streamID) delay=\(delay)s currentResolution=\(currentResolution) targetResolution=\(targetResolution) stable=\(stable) rate=\(player.rate)"
|
||||
"qualityUpgrade check id=\(streamID) delay=\(delay)s targetResolution=\(targetResolution) stable=\(stable) rate=\(player.rate) indicatedBitrate=\(Int(indicatedBitrate))"
|
||||
)
|
||||
|
||||
guard stable else { continue }
|
||||
|
||||
if currentResolution == targetResolution {
|
||||
logMultiView("qualityUpgrade skip id=\(streamID) reason=already-\(targetResolution)")
|
||||
return
|
||||
}
|
||||
|
||||
guard let upgradedURL = await viewModel.resolveStreamURL(
|
||||
for: stream,
|
||||
resolutionOverride: targetResolution,
|
||||
@@ -764,13 +759,6 @@ private struct MultiStreamTile: View {
|
||||
(player.currentItem?.asset as? AVURLAsset)?.url
|
||||
}
|
||||
|
||||
private func currentStreamResolution(for player: AVPlayer) -> String? {
|
||||
guard let url = currentStreamURL(for: player) else { return nil }
|
||||
return URLComponents(url: url, resolvingAgainstBaseURL: false)?
|
||||
.queryItems?
|
||||
.first(where: { $0.name == "resolution" })?
|
||||
.value
|
||||
}
|
||||
|
||||
private func installClipTimeLimit(on player: AVPlayer) {
|
||||
removeClipTimeLimit(from: player)
|
||||
|
||||
Reference in New Issue
Block a user