Skip to main content

Synchronized audio player for Sendspin servers

Project description

sendspin

pypi_badge

Connect to any Sendspin server and instantly turn your computer into an audio target that can participate in multi-room audio.

Sendspin CLI includes three apps:

When using an explicit app (daemon, serve, or player), put it immediately after sendspin. For example, use sendspin daemon --name Kitchen, not sendspin --name Kitchen daemon.

Screenshot of the Sendspin terminal player

A project from the Open Home Foundation

Quick Start

Run directly with uv:

Start client

uvx sendspin

Host a Sendspin party

uvx sendspin serve --demo
uvx sendspin serve /path/to/media.mp3
uvx sendspin serve https://retro.dancewave.online/retrodance.mp3

Installation

With uv:

uv tool install sendspin

Support for Chromecast devices requires installation of extra dependencies:

uv tool install 'sendspin[cast]'

Install as daemon (Linux):

curl -fsSL https://raw.githubusercontent.com/Sendspin/sendspin-cli/refs/heads/main/scripts/systemd/install-systemd.sh | sudo bash

With pip:

pip install sendspin
Install from source
git clone https://github.com/Sendspin-Protocol/sendspin.git
cd sendspin
pip install .

After installation, run:

sendspin

The player will automatically connect to a Sendspin server on your local network and be available for playback.

Updating

To update to the latest version of Sendspin:

If installed with uv:

uv tool upgrade sendspin

If installed with pip:

pip install --upgrade sendspin

If installed as systemd daemon:

The systemd daemon preserves your configuration during updates. Simply upgrade the package:

# Upgrade sendspin (the daemon installer uses uv by default)
uv tool upgrade sendspin

# Or if you installed with pip
pip install --upgrade sendspin

# Restart the service to use the new version
sudo systemctl restart sendspin

Your client name, audio device selection, and other settings in /etc/default/sendspin are preserved during the update.

Note: You do not need to uninstall and reinstall when updating. Your configuration (client name, audio device, delay settings) is stored separately and will be preserved.

Configuration Options

Sendspin stores settings in JSON configuration files that persist between sessions. All command-line arguments can also be set in the config file, with CLI arguments taking precedence over stored settings.

Configuration File

Settings are stored in ~/.config/sendspin/:

  • settings-tui.json - Settings for the interactive TUI client
  • settings-daemon.json - Settings for daemon mode
  • settings-serve.json - Settings for serve mode

Example configuration file (TUI/daemon):

{
  "player_volume": 50,
  "player_muted": false,
  "static_delay_ms": -100.0,
  "last_server_url": "ws://192.168.1.100:8927/sendspin",
  "name": "Living Room",
  "client_id": "sendspin-living-room",
  "audio_device": "2",
  "audio_format": "flac:48000:24:2",
  "log_level": "INFO",
  "listen_port": 8927,
  "use_mpris": true,
  "use_hardware_volume": true,
  "hook_set_volume": "/usr/local/bin/set-avr-volume"
}

Example configuration file (serve):

{
  "log_level": "INFO",
  "listen_port": 8927,
  "name": "My Sendspin Server",
  "source": "/path/to/music.mp3",
  "clients": ["ws://192.168.1.50:8927/sendspin", "ws://192.168.1.51:8927/sendspin"]
}

Available settings:

Setting Type Mode Description
player_volume integer (0-100) TUI/daemon Player output volume percentage
player_muted boolean TUI/daemon Whether the player is muted
static_delay_ms float TUI/daemon Extra playback delay in milliseconds
last_server_url string TUI/daemon Server URL (used as default for --url)
name string All Friendly name for client or server (--name)
client_id string TUI/daemon Unique client identifier (--id)
audio_device string TUI/daemon Audio device index, name prefix, or ALSA device name (--audio-device)
audio_format string TUI/daemon Preferred audio format (--audio-format, e.g., flac:48000:24:2)
log_level string All Logging level: DEBUG, INFO, WARNING, ERROR, CRITICAL
listen_port integer daemon/serve Listen port (--port, default: 8927)
use_mpris boolean TUI/daemon Enable MPRIS integration (default: true)
use_hardware_volume boolean TUI/daemon Control hardware/system output volume instead of software volume (--hardware-volume true/false). Default: on for daemon (if available), off for TUI
hook_set_volume string TUI/daemon Script to run for external volume control (--hook-set-volume). Receives the effective volume 0-100 as the last argument
hook_start string TUI/daemon Command to run when audio stream starts
hook_stop string TUI/daemon Command to run when audio stream stops
source string serve Default audio source (file path or URL, ffmpeg input)
source_format string serve ffmpeg container format for audio source
clients array serve Client URLs to connect to (--client)

Settings are automatically saved when changed through the TUI. You can also edit the JSON file directly while the client is not running.

Server Connection

By default, the player automatically discovers Sendspin servers on your local network using mDNS. You can also connect directly to a specific server:

sendspin --url ws://192.168.1.100:8080/sendspin

List available servers on the network:

sendspin --list-servers

Client Identification

If you want to run multiple players on the same computer, you can specify unique identifiers:

sendspin --id my-client-1 --name "Kitchen"
sendspin --id my-client-2 --name "Bedroom"
  • --id: A unique identifier for this client (optional; defaults to sendspin-<hostname>, useful for running multiple instances on one computer)
  • --name: A friendly name displayed on the server (optional; defaults to hostname)

Audio Output Device Selection

By default, the player uses your system's default audio output device. You can list available devices or select a specific device:

List available audio devices:

sendspin --list-audio-devices

This displays all audio output devices with their IDs, channel configurations, and sample rates. The default device is marked.

Select a specific audio device by index:

sendspin --audio-device 2

Or by name prefix:

sendspin --audio-device "MacBook"

Or by raw ALSA device name (Linux):

sendspin --audio-device dmixer

This is useful for ALSA plugin devices (dmix, plug, etc.) that don't appear in --list-audio-devices. For example, in a dual mono setup where two daemons share a single sound card via dmix, each daemon can target a different ALSA device that routes to a specific channel:

# Room 1: left channel via dmix
sendspin daemon --name "Living Room" --audio-device living_room

# Room 2: right channel via dmix
sendspin daemon --name "Kitchen" --audio-device kitchen

This requires an /etc/asound.conf with dmix and plug devices that route to the appropriate channels. See your ALSA documentation for details on configuring dmix.

This is particularly useful when running sendspin daemon on headless devices or when you want to route audio to a specific output.

Preferred Audio Format

By default, the player negotiates the best audio format with the server from the list of formats supported by your audio device (preferring FLAC over PCM). You can specify a preferred format to prioritize:

sendspin --audio-format flac:48000:24:2

The format string uses the pattern codec:sample_rate:bit_depth:channels:

  • codec: flac (compressed, preferred) or pcm (uncompressed)
  • sample_rate: Sample rate in Hz (e.g., 44100, 48000, 96000)
  • bit_depth: Bits per sample (16 or 24)
  • channels: Channel count (1 for mono, 2 for stereo)

The specified format is validated against the audio device on startup. If the device doesn't support it, the player will exit with an error.

System Volume Control

On Linux with PulseAudio/PipeWire, Sendspin can control your system output volume directly. Volume adjustments (keyboard shortcuts, server commands) change the system volume. The current system volume is read on startup — the player_volume and player_muted settings are only used when hardware volume is disabled.

Hardware volume is on by default in daemon mode and off by default in TUI mode. To override:

sendspin --hardware-volume true             # Enable for TUI
sendspin daemon --hardware-volume false     # Disable for daemon

If your real volume control lives on another device, you can hand volume changes off to a script instead:

sendspin daemon --hook-set-volume /usr/local/bin/set-avr-volume

The script receives the effective output volume as its last argument in the range 0-100. When the player is muted, Sendspin calls the script with 0 and keeps the last logical player_volume persisted separately so unmuting restores the previous level.

Because Sendspin cannot read back external device state from the hook, startup volume comes from the persisted player_volume and player_muted settings. Those settings are updated whenever Sendspin successfully applies a new volume through the hook. When hook_set_volume is configured, it takes precedence over PulseAudio/PipeWire hardware volume control.

Adjusting Playback Delay

The player supports adjusting playback delay to compensate for audio hardware latency or achieve better synchronization across devices.

sendspin --static-delay-ms -100

Note: Based on limited testing, the delay value is typically a negative number (e.g., -100 or -150) to compensate for audio hardware buffering.

Daemon Mode

To run the player as a background daemon without the interactive TUI (useful for headless devices or scripts):

sendspin daemon

The daemon runs in the background and logs status messages to stdout. It accepts the same connection and audio options as the TUI client:

sendspin daemon --name "Kitchen" --audio-device 2

In daemon mode without --url, the client listens for incoming server connections and advertises itself via mDNS. The --name option (or name setting) is used as the friendly name in the mDNS advertisement, making it easy for servers to identify this client on the network.

Hooks

You can run external commands when audio streams start or stop. This is useful for controlling amplifiers, lighting, or other home automation:

sendspin --hook-start "./turn_on_amp.sh" --hook-stop "./turn_off_amp.sh"

Or with inline commands:

sendspin daemon --hook-start "amixer set Master unmute" --hook-stop "amixer set Master mute"

--hook-set-volume is separate from these stream lifecycle hooks. It is intended for external volume controllers and receives the effective output volume as its last argument.

Hooks receive these environment variables:

  • SENDSPIN_EVENT - Event type: "start" or "stop"
  • SENDSPIN_SERVER_ID - Connected server identifier
  • SENDSPIN_SERVER_NAME - Connected server friendly name
  • SENDSPIN_SERVER_URL - Connected server URL. Only available if client initiated the connection to the server.
  • SENDSPIN_CLIENT_ID - Client identifier
  • SENDSPIN_CLIENT_NAME - Client friendly name

Debugging & Troubleshooting

If you experience synchronization issues or audio glitches, you can enable detailed logging to help diagnose the problem:

sendspin --log-level DEBUG

This provides detailed information about time synchronization. The output can be helpful when reporting issues.

Install as Daemon (systemd, Linux)

For headless devices like Raspberry Pi, you can install sendspin daemon as a systemd service that starts automatically on boot.

Install:

curl -fsSL https://raw.githubusercontent.com/Sendspin/sendspin-cli/refs/heads/main/scripts/systemd/install-systemd.sh | sudo bash

The installer will:

  • Check and offer to install dependencies (libportaudio2, uv)
  • Install sendspin via uv tool install
  • Prompt for client name and audio device selection
  • Create systemd service and configuration

Manage the service:

sudo systemctl start sendspin    # Start the service
sudo systemctl stop sendspin     # Stop the service
sudo systemctl status sendspin   # Check status
journalctl -u sendspin -f        # View logs

Configuration: Edit /etc/default/sendspin to change client name, audio device, or delay settings.

Uninstall:

curl -fsSL https://raw.githubusercontent.com/Sendspin/sendspin-cli/refs/heads/main/scripts/systemd/uninstall-systemd.sh | sudo bash

Sendspin Party

The Sendspin client includes a mode to enable hosting a Sendspin Party. This will start a Sendspin server playing a specified audio file or URL in a loop, allowing nearby Sendspin clients to connect and listen together. It also hosts a web interface for easy playing and sharing. Fire up that home or office 🔥

# Demo mode
sendspin serve --demo
# Local file
sendspin serve /path/to/media.mp3
# Remote URL
sendspin serve https://retro.dancewave.online/retrodance.mp3
# Without pre-installing Sendspin
uvx sendspin serve /path/to/media.mp3
# Connect to specific clients
sendspin serve --demo --client ws://192.168.1.50:8927/sendspin --client ws://192.168.1.51:8927/sendspin

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sendspin-5.8.0.tar.gz (98.4 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

sendspin-5.8.0-cp313-cp313-win_amd64.whl (101.8 kB view details)

Uploaded CPython 3.13Windows x86-64

sendspin-5.8.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl (106.3 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ ARM64manylinux: glibc 2.28+ ARM64

sendspin-5.8.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl (108.0 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.28+ x86-64manylinux: glibc 2.5+ x86-64

sendspin-5.8.0-cp313-cp313-macosx_11_0_arm64.whl (100.1 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

sendspin-5.8.0-cp313-cp313-macosx_10_13_x86_64.whl (99.1 kB view details)

Uploaded CPython 3.13macOS 10.13+ x86-64

sendspin-5.8.0-cp312-cp312-win_amd64.whl (101.8 kB view details)

Uploaded CPython 3.12Windows x86-64

sendspin-5.8.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl (106.3 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ ARM64manylinux: glibc 2.28+ ARM64

sendspin-5.8.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl (108.0 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.28+ x86-64manylinux: glibc 2.5+ x86-64

sendspin-5.8.0-cp312-cp312-macosx_11_0_arm64.whl (100.1 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

sendspin-5.8.0-cp312-cp312-macosx_10_13_x86_64.whl (99.1 kB view details)

Uploaded CPython 3.12macOS 10.13+ x86-64

File details

Details for the file sendspin-5.8.0.tar.gz.

File metadata

  • Download URL: sendspin-5.8.0.tar.gz
  • Upload date:
  • Size: 98.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for sendspin-5.8.0.tar.gz
Algorithm Hash digest
SHA256 fdb2d1e15d401904bc98dc38ac32b4dcc5596122ec5b3c24774eab4211086e73
MD5 9b7f5868570752bd0bb5710ee6009f07
BLAKE2b-256 dd62a901791b72784d18556c834d7d37e7e21a3c286144f253415d3d6637e802

See more details on using hashes here.

Provenance

The following attestation bundles were made for sendspin-5.8.0.tar.gz:

Publisher: release.yml on Sendspin/sendspin-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sendspin-5.8.0-cp313-cp313-win_amd64.whl.

File metadata

  • Download URL: sendspin-5.8.0-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 101.8 kB
  • Tags: CPython 3.13, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for sendspin-5.8.0-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 5c9c5ff96f597c2c5524e96266135fcd9394968bb40b941bd8829d0c92951e99
MD5 740f406c832e91f528fdda17e33f5843
BLAKE2b-256 579b189835a4c1170b425a9a45b53681607947541d7180d52aa647a423610cda

See more details on using hashes here.

Provenance

The following attestation bundles were made for sendspin-5.8.0-cp313-cp313-win_amd64.whl:

Publisher: release.yml on Sendspin/sendspin-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sendspin-5.8.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for sendspin-5.8.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 07a539bda1523f722944d56db4c18efa106ee6d00abc5c39d493ae70ee25ce2e
MD5 753064ecbb0fb53c29520168279aacb0
BLAKE2b-256 ed6a560cc80889dadad5cb6ffc9e0c627652fa1a2f62721312948954939b7d72

See more details on using hashes here.

Provenance

The following attestation bundles were made for sendspin-5.8.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl:

Publisher: release.yml on Sendspin/sendspin-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sendspin-5.8.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl.

File metadata

File hashes

Hashes for sendspin-5.8.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
Algorithm Hash digest
SHA256 3ae744ab34c23de11b2cb92a78bfffb0ebff59b0b59d98ed92a5d3b0d5318874
MD5 2194289c9fc6b763afb11eb684a619a3
BLAKE2b-256 47b276fbf0b0afdad7530bbc9cc86486e3e4d259cd765439efa9d7dbff61f12c

See more details on using hashes here.

Provenance

The following attestation bundles were made for sendspin-5.8.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl:

Publisher: release.yml on Sendspin/sendspin-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sendspin-5.8.0-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for sendspin-5.8.0-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 bd63a2f3051fd221e1cf8706b4405339f7e9267a4b17b7e288c500d93caba563
MD5 a788b842b48a4447424735f7eaa0ea0f
BLAKE2b-256 a3110d446e797cdd9d78cca5ff797d0ff61e8e84b2859220bd2545eca4366b2d

See more details on using hashes here.

Provenance

The following attestation bundles were made for sendspin-5.8.0-cp313-cp313-macosx_11_0_arm64.whl:

Publisher: release.yml on Sendspin/sendspin-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sendspin-5.8.0-cp313-cp313-macosx_10_13_x86_64.whl.

File metadata

File hashes

Hashes for sendspin-5.8.0-cp313-cp313-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 ed9b43a4737eae382891983e2a60fc055f35c2b2365956fe9e219ad9f844f9b8
MD5 f0cf8c4a2b17047f990f39d9c2717a1f
BLAKE2b-256 7e1144bd8633bcbfcd6561cc0c64646be4e709885d829d8d830d4b5083ccee7c

See more details on using hashes here.

Provenance

The following attestation bundles were made for sendspin-5.8.0-cp313-cp313-macosx_10_13_x86_64.whl:

Publisher: release.yml on Sendspin/sendspin-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sendspin-5.8.0-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: sendspin-5.8.0-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 101.8 kB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for sendspin-5.8.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 278b8840d5727f545e1703cd758074ce97493a8ff1a404097aa2c852b02c0cf1
MD5 a5a5ad17808f21da5ba9fa27ec90e037
BLAKE2b-256 b819d09de0f5a13013cb5776827daec4af30b6257db77327ff2dc4b31edef49e

See more details on using hashes here.

Provenance

The following attestation bundles were made for sendspin-5.8.0-cp312-cp312-win_amd64.whl:

Publisher: release.yml on Sendspin/sendspin-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sendspin-5.8.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for sendspin-5.8.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 56b5bbbe8f243a6d9edfe81087c60df00ed84d036ad083b394affa2334a4de61
MD5 3f0eab6f0c3020283bc6a13e20ba1f1e
BLAKE2b-256 ff61585d74b772f131f69ba93fac705020e76079d9802acab80715d99888f84d

See more details on using hashes here.

Provenance

The following attestation bundles were made for sendspin-5.8.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl:

Publisher: release.yml on Sendspin/sendspin-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sendspin-5.8.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl.

File metadata

File hashes

Hashes for sendspin-5.8.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
Algorithm Hash digest
SHA256 f7bd30c0053144a79c3837eeed490acfbe10ef2601616c9db6a0ef6a8a43681d
MD5 a18030f44dd90a11d3e01a7cc9481427
BLAKE2b-256 6a43c0f458ae78a48b31c1e8077ddc5fdfa42e3125e36b186da07eef05abb222

See more details on using hashes here.

Provenance

The following attestation bundles were made for sendspin-5.8.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl:

Publisher: release.yml on Sendspin/sendspin-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sendspin-5.8.0-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for sendspin-5.8.0-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 16c93659dbc886dede92dbb66886ceb66fb3e22dfb4259be97ea969a3bf1353f
MD5 4490b18e2930f30aa33cb1f05fbec63a
BLAKE2b-256 05a840e0e6cb91d67f7462f971d4755ed527cef8c93f35af87d14335edecce10

See more details on using hashes here.

Provenance

The following attestation bundles were made for sendspin-5.8.0-cp312-cp312-macosx_11_0_arm64.whl:

Publisher: release.yml on Sendspin/sendspin-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sendspin-5.8.0-cp312-cp312-macosx_10_13_x86_64.whl.

File metadata

File hashes

Hashes for sendspin-5.8.0-cp312-cp312-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 b1706beaa5d656ca4369b168ce40a03db64bd4224f95a619b45117c52c404910
MD5 8d066051ebede7169ca7f6cb1a7acdbf
BLAKE2b-256 22fd4bc8ea140f862300eff06ba73f7afdf09160941b6495dd67c298d165c31f

See more details on using hashes here.

Provenance

The following attestation bundles were made for sendspin-5.8.0-cp312-cp312-macosx_10_13_x86_64.whl:

Publisher: release.yml on Sendspin/sendspin-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page