Cycast - Icecast-Compatible Streaming Server
A high-performance internet radio streaming server written in Python with Cython optimizations. Accepts live sources from Mixxx, VLC, or any Icecast-compatible source client and falls back to predefined playlists when no DJ is connected.
Modern Architecture:
- π Cython optimizations for 3-5x performance improvement
- π¨ Flask web application running on Tornado for production-grade performance
- π HCL configuration for human-friendly configuration files
- π΅ Beautiful web UI with real-time updates
- π RESTful API for status and statistics
Features
- Live Source Support: Accept streams from Mixxx, VLC, Virtual DJ, or any Icecast/Shoutcast source client
- Playlist Fallback: Automatically plays from a playlist when no live source is connected
- High Performance: Cython-optimized audio buffer and broadcaster for efficient streaming
- Multiple Listeners: Handle many simultaneous listeners efficiently with Tornado
- Web Status Page: Beautiful, responsive UI with real-time updates via AJAX
- RESTful API: JSON endpoints for status and statistics
- HCL Configuration: Easy-to-read and maintain configuration files
- Seamless Switching: Automatically switches between live source and playlist
Architecture
The server uses multiple technologies for optimal performance:
Backend:
- audio_buffer.pyx: High-performance circular buffer with zero-copy operations (Cython)
- stream_broadcaster.pyx: Efficient multi-listener broadcaster with dynamic buffering (Cython)
- cycast_server.py: Main server logic, source handling, and coordination (Python)
Web Layer: 4. flask_app.py: Flask application for UI and API endpoints 5. Tornado: WSGI server for production-grade performance and concurrency
Configuration: 6. config.hcl: Human-friendly HCL configuration file 7. config_loader.py: Configuration parser and validator
Installation
1. Install Dependencies
pip install -r requirements.txt
This installs:
- Cython (for compiling performance modules)
- pyhcl (for HCL configuration parsing)
- Flask (web framework)
- Tornado (high-performance web server)
2. Build Cython Extensions
python setup.py build_ext --inplace
This will compile the Cython modules into native extensions (.so files on Linux/Mac, .pyd on Windows).
3. Configure Your Server
Edit config.hcl to customize your settings:
server { host = "0.0.0.0" source_port = 8000 listen_port = 8001 source_password = "your-secure-password" mount_point = "/stream" } metadata { station_name = "Your Station Name" station_genre = "Your Genre" } playlist { directory = "./music" shuffle = true }
4. Prepare Your Music
Create a music directory and add some MP3 or OGG files:
mkdir music
# Copy your music files to the music directoryUsage
Start the Server
Or with a custom configuration file:
python cycast_server.py -c /path/to/myconfig.hcl
The server will display:
============================================================
Starting Cycast Server
============================================================
Configuration loaded from: config.hcl
Source port: 8000 (password: ******)
Listen port: 8001
Mount point: /stream
Station: Your Station Name
Buffer size: 10 MB
============================================================
Playlist loaded: 42 tracks
============================================================
Server ready!
Connect your source to: http://0.0.0.0:8000/stream
Listen at: http://0.0.0.0:8001/stream
Status page: http://0.0.0.0:8001/
Statistics: http://0.0.0.0:8001/api/stats
============================================================
Configure Your Source (Mixxx Example)
In Mixxx:
- Go to Preferences β Live Broadcasting
- Click Create new connection
- Select Icecast 2
- Set:
- Host:
localhost - Port:
8000 - Mount:
stream - Password:
hackme - Format: MP3 or OGG
- Host:
- Click Enable Live Broadcasting
Configure Your Source (VLC Example)
In VLC:
- Go to Media β Stream
- Add your audio source
- Click Stream
- Choose destination: IceCast
- Set:
- Address:
localhost:8000 - Mount point:
stream - Login:
source - Password:
hackme
- Address:
Listen to the Stream
Stream URL - Open in your media player or browser:
http://localhost:8001/stream
Status Page - Beautiful web interface with real-time updates:
API Endpoints:
http://localhost:8001/api/status # Current status (JSON)
http://localhost:8001/api/stats # Detailed statistics (JSON)
Customization
All configuration is done via the config.hcl file using HCL (HashiCorp Configuration Language):
server { host = "0.0.0.0" # Bind address source_port = 8000 # Port for DJ connections listen_port = 8001 # Port for listeners source_password = "secure123" # CHANGE THIS! mount_point = "/stream" } buffer { size_mb = 10 # Circular buffer size in MB } playlist { directory = "./music" shuffle = true extensions = [".mp3", ".ogg"] } broadcaster { chunk_size = 8192 # Bytes per chunk sleep_high = 0.001 # Sleep time when buffer >80% full sleep_medium = 0.005 # Sleep time when buffer 50-80% full sleep_low = 0.010 # Sleep time when buffer <50% full } metadata { station_name = "Cycast Radio" station_description = "High-performance internet radio" station_genre = "Various" station_url = "http://localhost:8001" enable_icy = true icy_metaint = 16000 } advanced { max_listeners = 0 # 0 = unlimited source_timeout = 10.0 # Seconds verbose_logging = false enable_stats = true flask_debug = false # Enable for development only! flask_secret_key = "change-me-in-production" }
Why HCL?
HCL provides:
- Human-friendly syntax with comments
- Clear hierarchical structure
- Type safety
- Better than JSON or YAML for configuration
Performance Tuning
The combination of Cython + Flask + Tornado provides excellent performance:
Cython Optimizations:
- Buffer Management: The circular audio buffer uses native C memory operations (memcpy) for zero-copy data handling
- Broadcasting: The broadcaster is optimized to send data to multiple listeners with minimal overhead
- Dynamic Buffering: Automatically adjusts sleep times based on buffer fill level
Flask on Tornado Benefits:
- Non-blocking I/O: Tornado handles concurrent connections efficiently
- Low latency: Better than traditional WSGI servers for streaming
- Scalability: Handles hundreds of concurrent listeners
- Production-ready: Battle-tested in high-traffic applications
Tuning Tips:
buffer { size_mb = 20 # Increase for more buffering (uses more RAM) } broadcaster { chunk_size = 16384 # Larger chunks = less overhead, higher latency } advanced { max_listeners = 500 # Set a limit to protect your server }
For maximum performance on production systems:
- Run on multi-core systems for better concurrent handling
- Use an SSD for playlist files
- Put behind nginx reverse proxy with caching
- Monitor with the
/api/statsendpoint
How It Works
- Source Connection: When Mixxx/VLC connects, it sends audio data to port 8000
- Buffer: Audio is written to a high-performance circular buffer (Cython)
- Broadcast: A separate thread reads from the buffer and sends to all listeners (Cython)
- Fallback: When no source is connected, the playlist feeder writes to the same buffer
- Listeners: HTTP server on port 8001 serves the stream to multiple clients
Limitations
This is a simplified streaming server suitable for:
- Small to medium internet radio stations
- Personal/hobby broadcasts
- LAN streaming
- Testing and development
For production use with hundreds of simultaneous listeners, consider:
- Full Icecast2 server
- Load balancing
- CDN integration
Architecture Diagram
βββββββββββββββ ββββββββββββββββββββ
β Mixxx/ ββββββββββΆβ Source Port β
β VLC β 8000 β (8000) β
βββββββββββββββ ββββββββββ¬ββββββββββ
β
βΌ
ββββββββββββββββββ
β Circular Bufferβ (Cython)
β (10 MB RAM) β
ββββββββββ¬ββββββββ
β
ββββββββββββββββββββΌβββββββββββββββββββ
β β β
βΌ βΌ βΌ
βββββββββββ βββββββββββ βββββββββββ
βListener β βListener β βListener β
β 1 β β 2 β β N β
βββββββββββ βββββββββββ βββββββββββ
β² β² β²
β β β
ββββββββββββββββββββ΄βββββββββββββββββββ
Flask on Tornado (8001)
βββββββββββββββββββββββββββ
β β’ Web UI (HTML/CSS/JS) β
β β’ /api/status (JSON) β
β β’ /api/stats (JSON) β
β β’ /stream (audio) β
βββββββββββββββββββββββββββ
ββββββββββββββββββββ
β Playlist Feeder β (Fallback when no source)
β (music/*.mp3) β
ββββββββββ¬ββββββββββ
β
ββββββββββββββββΆ Circular Buffer
Troubleshooting
Cython build fails:
- Make sure you have a C compiler installed (gcc on Linux, Xcode on Mac, MSVC on Windows)
- Try:
pip install --upgrade cython setuptools
Audio stutters/buffers:
- Increase buffer size:
audio_buffer.CircularAudioBuffer(size_mb=20) - Check network latency
- Reduce number of simultaneous listeners for testing
Can't connect source:
- Check firewall settings
- Verify port 8000 is not in use:
netstat -an | grep 8000 - Try changing the password
Playlist not working:
- Ensure MP3/OGG files are in the
./musicdirectory - Check file permissions
- Look for errors in console output
License
MIT License - feel free to modify and use for your projects!
Contributing
This is a demonstration project showing how to use Cython for performance-critical audio streaming. Feel free to extend it with:
- Better metadata handling
- Recording functionality
- Multiple mount points
- Admin interface
- Statistics/analytics
- Relay functionality
