Orpheus is a decentralized audio-over-IP network for the home. Every device is a node that can send and play audio, and there is no central server. On wired networks the nodes speak AES67: RTP with linear PCM, synchronized by PTP. That makes rooms play in sync and keeps latency low enough for video.
This repository holds the shared core and the Linux node, which is built on PipeWire. ESP32 receivers, a web UI and Wi-Fi operation are planned; see the roadmap.
Status: early development. Two Linux nodes can stream to each other over
RTP unicast (IPv4 or IPv6; multicast only for AES67/Dante interop), with the
clock synchronized over PTP and sample-rate conversion against the sound
cards' clocks. Nodes find each other over mDNS and speak NMOS (IS-04,
IS-05, BCP-004), so routes can be set with orpheusctl, which
connects both ends, or an NMOS controller; they are kept across restarts.
Wires play any channel on any output channel, with gains and meters, which
AES70 controllers can see and set too. Settings can be changed while a
node runs, and its state is pushed over a WebSocket. There is no authentication and no UI yet.
You need Rust (edition 2024), PipeWire with its development headers, and clang (for the PipeWire bindings).
cargo build --release
# PTP uses the privileged ports 319 and 320, and on Wi-Fi the node turns
# power saving off. Redo this after every build.
sudo setcap cap_net_bind_service,cap_net_admin=ep target/release/orpheusd
target/release/orpheusdWith just, just run does all three and asks for
sudo only when the capability is missing; see
development for the other build profiles.
Without the capability the node still runs, but on the system clock; see clock.
Both binaries, orpheusd and orpheusctl, end up in target/release. On a
second machine, start orpheusd the same way, with name = "Kitchen" in
its config. Then send the first machine's audio to
it:
orpheusctl nodes # other nodes on the network
orpheusctl connect KitchenThis creates a sink "Kitchen" on the first machine and connects a free receiver of the second machine to it. Whatever is played into the sink comes out of the second machine's default output. A node plays several streams at once; which ones are heard is its policy.
orpheusctl status # clock, receivers and routes
orpheusctl status --watch # the same, refreshed every second
orpheusctl disconnect Kitchen # stop sending, disconnect the receiverorpheusctl talks to http://localhost:7480 by default. Use --node URL
or ORPHEUS_NODE to query another node.
Sinks to other nodes use the icon orpheus-network-speaker, which icon
themes don't have. Install it with the other icons from
orpheusd/dist/icons.
To start the node with your session, install the systemd user unit from
orpheusd/dist/orpheusd.service; adjust
ExecStart if the binary is not in /usr/bin.
Before you rely on it, go through the first setup checklist on each machine: firewall, grandmaster, and Wi-Fi.
- First setup: a checklist for each new node, firewall and Wi-Fi
- Configuration: files,
~/.config/orpheus/config.toml, settings changed over the API - Usage:
orpheusctl, the HTTP API and its WebSocket, reading the status - Clock: PTP, TAI, settling, when PTP can't run, IPv4 and IPv6
- Architecture: crates, threads, the audio path
- Troubleshooting
- Development: building and tests
- Roadmap: milestones, known limitations, future work
The GNU General Public License, version 3 only (GPL-3.0-only): see
LICENCE.md.
orpheus-ptp is based on statime, whose code in it
stays under the MIT licence as well.