Contents

atelier-socle/swift-srt-kit

Pure Swift implementation of the SRT protocol. Caller, listener, rendezvous modes with AES encryption, FEC, connection bonding, congestion control, bandwidth probing, and real-time statistics. No C dependencies. macOS · iOS · tvOS · watchOS · visionOS · Linux.

Features

  • Caller/Listener/Rendezvous — Three connection modes for any SRT topology with full handshake negotiation (induction, conclusion, cookie exchange)
  • AES-CTR + AES-GCM encryption — End-to-end encryption with PBKDF2 key derivation (RFC 2898), RFC 3394 key wrap, configurable key sizes (128/192/256), and automatic key rotation with pre-announce
  • Forward Error Correction — XOR-based row, column, and matrix FEC with staircase/even layouts, configurable ARQ modes (always, onreq, never), and SRTO_PACKETFILTER format parsing
  • Connection Bonding — Broadcast (all links), main/backup (automatic failover), and balancing (weighted aggregate) groups with packet deduplication and stability monitoring
  • Congestion Control — LiveCC (packet pacing), FileCC (AIMD with slow start), AdaptiveCC (pattern detection), pluggable architecture via CongestionControllerPlugin protocol
  • Bandwidth Probing — Stepped probe engine with quick/standard/thorough presets, auto-configuration generation, and bitrate monitoring with hysteresis
  • TSBPD Timing — Time-Based Sender/Buffer/Delivery with clock drift correction, too-late packet drop, and configurable latency
  • Real-time Statistics — Comprehensive metrics (packets, bytes, RTT, bandwidth, buffers, congestion, FEC, encryption), quality scoring with 5 weighted metrics, Prometheus text exposition, and StatsD datagram export
  • Stream Recording — Buffered recording with size/duration-based rotation in MPEG-TS or raw format
  • Access Control — StreamID-based access control with #!:: format parsing and generation (resource, mode, session, user, content type, custom keys)
  • Auto-reconnect — Exponential backoff with configurable jitter and four presets (default, aggressive, conservative, disabled)
  • Multi-stream / Multi-caller — Route multiple streams over a single listener, manage multiple destinations with enable/disable control
  • Server Presets — One-line configuration for AWS MediaConnect, Nimble Streamer, Haivision SRT Gateway, OBS Studio, Wowza, vMix, and SRT Live Server
  • Cross-platform — macOS 14+, iOS 17+, tvOS 17+, watchOS 10+, visionOS 1+, and Linux (Ubuntu 22.04+ with Swift 6.2)
  • CLI toolsrt-cli for sending, receiving, probing, statistics, loopback testing, and diagnostics
  • Swift 6.2 strict concurrency — Actors for stateful types, Sendable everywhere, async/await throughout, zero @unchecked Sendable or nonisolated(unsafe)
  • Interop with libsrt and MediaMTX — Bidirectional interoperability with libsrt 1.5.4 and MPEG-TS publishing to MediaMTX 1.16.3 validated for both encrypted and unencrypted connections

Standards

| Standard | Reference | |----------|-----------| | SRT Protocol | SRT Alliance Technical Overview | | SRT Handshake | IETF Draft | | AES Key Wrap | RFC 3394 | | PBKDF2 | RFC 2898 | | AES-CTR | NIST SP 800-38A | | AES-GCM | NIST SP 800-38D |


Quick Start

Connect to an SRT listener, send data, check statistics, and disconnect:

import SRTKit

let caller = SRTCaller(configuration: .init(
    host: "srt.example.com", port: 4200
))

try await caller.connect()
let payload: [UInt8] = [0x47, 0x00, 0x11, 0x10]
let bytesSent = try await caller.send(payload)
let stats = await caller.statistics()
await caller.disconnect()

Installation

Swift Package Manager

Add the dependency to your Package.swift:

dependencies: [
    .package(url: "https://github.com/atelier-socle/swift-srt-kit.git", from: "0.3.0")
]

Then add it to your target:

.target(
    name: "YourTarget",
    dependencies: ["SRTKit"]
)

Platform Support

| Platform | Minimum Version | |----------|----------------| | macOS | 14+ | | iOS | 17+ | | tvOS | 17+ | | watchOS | 10+ | | visionOS | 1+ | | Linux | Swift 6.2 (Ubuntu 22.04+) |


Usage

Encrypted Caller

let caller = SRTCaller(configuration: .init(
    host: "srt.example.com",
    port: 4200,
    passphrase: "my-secret-key-phrase",
    keySize: .aes256,
    cipherMode: .ctr
))
try await caller.connect()

let payload: [UInt8] = [0xCA, 0xFE, 0xBA, 0xBE]
let bytesSent = try await caller.send(payload)
await caller.disconnect()

Listener

let listener = SRTListener(configuration: .init(port: 4200))
try await listener.start()

for await socket in listener.incomingConnections {
    Task {
        let data = await socket.receive()
        // Process received data
    }
}

Configuration with Builder

let config = try SRTConfigurationBuilder(
    host: "srt.example.com", port: 4200
)
.mode(.caller)
.latency(microseconds: 120_000)
.encryption(
    passphrase: "my-secret-key-phrase",
    keySize: .aes256,
    cipherMode: .ctr
)
.build()

Presets

// Six presets: lowLatency, balanced, reliable, highBandwidth, broadcast, fileTransfer
let config = SRTPreset.broadcast.configuration(
    host: "srt.example.com", port: 4200)

// File transfer disables TSBPD and uses file CC
let fileOptions = SRTPreset.fileTransfer.socketOptions()
// fileOptions.tsbpd == false
// fileOptions.congestionControl == "file"

AES-CTR Encryption

let sek = Array(repeating: UInt8(0x42), count: 16)
let salt = Array(repeating: UInt8(0x01), count: 16)

let encryptor = try SRTEncryptor(
    sek: sek, salt: salt, cipherMode: .ctr, keySize: .aes128)
let decryptor = try SRTDecryptor(
    sek: sek, salt: salt, cipherMode: .ctr, keySize: .aes128)

let plaintext: [UInt8] = Array(0..<188)
let header: [UInt8] = [0x00, 0x00, 0x00, 0x2A]
let encrypted = try encryptor.encrypt(
    payload: plaintext, sequenceNumber: SequenceNumber(42), header: header)
let decrypted = try decryptor.decrypt(
    payload: encrypted, sequenceNumber: SequenceNumber(42), header: header)
// decrypted == plaintext

Forward Error Correction

let fecConfig = try FECConfiguration(
    columns: 10, rows: 5, layout: .staircase, arqMode: .always)
// fecConfig.matrixSize == 50
// fecConfig.totalFECPackets == 15
// fecConfig.overheadRatio > 0

// Parse from SRTO_PACKETFILTER format
let filterString = fecConfig.toFilterString()
let parsed = FECConfiguration.parse(filterString)

Connection Bonding

let config = GroupConfiguration(
    mode: .mainBackup,
    stabilityTimeout: 40_000,
    peerLatency: 120_000)

var strategy = BroadcastStrategy(initialSequence: SequenceNumber(0))
let result = strategy.prepareSend(activeMembers: [1, 2, 3])
// result.targets == [1, 2, 3]

Statistics and Quality Scoring

let stats = await caller.statistics()
let quality = SRTConnectionQuality.from(statistics: stats)
// quality.score: 0.0–1.0
// quality.grade: .excellent, .good, .fair, .poor, .critical

// Prometheus export
let exporter = PrometheusExporter(prefix: "srt")
let rendered = exporter.render(stats, labels: ["stream": "main"])
// Contains "# HELP", "# TYPE", "srt_" prefixed metrics

Access Control

let access = SRTAccessControl.parse("#!::r=live/feed1,m=publish,u=operator")
// access.resource == "live/feed1"
// access.mode == .publish
// access.userName == "operator"

let generated = access.generate()
// "#!::r=live/feed1,m=publish,u=operator"

Reconnection

// Four presets: .default, .aggressive, .conservative, .disabled
let policy = SRTReconnectPolicy(
    maxAttempts: 10,
    initialDelayMicroseconds: 1_000_000,
    maxDelayMicroseconds: 60_000_000,
    backoffMultiplier: 2.0,
    jitter: 0.0)

let manager = ReconnectionManager(policy: policy)
let delay = manager.delayForAttempt(1)
// delay == 1_000_000

CLI

srt-cli provides command-line sending, receiving, probing, statistics, and diagnostics with progress display and structured output.

Installation

swift build -c release
cp .build/release/srt-cli /usr/local/bin/

Commands

| Command | Description | |---------|-------------| | send | Send data to an SRT listener | | receive | Receive data from an SRT caller | | probe | Probe available bandwidth and get recommendations | | stats | Display real-time connection statistics | | test | Run a loopback performance test | | info | Display version and feature information |

Examples

# Send a file with encryption
srt-cli send --host srt.example.com --port 4200 --file input.ts \
    --passphrase "my-secret-key-phrase"

# Receive to file with duration limit
srt-cli receive --port 4200 --output received.ts --duration 60

# Probe bandwidth with quality target
srt-cli probe --host srt.example.com --mode thorough --target quality

# Monitor real-time statistics with quality scoring
srt-cli stats --host srt.example.com --port 4200 --quality

# Loopback test at 20 Mbps for 30 seconds
srt-cli test --duration 30 --bitrate 20000 --latency 250

See the CLI Reference for the full command documentation with all options and flags.


Architecture

Sources/
├── SRTKit/                     # Core library
   ├── AccessControl/          # StreamID parsing and validation
   ├── Bonding/                # Connection groups (broadcast, backup, balancing)
   ├── Configuration/          # Options, presets, builder
   ├── Congestion/             # LiveCC, FileCC, AdaptiveCC, plugin system
   ├── Connection/             # SRTSocket, SRTCaller, SRTListener
   ├── Encryption/             # AES-CTR/GCM, key derivation, wrap, rotation
   ├── Errors/                 # Typed error hierarchy
   ├── FEC/                    # Forward error correction (XOR matrix)
   ├── Handshake/              # Handshake state machines
   ├── MultiCaller/            # Multi-destination sender
   ├── MultiStream/            # Multi-stream manager
   ├── Packet/                 # Packet structures (data, control, ACK, NAK, etc.)
   ├── Probing/                # Bandwidth probing and bitrate monitoring
   ├── Recording/              # Stream recording with rotation
   ├── Reconnection/           # Reconnection policy and manager
   ├── Reliability/            # ACK/NAK, loss detection, retransmission
   ├── Statistics/             # Metrics, quality scoring, exporters
   ├── Timing/                 # TSBPD, drift correction, too-late drop
   └── Transport/              # UDP I/O, multiplexer, address resolution
├── SRTKitCommands/             # CLI command implementations
└── SRTKitCLI/                  # CLI entry point (@main)

Documentation

Full API documentation is available as a DocC catalog:


Ecosystem

swift-srt-kit is part of the Atelier Socle streaming ecosystem:


Contributing

See CONTRIBUTING.md for guidelines on how to contribute.


License

This project is licensed under the Apache License 2.0.

Copyright 2026 Atelier Socle SAS. See NOTICE for details.

Package Metadata

Repository: atelier-socle/swift-srt-kit

Homepage: https://atelier-socle.github.io/swift-srt-kit/

Stars: 3

Forks: 0

Open issues: 0

Default branch: main

Primary language: swift

License: Apache-2.0

Topics: apple-platforms, cli, encryption, fec, linux, live-streaming, low-latency, media-transport, pure-swift, srt, streaming, swift, swift-package-manager, udp

README: README.md