IcecastKit

When you listen to a web radio or a live audio stream, there's a server behind it that receives the broadcaster's feed and redistributes it to listeners. That server is often Icecast — an open-source project by the Xiph.org foundation — or SHOUTcast, its historical counterpart.

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 wrappingsend(rawAAC:audioConfiguration:) API for sending raw AAC encoder output: IcecastKit automatically adds the 7-byte ADTS header (ISO 13818-7). AudioConfiguration for sample rate, channels and AAC profile (LC, Main, SSR, LTP). isADTS() detection for pre-wrapped data

  • TCP_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/catch block 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 duration

  • Auto-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 entirely

  • Real-time monitoringAsyncStream-based event bus with 7 event types (connected, disconnected, reconnecting, metadataUpdated, error, statistics, protocolNegotiated), rolling-window bitrate calculation, and periodic statistics snapshots

  • Cross-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 BitrateRecommendation events

  • Multi-destinationMultiIcecastClient actor for streaming to multiple servers with independent connections, failure isolation, live add/remove, and aggregated statistics

  • Bandwidth probingIcecastBandwidthProbe measures upload bandwidth, latency, and stability before streaming, with format-aware bitrate recommendations

  • Connection quality — Composite quality score (0.0–1.0) from five weighted metrics (write latency, throughput, stability, send success, reconnection) with QualityGrade and automatic recommendations

  • Stream recordingStreamRecorder actor writes audio to disk with size/time-based rotation, filename tokens ({date}, {mountpoint}, {index}), and format-aware extensions

  • Relay / ingestIcecastRelay actor pulls audio from existing streams with ICY metadata demuxing, content type detection, and relay-to-publish/relay-to-record chains

  • Advanced authIcecastAuthentication enum with Digest (RFC 7616, MD5/SHA-256), Bearer token, query token, SHOUTcast v1/v2, URL-embedded credentials parsing, and credential stripping

  • Server presetsIcecastServerPreset with 7 one-line configurations (AzuraCast, LibreTime, Radio.co, Centova Cast, SHOUTcast DNAS, Icecast Official, Broadcastify)

  • Metrics exportIcecastMetricsExporter protocol with PrometheusExporter (OpenMetrics, 8 metrics, onRender callback) and StatsDExporter (UDP POSIX), automatic labels, periodic export

  • CLI toolicecast-cli for streaming, bandwidth probing, relaying, connection testing, and server diagnostics with colored terminal output and structured exit codes

  • Swift 6.2 strict concurrency — Actors for stateful types, Sendable everywhere, async/await throughout, zero @unchecked Sendable or nonisolated(unsafe)

  • Zero core dependencies — The IcecastKit target has no third-party dependencies. Only swift-argument-parser for the CLI and swift-crypto conditionally 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

PlatformMinimum 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

StandardVersionReference

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:

TypeDescription

.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:

PresetPortAuthProtocol

.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

IcecastKit architecture — 16 modules: Client, Protocol, Metadata, Transport, Monitoring, AdaptiveBitrate, MultiClient, Probe, Quality, Recording, Relay, Authentication, ServerPresets, Metrics, Errors, Extensions
Overview of IcecastKit's modular architecture (16 modules)

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).

CommandDescription

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

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…

GitHub