FRadioPlayer is a wrapper around AVPlayer to handle internet radio playback.
SwiftUI demo source lives under Example/FRadioPlayerDemo/.
Use XcodeGen to generate and open the demo project:
brew install xcodegen # once
cd Example
xcodegen # generates FRadioPlayerDemo.xcodeproj
open FRadioPlayerDemo.xcodeproj- Support internet radio URL playback
- Update and parse track metadata
- Update and show album artwork (via iTunes API)
- Automatic handling of interruptions
- Automatic handling of route changes
- Support bluetooth playback
- Network interruptions handling
- Automatic stall recovery with bounded retries (reload with backoff, clean error state when the stream is gone)
- Support for Swift Package Manager SPM
- iOS 14.0+
- macOS 11.0+
- tvOS 14.0+
- Xcode 15+
- Swift 5.9+
FRadioPlayer is available through SPM. To add it in Xcode: File > Add Packages… and use the URL of this repository. Or add the dependency in Package.swift:
.package(url: "https://github.com/fethica/FRadioPlayer.git", from: "0.3.0")Add the package, then use the shared player and observe changes.
import FRadioPlayer
final class RadioController: NSObject, FRadioPlayerObserver {
let player = FRadioPlayer.shared
override init() {
super.init()
player.addObserver(self)
player.enableArtwork = true // Optional (default true)
player.isAutoPlay = true // Optional (default true)
player.radioURL = URL(string: "https://your.station/stream.mp3")
// Or manually control playback: player.play()
}
func radioPlayer(_ player: FRadioPlayer, playerStateDidChange state: FRadioPlayer.State) {
print("Player state: \(state)")
}
}
// Elsewhere
FRadioPlayer.shared.togglePlaying() // Play/Pause
FRadioPlayer.shared.stop() // Stop
FRadioPlayer.shared.volume = 0.8 // Set volume (0.0...1.0)Prefer SPM. If needed, drag Sources/FRadioPlayer into your Xcode project.
- Import
FRadioPlayer
import FRadioPlayer- Get the singleton
FRadioPlayerinstance
let player = FRadioPlayer.shared- Observe player events (optional)
final class MyObserver: NSObject, FRadioPlayerObserver {
override init() {
super.init()
FRadioPlayer.shared.addObserver(self)
}
func radioPlayer(_ player: FRadioPlayer, playerStateDidChange state: FRadioPlayer.State) {
// handle state change
}
}- Set the radio URL
player.radioURL = URL(string: "http://example.com/station.mp3")isAutoPlay: BoolAuto-play whenradioURLis set (defaulttrue).enableArtwork: BoolFetch album artwork via iTunes API (defaulttrue).artworkAPI: FRadioArtworkAPIArtwork provider, defaultiTunesAPI(artworkSize: 300).rate: Float?CurrentAVPlayerrate.isPlaying: BoolConvenience read-only state.state: FRadioPlayer.StatePlayer state.playbackState: FRadioPlayer.PlaybackStatePlayback state.volume: Float?Player volume, 0.0…1.0.httpHeaderFields: [String:String]?HTTP headers for the underlyingAVURLAsset.metadataExtractor: FRadioMetadataExtractorStrategy to parse timed metadata.currentMetadata: FRadioPlayer.Metadata?Last parsed timed metadata.currentArtworkURL: URL?Last resolved artwork URL.duration: TimeIntervalTotal duration, 0 for live streams.currentTime: DoubleCurrent playback time in seconds.
- Play
player.play()- Pause
player.pause()- Stop
player.stop()- Toggle playing state
player.togglePlaying()- Player state
func radioPlayer(_ player: FRadioPlayer, playerStateDidChange state: FRadioPlayer.State)- Playback state
func radioPlayer(_ player: FRadioPlayer, playbackStateDidChange state: FRadioPlayer.PlaybackState)- Item change
func radioPlayer(_ player: FRadioPlayer, itemDidChange url: URL?)- Timed metadata
func radioPlayer(_ player: FRadioPlayer, metadataDidChange metadata: FRadioPlayer.Metadata?)- Artwork URL
func radioPlayer(_ player: FRadioPlayer, artworkDidChange artworkURL: URL?)- Duration and time updates
func radioPlayer(_ player: FRadioPlayer, durationDidChange duration: TimeInterval)
func radioPlayer(_ player: FRadioPlayer, playTimeDidChange currentTime: TimeInterval, duration: TimeInterval)For more complete app features, check out Swift Radio App based on FRadioPlayer
This repository uses Swift Package Manager for building and testing:
swift build
swift testThe test suite covers the public API contract, metadata extraction, the artwork API (stubbed, no network), playback against bundled fixtures, and state machine regressions. CI runs it on every push and pull request. Bug fixes should come with a failing test first.
FRadioPlayer is available under the MIT license. See the LICENSE file for more info.

