I am growing an iOS radio app that performs numerous HLS streams. The problem is that some stations broadcast HLS streams containing each audio and video (instance: https://svs.itworkscdn.internet/smcwatarlive/smcwatar/chunks.m3u8), however I wish to:
Extract and play solely the audio observe
Assist AirPlay for audio-only streaming
Decrease information utilization by not downloading video content material
Technical Particulars:
iOS 17+
Swift 6
Utilizing AVFoundation for playback
Present implementation makes use of AVPlayer with AVPlayerItem
Present Code Construction:
class StreamPlayer: ObservableObject { @Revealed var isPlaying = false non-public var participant: AVPlayer? non-public var playerItem: AVPlayerItem?
func playStream(url: URL) {
let asset = AVURLAsset(url: url)
playerItem = AVPlayerItem(asset: asset)
participant = AVPlayer(playerItem: playerItem)
participant?.play()
}
Stream Evaluation: When analyzing the video stream utilizing FFmpeg:
CopyInput #0, hls, from 'https://svs.itworkscdn.internet/smcwatarlive/smcwatar/chunks.m3u8':
Stream #0:0: Video: h264, yuv420p(television, bt709), 1920x1080 [SAR 1:1 DAR 16:9], 25 fps
Stream #0:1: Audio: aac, 44100 Hz, stereo, fltp
Tried Options:
Utilizing MobileFFmpeg:
let command = [
"-i", streamUrl,
"-vn",
"-acodec", "aac",
"-ac", "2",
"-ar", "44100",
"-b:a", "128k",
"-f", "mpegts",
"udp://127.0.0.1:12345"
].joined(separator: " ")
ffmpegProcess = MobileFFmpeg.execute(command)
I
ssue: Whereas FFmpeg efficiently extracts audio, playback by way of AVPlayer does not work reliably.
Tried utilizing HLS output:
let command = [
"-i", streamUrl,
"-vn",
"-acodec", "aac",
"-ac", "2",
"-ar", "44100",
"-b:a", "128k",
"-f", "hls",
"-hls_time", "2",
"-hls_list_size", "3",
outputUrl.path
]
Challenge: Creates short-term recordsdata however faces synchronization points with dwell streams.
Testing URLs:
Audio+Video: https://svs.itworkscdn.internet/smcwatarlive/smcwatar/chunks.m3u8
Audio Solely: https://mbcfm-radio.mbc.internet/mbcfm-radio.m3u8
Necessities:
- Actual-time audio extraction from HLS stream
- Preserve dwell streaming capabilities
- Full AirPlay assist
- Minimal information utilization (keep away from downloading video content material)
- Deal with community interruptions gracefully
Questions:
- What’s essentially the most environment friendly approach to extract solely audio from an HLS stream in real-time?
- Is there a approach to inform AVPlayer to disregard video tracks utterly?
- Are there higher options to FFmpeg for this particular use case?
- What is the advisable method for dealing with AirPlay with modified streams?
Any steerage or various approaches could be significantly appreciated. Thanks!
What I Tried:
- Direct AVPlayer Implementation:
- Used normal AVPlayer to play HLS stream
- Anticipated it to permit deciding on audio-only tracks
- Consequence: All the time downloads each video and audio, consuming pointless bandwidth
- FFmpeg Audio Extraction:
let command = [
"-i", "https://svs.itworkscdn.net/smcwatarlive/smcwatar/chunks.m3u8",
"-vn", // Remove video
"-acodec", "aac", // Audio codec
"-ac", "2", // 2 channels
"-ar", "44100", // Sample rate
"-b:a", "128k", // Bitrate
"-f", "mpegts", // Output format
"udp://127.0.0.1:12345" // Local stream
]
ffmpegProcess = MobileFFmpeg.execute(command)
Anticipated: Clear audio stream that AVPlayer might play
Consequence: FFmpeg extracts audio however AVPlayer cannot play the UDP stream
- HLS Segmented Strategy:
swiftCopylet command = [
"-i", streamUrl,
"-vn",
"-acodec", "aac",
"-f", "hls",
"-hls_time", "2",
"-hls_list_size", "3",
outputUrl.path
]
Anticipated: Create native HLS playlist with audio-only segments
Consequence: Creates recordsdata however faces sync points with dwell stream
Anticipated Habits:
- Stream performs audio solely
- Minimal information utilization (no video obtain)
- Working AirPlay assist
- Actual-time playback with out delays
Precise Outcomes:
- Both downloads full video stream (wasteful)
- Or fails to play extracted audio
- AirPlay points with modified streams
- Sync issues with dwell content material