IcecastKit
Published on · Updated · 28 min
The concept: a source client connects to the server, sends a continuous audio stream (MP3, AAC, Ogg…), and the server redistributes it to all connected listeners over HTTP. Simple on the surface, but the protocol has its subtleties — PUT vs SOURCE negotiation, HTTP Basic or plaintext password authentication, binary ICY metadata interleaved into the stream, automatic source ports for SHOUTcast, and disconnect handling.
While building the Atelier Socle streaming ecosystem — PodcastFeedMaker for RSS feeds, HLSKit for HTTP Live Streaming — the missing piece was live broadcasting to Icecast and SHOUTcast servers. Not a wrapper around a C library, not a shell script — a proper native Swift client, with Swift 6.2 structured concurrency, zero dependencies in the core, and cross-platform TCP transport (Network.framework on Apple, POSIX sockets on Linux).
I looked. Nothing existed in Swift. IcecastKit was born from that need.
Version 0.2.0 — Broadcast Engine — transforms IcecastKit from a simple streaming client into a full broadcast engine: adaptive bitrate with congestion detection, simultaneous multi-destination publishing, bandwidth probing, connection quality scoring, local recording with file rotation, relay/ingest from existing streams, advanced authentication (Digest, Bearer, query token), server presets for 7 platforms, and Prometheus and StatsD metrics export. All backed by 1246 tests and 97.13% coverage.
Version 0.3.0 adds ADTS wrapping (ISO 13818-7) for sending raw AAC without worrying about framing, enables TCP_NODELAY on both transport layers to eliminate Nagle buffering on small audio frames, and moves monitoring off the critical send path. 1281 tests.
What's new in 0.2.0
Version 0.2.0 — Broadcast Engine — adds 9 major modules:
Adaptive bitrate — EWMA-based congestion detection with configurable policies (conservative, responsive, aggressive, custom)
Multi-destination — Stream to multiple servers simultaneously with failure isolation
Bandwidth probing — Pre-stream upload measurement with format-aware bitrate recommendations
Connection quality — Composite score (0.0–1.0) from five weighted metrics with automatic recommendations
Stream recording — Local recording with size/time-based file rotation and filename tokens
Relay / Ingest — Pull audio from existing Icecast/SHOUTcast streams with ICY demuxing
Advanced authentication — Digest (RFC 7616), Bearer token, query token, and URL-embedded credentials
Server presets — One-line configuration for AzuraCast, LibreTime, Radio.co, Centova Cast, SHOUTcast DNAS, Icecast Official, and Broadcastify
Metrics export — Prometheus (OpenMetrics) and StatsD exporters with automatic per-destination labels
What's new in 0.3.0
Version 0.3.0 adds ADTS wrapping and transport optimizations:
ADTS wrapping —
send(rawAAC:audioConfiguration:)API for sending raw AAC encoder output: IcecastKit automatically adds the 7-byte ADTS header (ISO 13818-7).AudioConfigurationfor sample rate, channels and AAC profile (LC, Main, SSR, LTP).isADTS()detection for pre-wrapped dataTCP_NODELAY — Enabled by default on both transport layers (Network.framework and POSIX) to eliminate Nagle buffering (~200ms) on small AAC frames (200-400 bytes)
Optimized send path — Metrics recording (bytes sent, latency, network condition, recorder write) moved outside the critical
do/catchblock to execute only after a successful send
ADTS Wrapping (0.3.0)
The new send(rawAAC:audioConfiguration:) API lets you send raw AAC encoder output without worrying about ADTS framing. IcecastKit automatically builds the compliant 7-byte header per ISO 13818-7 with sync word, profile, sample rate index, channel configuration and frame length:
What IcecastKit does
IcecastKit is a pure Swift library for streaming audio to Icecast and SHOUTcast servers. It covers the entire broadcast lifecycle: connection, authentication, audio data transmission, metadata updates, real-time statistics, and graceful disconnection. All with strict Sendable conformance end to end.
Icecast 2.x — HTTP PUT protocol (modern, Icecast 2.4+) and legacy SOURCE protocol with automatic fallback for pre-2.4.0 servers
SHOUTcast v1/v2 — Password authentication for single-stream servers (v1) and multi-stream with stream IDs (v2), with automatic source port calculation (listener port + 1)
ICY metadata — Full binary wire format encoding/decoding with Unicode support (CJK, emoji), escaped quotes, zero-padded blocks, and configurable metadata intervals
Admin API — Server-side metadata updates via
/admin/metadata, global server stats via/admin/stats, and per-mountpoint stats with listener counts, bitrate, genre and connected durationAuto-reconnection — Exponential backoff with configurable jitter, retry limits, max delay caps, and four presets (
.default,.aggressive,.conservative,.none). Non-recoverable errors (auth, mountpoint conflict) skip reconnection entirelyReal-time monitoring —
AsyncStream-based event bus with 7 event types (connected, disconnected, reconnecting, metadataUpdated, error, statistics, protocolNegotiated), rolling-window bitrate calculation, and periodic statistics snapshotsCross-platform — macOS 14+, iOS 17+, tvOS 17+, watchOS 10+, visionOS 1+, and Linux (Ubuntu 22.04+ with Swift 6.2)
Adaptive bitrate — EWMA-based congestion detection with three presets and custom policies, per-format quality steps (MP3, AAC, Opus, Vorbis), and
BitrateRecommendationeventsMulti-destination —
MultiIcecastClientactor for streaming to multiple servers with independent connections, failure isolation, live add/remove, and aggregated statisticsBandwidth probing —
IcecastBandwidthProbemeasures upload bandwidth, latency, and stability before streaming, with format-aware bitrate recommendationsConnection quality — Composite quality score (0.0–1.0) from five weighted metrics (write latency, throughput, stability, send success, reconnection) with
QualityGradeand automatic recommendationsStream recording —
StreamRecorderactor writes audio to disk with size/time-based rotation, filename tokens ({date},{mountpoint},{index}), and format-aware extensionsRelay / ingest —
IcecastRelayactor pulls audio from existing streams with ICY metadata demuxing, content type detection, and relay-to-publish/relay-to-record chainsAdvanced auth —
IcecastAuthenticationenum with Digest (RFC 7616, MD5/SHA-256), Bearer token, query token, SHOUTcast v1/v2, URL-embedded credentials parsing, and credential strippingServer presets —
IcecastServerPresetwith 7 one-line configurations (AzuraCast, LibreTime, Radio.co, Centova Cast, SHOUTcast DNAS, Icecast Official, Broadcastify)Metrics export —
IcecastMetricsExporterprotocol withPrometheusExporter(OpenMetrics, 8 metrics,onRendercallback) andStatsDExporter(UDP POSIX), automatic labels, periodic exportCLI tool —
icecast-clifor streaming, bandwidth probing, relaying, connection testing, and server diagnostics with colored terminal output and structured exit codesSwift 6.2 strict concurrency — Actors for stateful types,
Sendableeverywhere,async/awaitthroughout, zero@unchecked Sendableornonisolated(unsafe)Zero core dependencies — The
IcecastKittarget has no third-party dependencies. Onlyswift-argument-parserfor the CLI andswift-cryptoconditionally on Linux
Quick start
Connect to an Icecast server, stream audio data, update the now-playing metadata, and disconnect gracefully — in a few lines:
Installation
Via Swift Package Manager, by adding the dependency to your Package.swift:
Then add it to your target:
Platform support
| Platform | Minimum version |
|---|---|
macOS | 14+ |
iOS | 17+ |
tvOS | 17+ |
watchOS | 10+ |
visionOS | 1+ |
Linux | Swift 6.2 (Ubuntu 22.04+) |
The TCP transport adapts automatically: Network.framework on Apple platforms, POSIX sockets on Linux.
Implemented standards
| Standard | Version | Reference |
|---|---|---|
Icecast Source Protocol | 2.5.0 | |
ICY Metadata Protocol | — | |
SHOUTcast DNAS | 2.6.1 | |
HTTP Basic Auth | RFC 7617 | |
HTTP Digest Auth | RFC 7616 | |
ADTS / AAC Transport | ISO 13818-7 |
Icecast PUT streaming with station info
You can configure a full station with name, genre, bitrate, sample rate and channels. The client negotiates the best protocol automatically — trying modern HTTP PUT first, then falling back to legacy SOURCE if the server is pre-2.4.0:
URL-based configuration
Parse a connection URL into a configuration and credentials in one call. Supports icecast://, shoutcast://, http://, and https:// schemes:
SHOUTcast v1 and v2
SHOUTcast v1 uses password-only authentication. IcecastKit automatically connects to the source port (listener port + 1) and sends the password line followed by icy-* stream headers:
SHOUTcast v2 extends v1 with stream IDs for multi-stream servers. The password is sent as password:#streamId:
Real-time monitoring
The AsyncStream-based event bus lets you react in real time to connection state changes, metadata updates, errors, and periodic statistics:
Auto-reconnection
IcecastKit handles automatic reconnection when a connection is lost mid-stream. Four presets are available, and custom policies are supported with jitter to prevent thundering herd problems:
The reconnection delay follows: min(initialDelay × backoffMultiplier^attempt, maxDelay) ± jitter. Non-recoverable errors (authentication failure, mountpoint in use, content type rejected) transition directly to .failed without retrying. Calling disconnect() during reconnection cancels the loop immediately.
ICY metadata
IcecastKit handles full encoding and decoding of the ICY binary wire format for inline stream embedding. Unicode support, escaped quotes, and custom fields:
Metadata interleaving
The MetadataInterleaver inserts metadata blocks into an audio stream at fixed byte intervals. It's an actor that tracks its position across multiple calls, so you can feed audio data in any chunk size:
Admin API
Server-side metadata updates via the Icecast admin HTTP API are the preferred method (over inline metadata). You can also query global server statistics and per-mountpoint stats:
When adminCredentials are set on IcecastConfiguration, IcecastClient.updateMetadata() automatically uses the admin API and falls back to inline metadata if the admin endpoint returns 404:
Content type detection
IcecastKit auto-detects the audio content type from a filename extension:
Concurrent operations
IcecastClient is an actor — all operations are inherently thread-safe. You can safely call send() and updateMetadata() from multiple concurrent tasks without data races:
Adaptive bitrate
IcecastKit monitors network conditions in real time and emits bitrate recommendations. The NetworkConditionMonitor detects congestion via EWMA latency spikes, RTT spikes, and bandwidth slowdowns. AudioQualityStep provides per-format bitrate tiers (MP3: 7 steps from 32–320 kbps, plus AAC, Opus, Vorbis). Three presets (conservative, responsive, aggressive) plus full custom configuration:
Multi-destination publishing
The MultiIcecastClient actor lets you stream to multiple servers simultaneously with independent connections and failure isolation. Destinations can be added or removed live while streaming. Each destination has its own reconnection policy:
Bandwidth probing
IcecastBandwidthProbe measures upload bandwidth and latency before committing to a live stream. The result includes measured bandwidth, average write latency, latency class, a stability score and a format-aware bitrate recommendation:
Connection quality
Connection quality scoring provides a composite score (0.0–1.0) computed from five weighted metrics: write latency (30%), throughput (25%), stability (20%), send success (15%), reconnection (10%). QualityGrade is Comparable with five levels:
Quality events arrive via the event stream: .qualityChanged(_:) and .qualityWarning(_:).
Stream recording
The StreamRecorder actor writes audio to disk with automatic file rotation. Rotation can be size-based or time-based. Filenames support dynamic tokens ({date}, {mountpoint}, {index}) and extensions are auto-detected by format:
Recording integrates with IcecastClient via IcecastConfiguration.recording for auto-start recording. Events: .recordingStarted, .recordingStopped, .recordingFileRotated.
Relay / Ingest
The IcecastRelay actor pulls audio from an existing Icecast or SHOUTcast stream. It handles ICY metadata demuxing, content type detection, and can be chained with IcecastClient for relay-to-publish or with StreamRecorder for relay-to-record:
Advanced authentication
IcecastKit supports six authentication methods via the IcecastAuthentication enum. Beyond classic HTTP Basic and SHOUTcast password, version 0.2.0 adds Digest (RFC 7616 with MD5 and SHA-256 — the password never goes on the wire), Bearer token, query token, and automatic URL credential parsing/stripping:
| Type | Description |
|---|---|
.basic | HTTP Basic (RFC 7617) |
.digest | HTTP Digest (RFC 7616, MD5/SHA-256) |
.bearer | Bearer token |
.queryToken | Token in URL query string |
.shoutcast | SHOUTcast v1 password-only |
.shoutcastV2 | SHOUTcast v2 with stream ID |
Server presets
IcecastServerPreset provides one-line configuration for 7 popular streaming platforms. Port, authentication method, protocol and default mountpoint are preconfigured:
| Preset | Port | Auth | Protocol |
|---|---|---|---|
.azuracast | 8000 | Basic | Icecast PUT |
.libretime | 8000 | Basic | Icecast PUT |
.radioCo | 8000 | Bearer | Icecast PUT |
.centovaCast | 8000 | SHOUTcast v2 | SHOUTcast v2 |
.shoutcastDNAS | 8000 | Password | SHOUTcast v1 |
.icecastOfficial | 8000 | Basic | Icecast PUT |
.broadcastify | 80 | Bearer | Icecast PUT |
Metrics export
IcecastKit can export streaming metrics to Prometheus (OpenMetrics format) or StatsD (UDP datagrams). The IcecastMetricsExporter protocol defines the common interface, and labels are auto-generated from configuration (mountpoint, server) with consumer overrides:
Exported metrics: bytes_sent, stream_duration_seconds, current_bitrate, metadata_updates_total, reconnections_total, write_latency_ms, peak_bitrate, connection_quality_score. Labels are auto-generated from configuration (mountpoint, server) with consumer overrides.
Architecture

The library is organized into 16 clearly separated modules, each with a well-defined responsibility:
CLI tool
icecast-cli provides command-line streaming, bandwidth probing, relaying, connection testing, and server diagnostics with colored terminal output and structured exit codes (0 = success, 2 = connection error, 3 = auth error, 4 = file error, 6 = server error, 7 = timeout).
| Command | Description |
|---|---|
stream | Stream an audio file with optional multi-destination, auth types, looping, and auto-reconnect |
probe | Measure upload bandwidth and latency to a server |
relay | Pull audio from a source and optionally re-publish or record |
test-connection | Test TCP connectivity, protocol negotiation, and authentication, then disconnect |
info | Query global server stats or per-mountpoint stats via the admin API |
Ecosystem
IcecastKit is part of the Atelier Socle streaming ecosystem:
PodcastFeedMaker — Podcast RSS feed generation
HLSKit — HTTP Live Streaming
IcecastKit (this library) — Icecast/SHOUTcast streaming
RTMPKit — RTMP streaming
SRTKit — SRT streaming
CaptureKit — Unified media capture
Links
GitHub - atelier-socle/swift-icecast-kit: Pure Swift client for Icecast/SHOUTcast streaming. Adaptive bitrate, multi-destination, relay/ingest, recording, Digest auth, server presets, Prometheus/StatsD metrics. Zero dependencies. macOS · iOS · Linux
Pure Swift client for Icecast/SHOUTcast streaming. Adaptive bitrate, multi-destination, relay/ingest, recording, Digest auth, server presets, Promethe…