openairplay•Mar 27, 2025
airplay2-receiver
Experimental
Somewhat comprehensive python implementation of AP2 receiver using some
multi-room features. For now it implements:
HomeKit transient pairing (SRP/Curve25519/ChaCha20-Poly1305) - bit flag 48
HomeKit non-transient pairing
Some refinements for HomeKit interaction (e.g. managed/active flags)
Persist device name and some HomeKit properties across restarts (just use the -m flag again to set the device name anew)
FairPlay (v3) authentication and decryption of AES keys - the first and only Python implementation. Credit to @systemcrash for implementation.
Receiving of both REALTIME and BUFFERED Airplay2 audio streams
Airplay2 Service publication
Decoding of all Airplay2 supported CODECs: ALAC, AAC, OPUS, PCM.
Ref: here and
here
Output latency compensation for sync with other Airplay receivers
ANNOUNCE and RSA AES for unbuffered streaming from iTunes/Windows
Spotify (via AirPlay2) and other live media streams with AES keys.
RTCP
RFC2198 RTP Redundancy handling (basic); enable bit flag 61
streamConnections; enable bit flag 59
For now it does not implement:
FairPlay v2
Accurate audio sync (with help of PTP and/or NTP)
It may never implement:
MFi Authentication (requires MFi hardware module)
This code is experimental, yet fully functional. It can act as a real receiver but does not implement all airplay protocols and related pairing/authentication methods.
Next steps:
PTP (Precision Time Protocol)
Remove all os specific code (Soft Volume management)
Sender (branch-sender) - Implementation
Raspbian package
DACP/(+MRP?) Support
FairPlay v2 Support
Multiple Connections
Since multithreading is now enabled, this allows multiple concurrent connections. There are no safeguards
built to prevent you playing multiple streams. Python multiprocessing makes this "DJ" mode a
possibility but makes stream management and session management (global state data) nigh impossible. So
threading is the right approach in the receiver.
HomeKit and other AP senders can now connect concurrently to the receiver and perform operations. This
opens the path to Remote Control functionality.
mDNS/ZeroConf
If you encounter strange errors like NonUniqueNameException, or Address already in use,
and you run on macOS, you may have noticed that macOS and this app both try to send updates.
Here is a possible workaround.
Raspberry Pi 4
Install docker and then build the image:
To run the receiver:
Default network device is wlan0, you can change this with AP2IFACE env variable:
Docker Compose
Example Docker Compose
Debian
macOS Catalina
To run the receiver please use Python 3 and do the following:
Run the following commands
Note: in recent macOS versions (e.g. Ventura), you must disable AirPlay Receiver:
System Settings -> AirDrop & Handoff -> AirPlay Receiver: disable.
Windows
To run the receiver please use Python 3 and do the following:
Run the following commands
the AirPlay 2 receiver is announced as myap2.
Tested on Python 3.7.5 / macOS 10.15.2 with iPhone X 13.3 and Raspberry Pi 4
Protocol notes
https://emanuelecozzi.net/docs/airplay2