You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Field log from AetherPlayer 0.18.1 (69), iPhone 17 Pro, iOS 27.0 (24A435), engine 7.5.0.
A software-path session was playing when the viewer started AirPlay. The route switch arrived as an audio session interruption. The resume fired, and playback never came back: the master clock stopped and stayed stopped for the remaining two minutes of the log.
11:08:08.123 [AetherEngine] AVAudioSession interruption BEGAN reason=0 resumeArmed=true otherAudio=false silenceHint=false
11:08:08.134 [SWDiag] clk=10.81 dclk=1.00 aLead=4.00 vLead=0.32 parkedPkts=83 enq=+24 disp=+24
11:08:09.135 [SWDiag] clk=10.81 dclk=0.00 aLead=4.00 vLead=0.37 parkedPkts=82 enq=+1 disp=+1
11:08:18.360 [AetherEngine] AVAudioSession interruption ENDED shouldResume=true otherAudio=true resumeArmed=true autoResume=true
11:08:20.884 [SWDiag] clk=10.81 dclk=0.00 aLead=4.00 vLead=3.79 parkedPkts=0 enq=+0 disp=+0
...identical every second until the log ends at 11:09:00
autoResume=true is the engine stating that it called play(). clk never moved again, dclk stayed at 0.00, and the demux loop drained its parked packets and then stood still with 3.79 s of decoded video in hand.
Why
The interruption path and the resume it drives were written for the native path, where AVPlayer owns both the audio session and the clock and AVFoundation restores them. The renderer paths (SoftwarePlaybackHost, AudioPlaybackHost) own both themselves, and nothing on them recovers. Three gaps, all in the same direction:
play() cannot start a clock the host did not stop.SoftwarePlaybackHost.play() re-rates the synchronizer only inside if pausedByHost (AudioPlaybackHost.play() is identical). A system interruption never goes through pause(), so the flag is false and the resume is a no-op on the clock by construction. The guard itself is right for a host pause (AU live tv #107: never rate-change an un-anchored synchronizer); what is missing is any other door.
The audio session is activated once per load and never again.applyRendererAudioSession (AetherEngine+Loading.swift) is the only setActive(true) in the repo. After an interruption ends the app has to reactivate its own session; on these paths no one does. The log has exactly one renderer audio session active: line, at load, and none after the resume.
The renderer's automatic flush is not observed.AVSampleBufferAudioRenderer flushes itself on an interruption and posts wasFlushedAutomaticallyNotification carrying the flush time, which is the documented signal to re-anchor and re-enqueue from there. There is no reference to it anywhere in Sources/. aLead=4.00 right up to the freeze and parkedPkts draining to zero afterwards is consistent with the queued lead having been thrown away.
There is also no AVAudioSession.routeChangeNotification observer in the engine at all, which is the other door the same event can arrive through.
Scope
Every renderer-path session on iOS, not only AirPlay: a phone call, Siri, or any other interruption should wedge the same way, and audio-only sessions carry the identical play() shape. The native path is unaffected, AVPlayer restores itself. tvOS sees interruptions far less often but the code path is shared.
Repro
No AirPlay needed: play a source that routes software (any forward-only HTTP source will do, or --sw), take a phone call, hang up. Expected: playback resumes. Observed shape: the clock never restarts and the picture freezes with the audio silent.
Reported on Discord (AirPlay half of the same report is filed separately).
Field log from AetherPlayer 0.18.1 (69), iPhone 17 Pro, iOS 27.0 (24A435), engine 7.5.0.
A software-path session was playing when the viewer started AirPlay. The route switch arrived as an audio session interruption. The resume fired, and playback never came back: the master clock stopped and stayed stopped for the remaining two minutes of the log.
autoResume=trueis the engine stating that it calledplay().clknever moved again,dclkstayed at 0.00, and the demux loop drained its parked packets and then stood still with 3.79 s of decoded video in hand.Why
The interruption path and the resume it drives were written for the native path, where AVPlayer owns both the audio session and the clock and AVFoundation restores them. The renderer paths (
SoftwarePlaybackHost,AudioPlaybackHost) own both themselves, and nothing on them recovers. Three gaps, all in the same direction:play()cannot start a clock the host did not stop.SoftwarePlaybackHost.play()re-rates the synchronizer only insideif pausedByHost(AudioPlaybackHost.play()is identical). A system interruption never goes throughpause(), so the flag is false and the resume is a no-op on the clock by construction. The guard itself is right for a host pause (AU live tv #107: never rate-change an un-anchored synchronizer); what is missing is any other door.The audio session is activated once per load and never again.
applyRendererAudioSession(AetherEngine+Loading.swift) is the onlysetActive(true)in the repo. After an interruption ends the app has to reactivate its own session; on these paths no one does. The log has exactly onerenderer audio session active:line, at load, and none after the resume.The renderer's automatic flush is not observed.
AVSampleBufferAudioRendererflushes itself on an interruption and postswasFlushedAutomaticallyNotificationcarrying the flush time, which is the documented signal to re-anchor and re-enqueue from there. There is no reference to it anywhere inSources/.aLead=4.00right up to the freeze andparkedPktsdraining to zero afterwards is consistent with the queued lead having been thrown away.There is also no
AVAudioSession.routeChangeNotificationobserver in the engine at all, which is the other door the same event can arrive through.Scope
Every renderer-path session on iOS, not only AirPlay: a phone call, Siri, or any other interruption should wedge the same way, and audio-only sessions carry the identical
play()shape. The native path is unaffected, AVPlayer restores itself. tvOS sees interruptions far less often but the code path is shared.Repro
No AirPlay needed: play a source that routes software (any forward-only HTTP source will do, or
--sw), take a phone call, hang up. Expected: playback resumes. Observed shape: the clock never restarts and the picture freezes with the audio silent.Reported on Discord (AirPlay half of the same report is filed separately).