IcecastKit
Publié le · Mis à jour le · 30 min
Le principe : un client source se connecte au serveur, envoie un flux audio continu (MP3, AAC, Ogg…), et le serveur le redistribue à tous les auditeurs connectés en HTTP. Simple en apparence, mais le protocole a ses subtilités — négociation PUT vs SOURCE, authentification HTTP Basic ou par mot de passe en clair, métadonnées ICY binaires à intercaler dans le flux, ports source automatiques pour SHOUTcast, et gestion des déconnexions.
En travaillant sur l'écosystème streaming d'Atelier Socle — PodcastFeedMaker pour les flux RSS, HLSKit pour le HTTP Live Streaming — il manquait la brique de diffusion live vers les serveurs Icecast et SHOUTcast. Pas un wrapper autour d'une lib C, pas un script shell — un vrai client Swift natif, avec la concurrence structurée de Swift 6.2, zéro dépendance dans le cœur, et un transport TCP cross-platform (Network.framework sur Apple, sockets POSIX sur Linux).
J'ai cherché. Rien n'existait en Swift. IcecastKit est née de ce besoin.
La version 0.2.0 — Broadcast Engine — transforme IcecastKit d'un simple client de streaming en un véritable moteur de diffusion : bitrate adaptatif avec détection de congestion, publication multi-destination simultanée, sondage de bande passante, scoring de qualité de connexion, enregistrement local avec rotation de fichiers, relay/ingest depuis des flux existants, authentification avancée (Digest, Bearer, query token), presets serveur pour 7 plateformes, et export de métriques Prometheus et StatsD. Le tout avec 1246 tests et 97.13% de couverture.
La version 0.3.0 ajoute le wrapping ADTS (ISO 13818-7) pour envoyer de l'AAC brut sans se soucier du framing, active TCP_NODELAY sur les deux couches transport pour éliminer le buffering de Nagle sur les petites trames audio, et déplace le monitoring hors du chemin critique d'envoi. 1281 tests.
Nouveautés de la version 0.2.0
La version 0.2.0 — Broadcast Engine — ajoute 9 modules majeurs :
Bitrate adaptatif — Détection de congestion basée sur EWMA avec politiques configurables (conservative, responsive, aggressive, custom)
Multi-destination — Streaming simultané vers plusieurs serveurs avec isolation des pannes
Sondage de bande passante — Mesure de la bande passante upload avant le streaming avec recommandations de bitrate par format
Qualité de connexion — Score composite (0.0–1.0) à partir de cinq métriques pondérées avec recommandations automatiques
Enregistrement de flux — Enregistrement local avec rotation par taille/durée et tokens de nommage de fichiers
Relay / Ingest — Pull audio depuis des flux Icecast/SHOUTcast existants avec démuxage ICY
Authentification avancée — Digest (RFC 7616), Bearer token, query token, et credentials embarqués dans l'URL
Presets serveur — Configuration en une ligne pour AzuraCast, LibreTime, Radio.co, Centova Cast, SHOUTcast DNAS, Icecast Official, et Broadcastify
Export de métriques — Exporteurs Prometheus (OpenMetrics) et StatsD avec labels automatiques par destination
Nouveautés de la version 0.3.0
La version 0.3.0 ajoute le wrapping ADTS et des optimisations de transport :
Wrapping ADTS — API
send(rawAAC:audioConfiguration:)pour envoyer de l'AAC brut : IcecastKit ajoute automatiquement le header ADTS 7 bytes (ISO 13818-7).AudioConfigurationpour sample rate, channels et profil AAC (LC, Main, SSR, LTP). DétectionisADTS()pour les données déjà encapsuléesTCP_NODELAY — Activé par défaut sur les deux couches transport (Network.framework et POSIX) pour éliminer le buffering de Nagle (~200ms) sur les petites trames AAC (200-400 bytes)
Chemin d'envoi optimisé — L'enregistrement des métriques (bytes envoyés, latence, condition réseau, écriture recorder) est déplacé hors du
do/catchcritique pour ne s'exécuter qu'après un envoi réussi
Wrapping ADTS (0.3.0)
La nouvelle API send(rawAAC:audioConfiguration:) permet d'envoyer la sortie brute d'un encodeur AAC sans se soucier du framing ADTS. IcecastKit construit automatiquement le header 7 bytes conforme ISO 13818-7 avec le sync word, le profil, l'index de sample rate, la configuration des canaux et la longueur de trame :
Ce que fait IcecastKit
IcecastKit est une bibliothèque Swift pure pour streamer de l'audio vers des serveurs Icecast et SHOUTcast. Elle couvre l'ensemble du cycle de vie d'une diffusion : connexion, authentification, envoi du flux audio, mise à jour des métadonnées, statistiques temps réel, et déconnexion propre. Le tout avec conformité Sendable stricte de bout en bout.
Icecast 2.x — Protocole HTTP PUT (moderne, Icecast 2.4+) et protocole SOURCE legacy avec fallback automatique pour les serveurs pré-2.4.0
SHOUTcast v1/v2 — Authentification par mot de passe pour serveurs mono-flux (v1) et multi-flux avec stream IDs (v2), avec calcul automatique du port source (port listener + 1)
Métadonnées ICY — Encodage/décodage complet du format binaire wire avec support Unicode (CJK, emoji), quotes échappées, blocs zero-padded, et intervalles configurables
API Admin — Mise à jour des métadonnées côté serveur via
/admin/metadata, statistiques globales via/admin/stats, et stats par mountpoint avec nombre d'auditeurs, bitrate, genre et durée de connexionReconnexion automatique — Backoff exponentiel avec jitter configurable, limite de tentatives, plafond de délai, et quatre presets (
.default,.aggressive,.conservative,.none). Les erreurs non récupérables (auth, conflit mountpoint) sautent la reconnexionMonitoring temps réel — Bus d'événements basé sur
AsyncStreamavec 7 types d'événements (connected, disconnected, reconnecting, metadataUpdated, error, statistics, protocolNegotiated), calcul de bitrate en fenêtre glissante, et snapshots statistiques périodiquesCross-platform — macOS 14+, iOS 17+, tvOS 17+, watchOS 10+, visionOS 1+, et Linux (Ubuntu 22.04+ avec Swift 6.2)
Bitrate adaptatif — Détection de congestion basée sur EWMA avec trois presets et politiques custom, paliers de qualité par format (MP3, AAC, Opus, Vorbis), et événements
BitrateRecommendationMulti-destination — Actor
MultiIcecastClientpour streamer vers plusieurs serveurs avec connexions indépendantes, isolation des pannes, ajout/suppression live, et statistiques agrégéesSondage de bande passante —
IcecastBandwidthProbemesure la bande passante upload, la latence et la stabilité avant le streaming, avec recommandations de bitrate par formatQualité de connexion — Score de qualité composite (0.0–1.0) à partir de cinq métriques pondérées (latence d'écriture, débit, stabilité, succès d'envoi, reconnexion) avec
QualityGradeet recommandations automatiquesEnregistrement de flux — Actor
StreamRecorderécrit l'audio sur disque avec rotation par taille/durée, tokens de nommage ({date},{mountpoint},{index}), et extensions par formatRelay / ingest — Actor
IcecastRelaypull l'audio depuis des flux existants avec démuxage ICY des métadonnées, détection du content type, et chaînes relay-to-publish/relay-to-recordAuthentification avancée — Enum
IcecastAuthenticationavec Digest (RFC 7616, MD5/SHA-256), Bearer token, query token, SHOUTcast v1/v2, parsing de credentials depuis l'URL, et stripping de credentialsPresets serveur —
IcecastServerPresetavec 7 configurations en une ligne (AzuraCast, LibreTime, Radio.co, Centova Cast, SHOUTcast DNAS, Icecast Official, Broadcastify)Export de métriques — Protocole
IcecastMetricsExporteravecPrometheusExporter(OpenMetrics, 8 métriques, callbackonRender) etStatsDExporter(UDP POSIX), labels automatiques, export périodiqueOutil CLI —
icecast-clipour streamer, sonder la bande passante, relayer, tester les connexions et diagnostiquer les serveurs avec sortie colorée et codes de sortie structurésSwift 6.2 strict concurrency — Actors pour les types stateful,
Sendablepartout,async/awaitde bout en bout, zéro@unchecked Sendableounonisolated(unsafe)Zéro dépendance core — Le target
IcecastKitn'a aucune dépendance tierce. Seulswift-argument-parserpour le CLI etswift-cryptoconditionnellement sur Linux
Quick start
Se connecter à un serveur Icecast, streamer de l'audio, mettre à jour les métadonnées now-playing, et se déconnecter proprement — en quelques lignes :
Installation
Via Swift Package Manager, en ajoutant la dépendance dans votre Package.swift :
Puis dans le target concerné :
Plateformes supportées
| Plateforme | Version minimum |
|---|---|
macOS | 14+ |
iOS | 17+ |
tvOS | 17+ |
watchOS | 10+ |
visionOS | 1+ |
Linux | Swift 6.2 (Ubuntu 22.04+) |
Le transport TCP s'adapte automatiquement : Network.framework sur les plateformes Apple, sockets POSIX sur Linux.
Standards implémentés
| Standard | Version | Référence |
|---|---|---|
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 |
Streaming Icecast PUT avec infos station
On peut configurer une station complète avec nom, genre, bitrate, sample rate et canaux. Le client négocie automatiquement le meilleur protocole — HTTP PUT d'abord, puis fallback vers SOURCE legacy si le serveur est pré-2.4.0 :
Configuration par URL
On peut parser une URL de connexion en configuration + credentials en un seul appel. Les schémas icecast://, shoutcast://, http:// et https:// sont supportés :
SHOUTcast v1 et v2
SHOUTcast v1 utilise une authentification par mot de passe seul. IcecastKit se connecte automatiquement au port source (port listener + 1) et envoie le mot de passe suivi des headers icy-* :
SHOUTcast v2 étend v1 avec les stream IDs pour les serveurs multi-flux. Le mot de passe est envoyé sous la forme password:#streamId :
Monitoring temps réel
Le bus d'événements basé sur AsyncStream permet de réagir en temps réel aux changements d'état de connexion, mises à jour de métadonnées, erreurs, et statistiques périodiques :
Reconnexion automatique
IcecastKit gère la reconnexion automatique quand une connexion est perdue en cours de streaming. Quatre presets sont disponibles, et les politiques custom sont supportées avec jitter pour éviter les problèmes de thundering herd :
Le délai de reconnexion suit la formule : min(initialDelay × backoffMultiplier^attempt, maxDelay) ± jitter. Les erreurs non récupérables (échec d'authentification, mountpoint occupé, content type rejeté) passent directement à l'état .failed sans tentative de reconnexion. Appeler disconnect() pendant la reconnexion annule la boucle immédiatement.
Métadonnées ICY
IcecastKit gère l'encodage et le décodage complet du format binaire ICY pour l'insertion inline dans le flux. Support Unicode, quotes échappées, et champs custom :
Interleaving de métadonnées
Le MetadataInterleaver insère des blocs de métadonnées dans un flux audio à intervalles fixes. C'est un actor qui garde la trace de sa position entre les appels, ce qui permet d'envoyer l'audio par chunks de n'importe quelle taille :
API Admin
La mise à jour des métadonnées côté serveur via l'API HTTP admin Icecast est la méthode privilégiée (plutôt que l'insertion inline). On peut aussi interroger les statistiques globales et par mountpoint :
Quand des adminCredentials sont définies sur IcecastConfiguration, IcecastClient.updateMetadata() utilise automatiquement l'API admin et bascule sur les métadonnées inline si l'endpoint admin renvoie un 404 :
Détection du content type
IcecastKit détecte automatiquement le content type audio à partir de l'extension du fichier :
Opérations concurrentes
IcecastClient est un actor — toutes les opérations sont thread-safe par construction. On peut appeler send() et updateMetadata() depuis plusieurs tâches concurrentes sans data race :
Bitrate adaptatif
IcecastKit surveille les conditions réseau en temps réel et émet des recommandations de bitrate. Le NetworkConditionMonitor détecte la congestion via des pics de latence EWMA, des pics de RTT et des ralentissements de bande passante. AudioQualityStep fournit des paliers de bitrate par format (MP3 : 7 paliers de 32 à 320 kbps, plus AAC, Opus, Vorbis). Trois presets (conservative, responsive, aggressive) plus une configuration custom complète :
Publication multi-destination
L'actor MultiIcecastClient permet de streamer vers plusieurs serveurs simultanément avec des connexions indépendantes et une isolation des pannes. On peut ajouter ou retirer des destinations à chaud pendant le streaming. Chaque destination a sa propre politique de reconnexion :
Sondage de bande passante
IcecastBandwidthProbe mesure la bande passante upload et la latence avant de lancer un stream live. Le résultat inclut la bande passante mesurée, la latence moyenne d'écriture, la classe de latence, un score de stabilité et une recommandation de bitrate adaptée au format :
Qualité de connexion
Le scoring de qualité de connexion fournit un score composite (0.0–1.0) calculé à partir de cinq métriques pondérées : latence d'écriture (30%), débit (25%), stabilité (20%), succès d'envoi (15%), reconnexion (10%). Le QualityGrade est Comparable et cinq niveaux sont définis :
Les événements de qualité arrivent via le bus d'événements : .qualityChanged(_:) et .qualityWarning(_:).
Enregistrement de flux
L'actor StreamRecorder écrit l'audio sur disque avec rotation automatique des fichiers. La rotation peut se faire par taille maximale ou par durée. Les noms de fichiers supportent des tokens dynamiques ({date}, {mountpoint}, {index}) et les extensions sont détectées automatiquement par format :
L'enregistrement s'intègre avec IcecastClient via IcecastConfiguration.recording pour un démarrage automatique. Événements émis : .recordingStarted, .recordingStopped, .recordingFileRotated.
Relay / Ingest
L'actor IcecastRelay permet de puller de l'audio depuis un flux Icecast ou SHOUTcast existant. Il gère le démuxage des métadonnées ICY, la détection du content type, et peut être chaîné avec IcecastClient pour un relay-to-publish ou avec StreamRecorder pour un relay-to-record :
Authentification avancée
IcecastKit supporte six méthodes d'authentification via l'enum IcecastAuthentication. Au-delà du HTTP Basic classique et du mot de passe SHOUTcast, la version 0.2.0 ajoute Digest (RFC 7616 avec MD5 et SHA-256 — le mot de passe ne transite jamais en clair), Bearer token, query token, et le parsing/stripping automatique de credentials depuis les URLs :
| Type | Description |
|---|---|
.basic | HTTP Basic (RFC 7617) |
.digest | HTTP Digest (RFC 7616, MD5/SHA-256) |
.bearer | Bearer token |
.queryToken | Token dans la query string de l'URL |
.shoutcast | SHOUTcast v1 mot de passe seul |
.shoutcastV2 | SHOUTcast v2 avec stream ID |
Presets serveur
IcecastServerPreset fournit une configuration en une ligne pour 7 plateformes de streaming populaires. Port, méthode d'authentification, protocole et mountpoint par défaut sont préconfigurés :
| Preset | Port | Auth | Protocole |
|---|---|---|---|
.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 |
Export de métriques
IcecastKit peut exporter les métriques de streaming vers Prometheus (format OpenMetrics) ou StatsD (datagrammes UDP). Le protocole IcecastMetricsExporter définit l'interface commune, et les labels sont auto-générés à partir de la configuration (mountpoint, serveur) avec possibilité de surcharge côté consommateur :
Métriques exportées : bytes_sent, stream_duration_seconds, current_bitrate, metadata_updates_total, reconnections_total, write_latency_ms, peak_bitrate, connection_quality_score. Les labels sont auto-générés depuis la configuration (mountpoint, serveur) avec surcharges consommateur.
Architecture

La bibliothèque est organisée en 16 modules clairement séparés, chacun avec une responsabilité bien définie :
Outil CLI
icecast-cli fournit le streaming en ligne de commande, le sondage de bande passante, le relay, le test de connexion, et le diagnostic serveur avec sortie colorée et codes de sortie structurés (0 = succès, 2 = erreur connexion, 3 = erreur auth, 4 = erreur fichier, 6 = erreur serveur, 7 = timeout).
| Commande | Description |
|---|---|
stream | Streamer un fichier audio avec multi-destination optionnelle, types d'auth, boucle et reconnexion automatique |
probe | Mesurer la bande passante upload et la latence vers un serveur |
relay | Puller l'audio d'une source et optionnellement re-publier ou enregistrer |
test-connection | Tester la connectivité TCP, la négociation de protocole et l'authentification, puis se déconnecter |
info | Interroger les stats globales du serveur ou les stats par mountpoint via l'API admin |
Écosystème
IcecastKit fait partie de l'écosystème streaming d'Atelier Socle :
PodcastFeedMaker — Génération de flux RSS podcast
HLSKit — HTTP Live Streaming
IcecastKit (cette bibliothèque) — Streaming Icecast/SHOUTcast
RTMPKit — Streaming RTMP
SRTKit — Streaming SRT
CaptureKit — Capture média unifiée
Liens
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…