Add AudioDiagnostics heartbeat logging
Adds [AUDIO]-prefixed logs to both single-stream and multi-stream players: 1 Hz heartbeat with rate/timeControl/mute/volume/bitrate/route, plus immediate events on rate, isMuted, volume, currentItem, media selection, access-log, error-log, and system audio route/interruption changes. Grep Xcode console for `[AUDIO]` or `[AUDIO SYSTEM]` to isolate. Also reverts the AAC-preference in pinAudioSelection: the ballgame.treytartt.com master playlist is already all mp4a.40.2 stereo, so the Dolby-DRC theory doesn't fit. Pin simply selects the default audible option now. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -75,8 +75,7 @@ private func makeSingleStreamPlayerItem(from source: SingleStreamPlaybackSource)
|
||||
return item
|
||||
}
|
||||
|
||||
/// Lock the HLS audio rendition to the default option so ABR can't swap
|
||||
/// to a different channel layout / loudness mid-stream.
|
||||
/// Pin the HLS audio rendition so ABR can't swap channel layouts mid-stream.
|
||||
private func pinSingleStreamAudioSelection(on item: AVPlayerItem) {
|
||||
let asset = item.asset
|
||||
Task { @MainActor [weak item] in
|
||||
@@ -571,6 +570,10 @@ struct SingleStreamPlayerView: UIViewControllerRepresentable {
|
||||
logSingleStream("Configured player for quality ramp preferredForwardBufferDuration=8 automaticallyWaitsToMinimizeStalling=true")
|
||||
context.coordinator.attachDebugObservers(to: player, url: url, resolveNextSource: resolveNextSource)
|
||||
controller.player = player
|
||||
if context.coordinator.audioDiagnostics == nil {
|
||||
context.coordinator.audioDiagnostics = AudioDiagnostics(tag: "single")
|
||||
}
|
||||
context.coordinator.audioDiagnostics?.attach(to: player)
|
||||
logSingleStream("AVPlayer assigned to controller; calling playImmediately(atRate: 1.0)")
|
||||
player.playImmediately(atRate: 1.0)
|
||||
context.coordinator.installClipTimeLimit(on: player, resolveNextSource: resolveNextSource)
|
||||
@@ -602,6 +605,10 @@ struct SingleStreamPlayerView: UIViewControllerRepresentable {
|
||||
logSingleStream("dismantleUIViewController — PiP active, observers cleared but keeping player")
|
||||
return
|
||||
}
|
||||
Task { @MainActor in
|
||||
coordinator.audioDiagnostics?.detach()
|
||||
coordinator.audioDiagnostics = nil
|
||||
}
|
||||
uiViewController.player?.pause()
|
||||
uiViewController.player = nil
|
||||
logSingleStream("dismantleUIViewController complete")
|
||||
@@ -613,6 +620,7 @@ struct SingleStreamPlayerView: UIViewControllerRepresentable {
|
||||
private var startupRecoveryTask: Task<Void, Never>?
|
||||
private var qualityMonitorTask: Task<Void, Never>?
|
||||
private var clipTimeLimitObserver: Any?
|
||||
var audioDiagnostics: AudioDiagnostics?
|
||||
private static let maxClipDuration: Double = 15.0
|
||||
var onTogglePitchInfo: (() -> Void)?
|
||||
var onToggleGameCenter: (() -> Void)?
|
||||
|
||||
Reference in New Issue
Block a user