A pure-Elixir AirPlay (RAOP) audio sender. Discover receivers on your network
and stream lossless audio to them — no native dependencies, just the Erlang/OTP.
:crypto, :gen_udp and :gen_tcp.
It speaks classic AirPlay 1 / RAOP: unencrypted ALAC over RTP with the NTP-style timing/sync receivers require. Verified streaming real audio to shairport-sync, AirPort Express, and Apple HomePods.
Experimental AirPlay 2 building blocks (transient SRP pairing, ChaCha20-Poly1305 encrypted control channel, binary plist, SETUP) live under
AirPlay.V2. The control plane is verified against real HomePods, but audio rendering (PTP clock-slaving) is not complete yet — use the AirPlay 1 API below for playback.
This is still WIP, created to scratch an itch.
Installation
def deps do
[{:airplay, "~> 0.1.0"}]
endUsage
# Discover receivers (mDNS browse of _raop._tcp.local)
AirPlay.discover()
#=> [%{name: "Office", host: "172.16.42.35", port: 7000}, ...]
# Stream a file (decoded to PCM via ffmpeg) at 40% volume
{:ok, session} = AirPlay.play("172.16.42.35", "/music/track.flac", volume: 40)
AirPlay.set_volume(session, 25)
AirPlay.stop(session)
# Or stream raw PCM you already have (44.1 kHz, signed 16-bit LE, stereo, interleaved)
{:ok, session} = AirPlay.play_pcm("172.16.42.35", pcm, volume: 40)A session is a lightweight GenServer that streams in the background and stops
itself when the track ends; pass it to set_volume/2 and stop/1.
Requirements
- Elixir ~> 1.14
ffmpegon thePATH— only forAirPlay.play/3(file decoding).AirPlay.play_pcm/3has no external dependency.
How it works
play/3 opens an RTSP control connection (OPTIONS → ANNOUNCE → SETUP → RECORD),
binds the UDP timing/control ports and answers the receiver's NTP timing probe
before SETUP (HomePods return 520 Origin Error otherwise), then paces ALAC
RTP packets to the receiver against a wall-clock with periodic sync packets.
| Module | Role |
|---|---|
AirPlay.Discovery | mDNS _raop._tcp browse |
AirPlay.Rtsp / AirPlay.Session | RTSP control plane + handshake |
AirPlay.Player | RTP audio streaming + timing/sync |
AirPlay.Rtp / AirPlay.Alac / AirPlay.Ntp | packet builders + codecs |
AirPlay.Source | file → PCM (ffmpeg) + framing |
AirPlay.Cast | play/stop/volume session GenServer |
License
BSD-3-Clause. See LICENSE.