#+TITLE: AAC Streaming Support #+AUTHOR: Asteroid Radio Development Team #+DATE: 2025-10-01 #+STARTUP: overview * Overview This branch adds AAC (Advanced Audio Coding) streaming support to Asteroid Radio, providing better audio quality at lower bitrates. * Features Added ** 🎵 Multiple Stream Formats - *AAC 96kbps* - High quality, efficient compression (recommended) - *MP3 128kbps* - Standard quality, maximum compatibility - *MP3 64kbps* - Low bandwidth option ** 🌐 Web Interface Updates - *Stream quality selector* on both front page and player page - *Dynamic stream switching* without page reload - *AAC set as default* (recommended option) ** ⚙️ Technical Implementation - *Liquidsoap real-time transcoding* from MP3 files to AAC - *FDK-AAC encoder* via =%fdkaac()= function - *Existing Docker image* =savonet/liquidsoap:792d8bf= already includes AAC support * Stream URLs When running, the following streams will be available: #+BEGIN_EXAMPLE High Quality AAC: http://localhost:8000/asteroid.aac High Quality MP3: http://localhost:8000/asteroid.mp3 Low Quality MP3: http://localhost:8000/asteroid-low.mp3 #+END_EXAMPLE * Benefits of AAC ** Quality Comparison - 96kbps AAC ≈ 128kbps MP3 quality - Better handling of complex audio (orchestral, electronic) - More transparent compression (fewer artifacts) ** Bandwidth Savings - *25% less bandwidth* than equivalent MP3 quality - 96kbps AAC = 43.2 MB/hour per user (vs 57.6 MB/hour for 128kbps MP3) - Significant cost savings for streaming infrastructure ** Modern Standard - Used by Apple Music, YouTube, most streaming services - Better mobile device support - Future-proof codec choice * Browser Support AAC streaming is supported by all modern browsers: - ✅ Chrome/Edge (native support) - ✅ Firefox (native support) - ✅ Safari (native support) - ✅ Mobile browsers (iOS/Android) * Technical Details ** Liquidsoap Configuration The updated =asteroid-radio-docker.liq= now includes: #+BEGIN_SRC liquidsoap # AAC High Quality Stream (96kbps) output.icecast( %fdkaac(bitrate=96), host="icecast", port=8000, password="H1tn31EhsyLrfRmo", mount="asteroid.aac", name="Asteroid Radio (AAC)", description="Music for Hackers - High efficiency AAC stream", genre="Electronic/Alternative", url="http://localhost:8080/asteroid/", public=true, radio ) #+END_SRC ** Docker Configuration - Uses existing =savonet/liquidsoap:792d8bf= image (Liquidsoap 2.4.1+git) - FDK-AAC encoder already included and supported - No Docker image changes required - Maintains full backward compatibility with existing MP3 streams ** Web Interface Updates - Added stream quality selector with JavaScript switching - Maintains playback state when changing quality - AAC set as default recommended option * CPU Impact Real-time transcoding adds minimal CPU overhead: - *MP3 encoding*: ~10% CPU per stream - *AAC encoding*: ~15% CPU per stream - *Total impact*: ~25% CPU for all three streams on Hetzner CPX21 * Testing To test the AAC streaming: ** Build and start containers: #+BEGIN_SRC bash cd docker docker compose build docker compose up -d #+END_SRC ** Verify streams are available: #+BEGIN_SRC bash curl -I http://localhost:8000/asteroid.aac curl -I http://localhost:8000/asteroid.mp3 curl -I http://localhost:8000/asteroid-low.mp3 #+END_SRC ** Test web interface: - Visit http://localhost:8080/asteroid/ - Try different quality options in the dropdown - Verify smooth switching between formats * Future Enhancements - *Adaptive bitrate streaming* based on connection speed - *FLAC streaming* for audiophile users (premium feature) - *Opus codec support* for even better efficiency - *User preference storage* for stream quality * Bandwidth Calculations ** Phase 0 MVP with AAC (10 concurrent users): #+BEGIN_EXAMPLE AAC Primary (96kbps): 10 users × 43.2 MB/hour = 432 MB/hour Daily: 432 MB × 24h = 10.4 GB/day Monthly: ~312 GB/month (vs 414 GB with MP3 only) Savings: 25% reduction in bandwidth costs #+END_EXAMPLE This makes the AAC implementation particularly valuable for the cost-conscious MVP approach outlined in the scaling roadmap. --- *Branch*: =feature/aac-streaming= *Status*: COMPLETED - Production Ready *Next*: Merge to main after validation