feat(source): add a source@v1 capture client (sendspin source) - #270
feat(source): add a source@v1 capture client (sendspin source)#270rudyberends wants to merge 2 commits into
Conversation
Add a 'sendspin source' command that runs a source client: capture audio from a local input (line-in/microphone) or a sine test tone, encode it (PCM, FLAC, or Opus via PyAV), and stream it to a server, which mixes and distributes it to players. The server controls when the source streams. - source_utils: PyAV SourceEncoder (exposes raw codec header) + RMS level - source_stream: SourceStreamer capture loop (sounddevice / sine), server start/stop handling, optional line-sense signal reporting - cli: 'source' subcommand and 'audio-devices inputs' listing - audio_devices: input-device enumeration - settings: SourceSettings persistence (settings-source.json) - README: source mode documentation
Follow aiosendspin dropping supported_formats from source@v1_support (spec#113). A source announces its capture format per stream in client_stream/start, so advertising it up front negotiated nothing and the field being required made a conforming hello fail to parse. Also spell out in the README that starting a source is a policy the server application makes: the library no longer starts one on its own, so a source pointed at a server that never asks for audio stays idle by design.
|
I tested this branch against Music Assistant's Sendspin server and traced the source connection path. The Observed server behavior:
This means the branch can exercise source streaming in legacy transition mode, but it cannot pair with a current Music Assistant server yet. Secure source support needs to land in |
|
Update to my earlier note: the current upstream path is now clear.
This CLI PR still targets the older API ( No encryption implementation needs to be duplicated in this repository. |
Adds a
sendspin sourcecommand: run as a Sendspin source client that captures audio from a local input (line-in/microphone) or a synthetic sine test tone, encodes it (PCM, FLAC, or Opus via PyAV), and streams it to a server, which mixes and distributes it to players.Implements the client side of the
source@v1role (Sendspin/spec#105).Depends on Sendspin/aiosendspin#286 (the
source@v1protocol + client SDK). Theaiosendspinversion pin here must be bumped to the release that includes it before this can merge — hence draft.Supersedes #123, which targeted the earlier
input_stream/*proposal.What's added
source_utils.py:SourceEncoder(PyAV; PCM passthrough / FLAC / Opus, exposing the raw codec header) + an RMS level metersource_stream.py:SourceStreamer— capture loop (sounddeviceline-in or sine tone), server-driven start/stop, optional line-sense reporting; stamps each frame with its capture timecli.py:sendspin sourcesubcommand andsendspin audio-devices inputslistingaudio_devices.py: input-device enumerationsettings.py:SourceSettingspersistence (settings-source.json)README.md: source-mode documentationCapture is 16-bit; the server handles decode/resample/mix. The server is the sole initiator of streaming (a source stays idle until told to start). A device may run both
sourceandplayer; it never plays its captured input locally.Testing
ruff+mypyclean;pytest: 155 passed (13 new, incl. a cross-repo round-trip: encode with the CLI encoder then decode with the aiosendspin server decoder, for PCM/FLAC/Opus).