Skip to content

Conversation

@tahakocal
Copy link

Problem

When playing HLS (m3u8) streams, audio doesn't start automatically on the first play() call. The player reports a "playing" state, but no audio is heard. Pausing and playing again makes audio work.

Root Cause

When play() is called:

  1. playWhenReady is set to true
  2. applyAVPlayerRate() is called to set the AVPlayer rate
  3. But AVPlayerItem.status is still .unknown at this point
  4. AVPlayer ignores rate changes when the item status is not .readyToPlay

Later, when the item becomes ready (status = .readyToPlay), nothing triggers playback because status changes were not being observed.

Solution

This PR adds observation of AVPlayerItem.status:

  1. AVPlayerItemObserver.swift: Added status to the observed keypaths and a new delegate method item(didUpdateStatus:)
  2. AVPlayerWrapper.swift: Implemented the delegate method to call applyAVPlayerRate() when status becomes .readyToPlay and playWhenReady is true

Why This Works

Timeline before fix:
play() called → playWhenReady=true → applyRate() → item.status=.unknown → ❌ No audio

Timeline after fix:
play() called → playWhenReady=true → applyRate() → item.status=.unknown → (no audio yet)
→ item.status=.readyToPlay → applyRate() → ✅ Audio plays!

Testing
Tested with:

  • HLS streams (m3u8)
  • MP3 files (no regression)
  • Various network conditions

References
From Apple's WWDC 2016 session on AVFoundation:
"You should observe the status property of AVPlayerItem and only begin playback when status is .readyToPlay"

When playing HLS streams, audio doesn't start on first play() call
because AVPlayerItem.status is still .unknown at that point.
AVPlayer ignores rate changes when item is not ready.

This fix adds observation of AVPlayerItem.status. When status becomes
.readyToPlay and playWhenReady is true, we call applyAVPlayerRate()
to start playback.

Problem:
1. play() is called -> playWhenReady = true
2. applyAVPlayerRate() sets rate, but item.status is .unknown
3. AVPlayer ignores the rate change
4. Item becomes .readyToPlay but nothing triggers playback
5. Audio doesn't play until pause/play cycle

Solution:
1. Observe AVPlayerItem.status changes
2. When status becomes .readyToPlay and playWhenReady is true
3. Call applyAVPlayerRate() to start actual playback

This is consistent with Apple's guidance from WWDC 2016:
"Observe the status property of AVPlayerItem and only begin
playback when status is .readyToPlay"

Fixes HLS streams not auto-starting on iOS.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant