Description: I’m developing a tvOS app using SwiftUI where we play background audio (music) in the Welcome screen, with support for offline playback via local caching.
Feature Overview:
- App fetches audio metadata from API
- Starts streaming audio (HLS .m3u8) immediately
- In parallel, downloads the raw audio file (.mp3)
- Once download completes:
- Switches playback from streaming → local file
- On next launch (offline mode), app plays audio from local storage
Issue: This flow works perfectly on the Simulator, but on a real Apple TV device:
- Audio plays for a few seconds (2–5 sec) and then stops
- Especially after switching from streaming → local file
- No explicit AVPlayer error is logged
- Playback sometimes stops after UI updates or periodic API refresh
Implementation Details:
- Using AVPlayer with AVPlayerItem
- Background audio controlled via a shared manager (singleton)
- Files stored locally using FileManager (currently using .cachesDirectory)
- Switching playback using:
player.replaceCurrentItem(with: AVPlayerItem(url: localURL)) player.play()
Observations:
- Works reliably on Simulator
- On device: -- Playback stops silently -- Seems related to lifecycle, buffering, or file access
- No issues when continuously streaming (without switching to local)
Questions:
- Is there any limitation or known issue with AVPlayer when switching from streaming (HLS) to local file playback on tvOS?
- Are there specific requirements for playing locally cached media files on tvOS (e.g., file location, permissions, or sandbox behavior)?
- What is the recommended storage location and size limit for cached media files on tvOS?
- We understand tvOS has limited persistent storage
- Is .cachesDirectory the correct approach for this use case?
- Are there known differences in AVPlayer behavior between Simulator and real Apple TV devices (especially regarding buffering or lifecycle)?
- What is the recommended approach for implementing offline background audio on tvOS apps?
Goal: We want to implement a reliable system where:
- Audio streams initially
- Seamlessly switches to local file after download
- Continues playing without interruption
- Supports offline playback on subsequent launches
Any guidance or best practices would be greatly appreciated.
Thank you!