Audiobooks are challenging content: 15-hour files, unstable connections, users demanding precise position resumption. A typical bug is the player losing progress when switching between Wi-Fi and LTE, and the sleep timer cutting off a chapter without fade-out. We solved this at the architecture level: aggressive caching via URLSession background tasks, position synchronization with cloud storage every 5 seconds, and smooth volume fade before stopping. Result: the app doesn't crash, positions are saved, users don't complain.
File Formats and Streaming Playback
Audiobooks come mostly in MP3 (widest), M4B (AAC with chapter markers, Apple standard), M4A, and OGG/Opus. M4B is preferred for new catalogs—it natively contains chapters, cover art, and metadata without a sidecar.
Streaming playback (no full download before play): on iOS, AVPlayer opens an HTTP URL and starts playing without full load. On Android, ExoPlayer (Media3) does the same via DefaultDataSource.Factory. For long files (15 hours ≈ 800 MB), this is critical.
Chapters from M4B: AVAsset.loadChapterMetadataGroups(bestMatchingPreferredLanguages:) returns AVTimedMetadataGroup[] with timestamps and titles. On Android, use MediaMetadataRetriever.extractMetadata plus parsing MP4 box structure for chapter atoms, or use ExoPlayer with a custom MetadataRetriever.
Why M4B Is Best for New Catalogs
M4B uses the MP4 container with built-in chapter markers, simplifying navigation and metadata storage. Unlike MP3, no external chapter file is needed. During streaming, the client immediately gets the book structure.
Precise Position Saving
A user listens in the car, closes the app—next opening must resume exactly at that spot, to the second.
We save currentTime (Double, seconds) plus bookId and timestamp to UserDefaults/SharedPreferences on every background transition (applicationDidEnterBackground) and via a Timer every 5 seconds during playback. The timer runs every 5 seconds, not every second—that's overkill.
On restore: player.seek(to: CMTime(seconds: savedPosition, preferredTimescale: 1000)) with .seconds precision. Not MSEC—audio doesn't need it.
Multi-device sync: CloudKit CKRecord (iOS) or Firebase Firestore with userId/bookId key. When opening the book on a new device, we offer "Continue from 1:23:45"—the user decides.
How to Ensure Seamless Sync?
We use cloud storage with a "last write wins" conflict resolution. On each position save, we send a request to Firestore/CloudKit with a timestamp. When loading the book on another device, we compare timestamps and pick the latest. Additionally, we keep a local cache for offline scenarios.
Sleep Timer
A popular feature: playback stops after N minutes. Trivial: DispatchQueue.main.asyncAfter (iOS) or Handler.postDelayed (Android). Advanced variant: "stop at end of current chapter"—we get the endTime of the current chapter from metadata and schedule the stop at that time.
Smooth fade-out before stop: 30 seconds before the end, we linearly decrease player.volume to 0 via CADisplayLink / ValueAnimator. No abrupt stop—that annoys users.
Technical details of smooth fade-out
We use a timer at 60 FPS (CADisplayLink on iOS, Choreographer on Android). Each update reduces volume by (1/60)*(1/30) ≈ 0.00056. On reaching the stop time, we pause the player and restore volume to the original for subsequent playback.Playback Speed and Pitch Correction
player.rate = 1.5 (AVPlayer) speeds up playback but raises pitch—the voice becomes squeaky. iOS automatically applies pitch correction for AVPlayer when rate ≠ 1.0 since iOS 16. On older versions, use AVAudioUnitTimePitch in an AVAudioEngine pipeline.
Android ExoPlayer: playbackParameters = PlaybackParameters(speed = 1.5f) — pitch correction built-in. Flutter just_audio: player.setSpeed(1.5) with default pitchCorrectionMethod.
Useful speed range: 0.75x (for complex technical content), 1.0x, 1.25x, 1.5x, 2.0x. Above 2x, intelligibility drops critically.
| Speed | Use Case | Pitch Correction |
|---|---|---|
| 0.75x | Technical content | Auto |
| 1.0x | Standard | None |
| 1.25x | Accelerated listening | Yes |
| 1.5x | Fast reading | Yes |
| 2.0x | Intelligibility limit | Yes |
"For audio playback, AVPlayer applies pitch correction when the rate is not 1.0." — Apple AVPlayer documentation.
Offline Download and DRM
Offline download uses URLSessionDownloadTask + URLSessionConfiguration.background (iOS): works even when the app is not running, progress survives crashes. Android: WorkManager + DownloadManager or OkHttp with custom progress.
For paid content, DRM is required. FairPlay Streaming (iOS) integrates with AVContentKeySession. Widevine L3 (Android) uses ExoPlayer with DefaultDrmSessionManager. The encryption key is requested from the license server on each playback. Without DRM, users can copy the file from /Library/Application Support and listen without a subscription.
Alternative without full DRM: AES-256 file encryption on disk with a key tied to the account and DeviceID. Cheaper to implement, but less protection.
| DRM | iOS | Android |
|---|---|---|
| FairPlay Streaming | AVContentKeySession | — |
| Widevine L3 | — | ExoPlayer + DrmSessionManager |
| AES-256 self-managed | CommonCrypto | Android Keystore |
Catalog and Search
User library: purchased and downloaded books. Store catalog: search, genres, new releases, recommendations. Pagination via cursor (Alchemy-style next token or offset/limit). Covers via SDWebImage/Coil/cached_network_image with aggressive disk cache (covers change rarely).
What's Included in the Work
- Source code of the app (iOS/Android) with comments.
- API documentation and database schema.
- Access to App Store Connect / Google Play Console.
- Team training for the client (2-3 sessions).
- 3 months of technical support after release.
- Integration with existing backend or setup of a new one.
| Feature | MVP | Full Version |
|---|---|---|
| MP3/M4B playback | yes | yes |
| Chapters and navigation | no | yes |
| Offline download | no | yes |
| Position sync | no | yes |
| DRM | no | yes |
| Sleep timer | yes | yes |
Timeline: MVP player with catalog and basic playback — 3-4 weeks. Full product with DRM, offline, sync, and subscription — 8-12 weeks. Savings on DRM licenses when using self-managed AES-256 can reach 30%.
Want to discuss your project? Contact us for an architecture assessment and optimal solution. Order turnkey audiobook app development.







