Skip to main content

Samsung Python

Release code license DeepWiki

WAM Bridge

Samsung Shape M5Samsung Shape M5

Windows-first bridge for streaming audio over Wi-Fi to Samsung Wireless Audio Multiroom speakers, including Shape M5 (WAM550/WAM551).

The CLI serves a tokenized local stream and starts it through Samsung's SetUrlPlayback API. The foobar2000 output component sends whatever foobar is playing, including internet radio. Finite share/DLNA playback is available through wambridge-share and foobar's Send to WAM (Share) track context menu, outside the normal PCM output path. The CLI path is hardware-validated; the foobar context-menu integration still needs a physical M5 pass.

Everything here was measured against one physical Shape M5 (SPK-WAM550, firmware WAM550WWB-3117.1). Other models in the family are untested.

Status: working rolling release

Both paths play audio on real hardware. The foobar component passed its full physical checklist on 2026-08-02: a complete 213-second track start to finish at a median 1.00x with every sample between 0.9x and 1.1x, seek, pause and resume, an unattended transition into the next track, internet radio across a 44.1 to 48 kHz switch, and a clean shutdown leaving no FFmpeg or helper behind.

A later full-track M5 recheck on 2026-10-21 did not reproduce that stability on the then-current connection. The older successful run remains historical evidence; see the physical M5 status for the newer failed baseline and what still needs validation.

What works:

  • SSDP discovery, saved devices resolved by stable device ID, playback control, custom radio stations and native TuneIn presets from the CLI.
  • Android adapter with automatic speaker discovery, Wi-Fi handoff recovery, UPnP renderer, Quick Settings tile and widgets, plus native TuneIn browsing with artwork and speaker-side playback controls.
  • foobar2000 2.x x64 output: f32le → FFmpeg FLAC → local HTTP → speaker.
  • Playback → WAM Bridge with emergency stop, standby and raw volume steps.
  • Configuration through %LOCALAPPDATA%\WAMBridge\foobar.ini.

The one limitation worth knowing before you install

The last end-to-end FLAC measurement was 6.7 seconds, before the host buffer was cut by another two seconds. On 2026-08-27 the physical M5 stayed stable with buffer_extra=0: the host queue held about 1.9 s instead of 3.9 s. A fresh ear-to-clock total has not been measured yet, so the old 6.7 s figure is historical rather than a claim about current stock behavior.

Earlier clean runs showed a correct host clock and seekbar, but those results do not establish uninterrupted speaker playback on the current network link. Pause, stop and skip still carry pipeline latency because they act through the PCM path; with hardware_volume=1, the volume slider is routed to the speaker instead. Lowering the bitrate makes the speaker prebuffer worse rather than better, and raising it helped by about a second in the older measurements. The remaining latency-sensitive controls belong on the speaker's own 55001 command path, which answers in about a second, rather than to keep shortening the audio path; that work is in progress.

Everything else is documented honestly, including the approaches that failed:

  • helper isolation (PR #2) and the output clock (PR #21) are merged,
  • manual pacing (PR #4) and the large share experiment (PR #7) are closed, with their measured conclusions kept.

Current architecture, failed approaches and continuation notes are in docs/DEVELOPMENT_STATUS.md. Measured protocol facts from a physical SPK-WAM550 are in docs/WAM_PROTOCOL.md. For the maintained guides, checklists and publishing instructions, use the documentation index.

Foobar2000 output

Normal rolling release: latest, rebuilt whenever tested main moves. It is a regular GitHub Release, not a pre-release. The tag and download links stay put while the component/APK assets are replaced from the same commit. The displayed version still comes from version in pyproject.toml; Android versionCode keeps rising independently for upgrades.

Each rolling release contains:

  • foo_out_wam.fb2k-component - the foobar2000 output
  • wambridge-<version>.apk - the signed Android adapter
  • a source archive

Open the .fb2k-component file with foobar2000 2.x x64, then select:

Preferences → Playback → Output → Samsung M5 (Wi-Fi)

This project is built primarily against one physical M5. The core transport has repeated hardware validation and Android now covers discovery, renderer/radio controls, MediaSession, widgets and speaker-side sleep controls, but other Shape models remain largely untested and some hardware-specific follow-up is still documented. If you own a Shape speaker and were looking for exactly this, read the limitation above and the release notes first.

Configuration, known limitations and the physical checklist are documented in foobar/README.md.

Requirements

  • Python 3.14+
  • FFmpeg available in PATH
  • computer and speaker reachable in the same LAN
  • Windows 10/11 and foobar2000 2.x x64 for the native output component
  • Windows Firewall access for the bridge on private networks

Install the CLI

git clone https://github.com/travnie/wambridge.git
cd wambridge
py -m venv .venv
.\.venv\Scripts\Activate.ps1
py -m pip install -e .

Confirm FFmpeg is visible:

ffmpeg -version

Discover speakers

wambridge --discover

Discovery sends repeated SSDP requests through active IPv4 adapters. When old firmware stays silent, it can fall back to checking Samsung's API on port 55001 in nearby /24 networks.

Useful diagnostics:

wambridge --discover --verbose
wambridge --discover --interface 192.168.1.25
wambridge --discover --no-scan

Saved devices

Save a speaker under an alias instead of relying on its DHCP address:

wambridge --speaker 10.0.0.118 --remember M5
wambridge --list-devices
wambridge --device M5 --probe
wambridge "D:\Music\track.opus" --device M5

The profile stores the stable Samsung device_id and caches the latest working IP. If the address changes, WAM Bridge searches the LAN for the same device and updates the profile.

On Windows profiles are stored in:

%LOCALAPPDATA%\WAMBridge\devices.json

The foobar2000 component passes the configured alias to the same helper and profile resolver.

Remove a saved profile:

wambridge --forget M5

Startup volume safety

The tested Shape M5 firmware uses raw API volume steps 0..30. Values above 30 are silently clamped to maximum while still returning success. The current client has not yet implemented model-aware percentage conversion, so treat volume arguments as raw M5 steps:

  • 3 is approximately 10 percent,
  • 6 is approximately 20 percent,
  • 30 is maximum.

Old WAM firmware may jump to a high level while switching to URL playback. WAM Bridge mutes the speaker, starts the stream with 1.5 seconds of silence and then applies the requested bounded step after decoding begins.

Choose a cautious explicit level:

wambridge "D:\Music\track.opus" --device M5 --volume 3

Change only the startup ceiling while preserving quieter current settings:

wambridge "D:\Music\track.opus" --device M5 --max-start-volume 3

Remote control

wambridge --device M5 --status
wambridge --device M5 --set-volume 3
wambridge --device M5 --mute
wambridge --device M5 --unmute
wambridge --device M5 --pause
wambridge --device M5 --play
wambridge --device M5 --stop
wambridge --device M5 --standby

Native providers such as TuneIn use their CPM commands. DLNA uses UIC pause and resume. Samsung URL playback cannot be resumed reliably, so starting the source again creates a new session.

Radio stations

Save a direct HTTP or HTTPS audio stream. Fallback URLs are tried in order:

wambridge --radio-add paradise "https://primary.example/radio.mp3" `
  "https://backup.example/radio.ogg"
wambridge --radio-list
wambridge --radio-play paradise --device M5 --volume 3
wambridge --radio-remove paradise

A station can also carry its TuneIn id. The id is resolved when the station is played, so it follows the broadcaster if the stream address moves - the URLs saved beside it stay as fallbacks for when TuneIn cannot be reached or offers nothing usable:

wambridge --radio-add trojka "http://41.dktr.pl:8000/trojka.ogg" --tunein-id s15984

Station definitions are stored in:

%LOCALAPPDATA%\WAMBridge\stations.json

Import the bundled BBC Radio 1, PR3 Trójka and PR4 Czwórka pack:

wambridge --radio-import top3
wambridge --radio-list
wambridge --radio-play bbc1 --device M5 --volume 3
wambridge --radio-play trojka --device M5 --volume 3
wambridge --radio-play czworka --device M5 --volume 3

These are WAM Bridge stations and do not overwrite the three presets selected by the physical button on the speaker.

Native TuneIn presets

Read and start TuneIn presets already stored by the speaker:

wambridge --device M5 --tunein-list
wambridge --device M5 --tunein-play 0 --volume 3
wambridge --device M5 --tunein-play "Radio Paradise" --volume 3

Preset write commands are available: adjacent my moves were hardware-tested, but saving, removing and moving into physical slots 0-2 remain unverified. Back up --tunein-list first; --tunein-remove has no undo:

wambridge --device M5 --tunein-save
wambridge --device M5 --tunein-remove 3
wambridge --device M5 --tunein-move 1 2 0

Android has no equivalent yet; writing presets from the phone still goes through Samsung's own app.

Browsing and searching TuneIn

The whole TuneIn catalogue is reachable without saving anything as a preset. --tunein-browse walks the tree; a path is the row numbers of the pages above, separated by slashes. --tunein-search finds a station by name. Both are paginated, so --tunein-start moves the window.

wambridge --device M5 --tunein-browse
wambridge --device M5 --tunein-browse 1/0
wambridge --device M5 --tunein-search "Radio Paradise"
wambridge --device M5 --tunein-search "jazz" --tunein-start 30

Rows print as index<TAB>kind<TAB>mediaid<TAB>title. The mediaid is the stable TuneIn station id, so it is what goes into --radio-add --tunein-id; the leading index only means "this row on this page" and changes as you move.

The speaker keeps the browse cursor itself, so a search leaves it in TuneIn's search results rather than the catalogue. --tunein-browse notices and steps back on its own.

Direct playback

wambridge --speaker 192.168.1.50 --probe
wambridge "https://example.net/radio-stream" --speaker 192.168.1.50
wambridge "D:\Music\track.opus" --speaker 192.168.1.50
wambridge "D:\Music\track.ogg" --speaker 192.168.1.50

Use MP3 output when FLAC is unstable on a particular firmware:

wambridge "D:\Music\track.opus" --speaker 192.168.1.50 --format mp3

When exactly one WAM speaker is discovered, --speaker may be omitted.

Notes

  • The local URL stream uses HTTP/1.0 without chunked transfer for old-firmware compatibility.
  • The URL contains a random session token and exists only while the command is running.
  • Do not expose port 55001 or a bridge HTTP port to the internet.
  • The tested M5 does not expose a standard UPnP AVTransport renderer. See the protocol notes before restarting generic UPnP work.
  • SetUrlPlayback may freeze malformed firmware when the served body is not playable audio. The bridge exposes only FFmpeg output and returns 404 for other paths.

Validate

py -m unittest discover -s tests -v

📰 Mininewsy

💬 Cytat z szuflady

❝E-Mail was invented before Internet. Shocked!!!! ” I also got shocked after hearing this.”❞

Python package / PyPI

The Python CLI is prepared for public release as trvny-wambridge. Build artifacts and Trusted Publishing setup live in PyPI publishing guide. After the first upload to PyPI, install with uv tool install trvny-wambridge; the foobar2000 plugin remains a separate .fb2k-component release.

Metadata

Release files for trvny-wambridge 0.0.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for trvny-wambridge 0.0.5
File Size Uploaded Provenance
trvny_wambridge-0.0.5.tar.gz 165.3 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for trvny-wambridge 0.0.5
File Interpreter ABI Platform
trvny_wambridge-0.0.5-py3-none-any.whl Python 3 none any Details

Total release size: 275.7 kB

Release files / trvny_wambridge-0.0.5.tar.gz

Download URL trvny_wambridge-0.0.5.tar.gz
Size 165.3 kB
Tags Source
SHA-256 checksum
How to use checksums
2644179550890afc282fb05084784e641ffcac85c502aee69635cd4d652b9a36
BLAKE2b-256 checksum
How to use checksums
f5c08d81d7b0e487c4cc9f5f70c5af4121ad0afbed39594abdac1bd1102def46
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / trvny_wambridge-0.0.5-py3-none-any.whl

Download URL trvny_wambridge-0.0.5-py3-none-any.whl
Size 110.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9bbc95f638c8406359306f1368ae4e416cb7dae02f830f0593f58c9818e7dc07
BLAKE2b-256 checksum
How to use checksums
645cda868f45cdd521497fc6e805be677bc22004970326a15d5a88e740cb1adf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for trvny-wambridge 0.0.5

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.0.5 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page