Skip to main content

Station Server

Puts a station-studio playlist on air. It plays the week's tracks in order, in real time, and sends them straight to your SHOUTcast or Icecast server with each song's title. That replaces iTunes playing out of the headphone jack, the loopback cable, and Winamp with the SHOUTcast DSP plugin.

No sound card is involved: the music files are decoded, joined and encoded inside Station Server. Nothing else playing on the computer (a YouTube video, system sounds) can reach the broadcast, and one computer can run both stations.

Status: 0.4: an app you download and install, running as many stations as you like on one computer, that updates itself. Each station has its own playlist, server and play log. See the plan.

Install

Download (no Python or terminal needed): a Mac .dmg (Apple Silicon or Intel) or a Windows setup .exe, each with its own ffmpeg. They're on each server-v… release of this repository. They're also built for every pull request that changes Station Server: open the pull request's Checks › Station Server installers run, and download from its Artifacts.

  • Mac: open the .dmg and drag Station Server to Applications. The first time, macOS says it can't check the app: open System Settings › Privacy & Security and click Open Anyway (the app isn't signed with a paid Apple certificate).
  • Windows: run the setup. If SmartScreen stops it, click More info › Run anyway. It installs for you only, with no administrator password, and adds Station Server to the Start menu.

Then, on the station's computer, turn on Settings › Start Station Server when I log in, so that after a restart, a power cut or Windows updates it starts in the background and puts the stations that were on air back on air. On a Mac it's also started again if it ever stops unexpectedly.

From a checkout (for development, or Linux): you need Python 3.11 or newer and ffmpeg with its MP3 encoder (macOS: brew install ffmpeg; Windows: winget install ffmpeg; or point Station Server at one with --ffmpeg PATH or $STATION_SERVER_FFMPEG).

python -m venv .venv
.venv/bin/pip install ./player ./server      # Windows: .venv\Scripts\pip

Station Server reads playlists with station-player's code, so both are installed. Then run .venv/bin/station-server (Windows: .venv\Scripts\station-server).

You'll also need the music on the computer, and the playlists exported from station-studio (or any iTunes / Music XML).

The app

.venv/bin/station-server

opens Station Server in a window of its own (with Chrome, Edge or Brave; otherwise a browser tab). It keeps running in the background: closing the window doesn't take a station off air, and running the command again just opens the window. Quit in the sidebar stops it.

  1. Add a station. Give it a name and its playlist: a station-studio export, or better its exports folder (~/.station-studio/exports/rebirth-classics), so the newest week is played and next week's is picked up by itself at the end of a track.
  2. Server. SHOUTcast or Icecast, the address and port, and the source password. Test connection checks them without going on air.
  3. Go on air. The station page shows the track playing, the running order with the time each track goes out, and any tracks whose files can't be found.

Joining the week by the clock. The playlist's first track is pinned to the start of the week (Monday 00:00 unless you change it), and the tracks' lengths say when each of the others airs. Go on air on Wednesday afternoon, or restart after a power cut, and the station joins where the clock says, part way into a track. Choose From the top to start at track 1 instead. A playlist shorter than a week loops.

A station that was on air when the app quit goes back on air when it starts. If no track in the playlist can be read, it sends silence and keeps trying rather than dropping off the server.

Play log. Every track played is logged; download a date range as CSV for PRS and PPL returns (the same format as station-player's).

Dock and taskbar icon. In the app window, Settings → Install as app gives Station Server its own icon in the Dock or taskbar, with Add a station and Play log on its menu, and it opens that way from then on. Opened from there while Station Server isn't running, the window starts it (through the station-server:// link the app registers) and waits.

New versions. As in Station Player and Station Studio, a note at the foot of the sidebar says when a new version is out, and Settings › Updates has Check for updates and Update now: the downloaded app fetches the new version from its GitHub release, checks it's the genuine file, and restarts; stations that were on air go back on air. It asks GitHub once a day; turn that off in Settings.

Two stations on one computer. Add a station for each; they run side by side, each with its own playlist, server, clock and play log, and go on and off air separately. Rebirth Classics to shoutcast://…:8000 and Rebirth Radio to shoutcast://…:8002, say, from one PC.

Settings, passwords, play logs and the log file station-server.log are kept in ~/.station-server ($STATION_SERVER_HOME to change it); the settings file is readable by you only. station-server app --port N uses another port than 8770.

From the command line

Check that ffmpeg is found and the playlist's music is all there:

station-server check ~/.station-studio/exports/rebirth-classics-week-12.xml

Record what listeners would hear to an MP3 (and the titles to a .txt beside it):

station-server play week-12.xml --to test.mp3 --once

Go on air

The password is the source password (the one Winamp's DSP plugin uses). Give it with --password, or set STATION_SERVER_PASSWORD so it isn't typed on the command line.

SHOUTcast (DNAS 1.9.x or 2.x). Use the listener port, the one in the station's link; Station Server connects to the port above it, as Winamp does.

station-server play week-12.xml --to shoutcast://81.150.147.206:8000 \
  --name "Rebirth Classics" --genre "Vintage Oldies / Club Classics" \
  --url https://www.rebirthclassics.uk

For stream 2 on a DNAS 2.x add ?sid=2: shoutcast://host:8002?sid=2.

Icecast (2.4 or later), to a mount:

station-server play week-12.xml --to icecast://source@my.server:8000/classics

While it plays, the window shows each track as it starts. Type s and Enter to skip a track; Ctrl+C stops.

Trying it on a Mac with your own Icecast

No station needed: run Icecast on the same Mac and listen in station-player.

brew install ffmpeg icecast
mkdir -p "$(brew --prefix)/var/log/icecast"      # Homebrew doesn't make it
icecast -c "$(brew --prefix)/etc/icecast.xml"    # leave running; Ctrl+C stops

http://localhost:8000 shows Icecast's status page. Its source password is hackme until you change <source-password> (and <admin-password>) in that icecast.xml. In a second terminal run .venv/bin/station-server, add a station with the playlist folder ~/.station-studio/exports/rebirth-classics, server Icecast, localhost, port 8000, mount /classics, password hackme, and go on air. Or from the command line:

.venv/bin/station-server play ~/.station-studio/exports/rebirth-classics/012.xml \
  --to icecast://localhost:8000/classics --password hackme --name "Rebirth Classics"

Then add the station http://localhost:8000/classics in station-player. The title changes with each track, and the status page shows the stream.

No music to hand? python server/tools/make_test_station.py makes a folder of short test songs and a week's station-studio export in ~/station-server-test, and prints the exports folder to use as the playlist. --week 13 adds next week's, to watch the switch-over; --missing adds a song whose file isn't there.

Trying it next to Winamp

Only one source can feed a stream at a time. To compare without taking the station off air, send Station Server to a spare stream: a second DNAS on another port, stream 2 on a DNAS 2.x (?sid=2, set up in its config), or a test Icecast mount. Listen to both in station-player.

Command-line options

Option What it does
--playlist NAME Which playlist, when the XML has several (a full library export)
--music-folder DIR Where to look for tracks that have moved since the XML was made (repeatable)
--remap FROM=TO Rewrite a path prefix, e.g. a Mac library played on a PC: --remap "/Users/rob/Music=D:/Music"
--start N Start at track N
--once Stop at the end of the playlist instead of starting again
--bitrate KBPS MP3 bitrate, 128 by default
--no-level Turn off volume levelling
--name, --genre, --url What the server shows about the station
--public Ask the server to list the station in its directory

How it works

playlist XML ─► each track decoded by ffmpeg ─► mixer (gapless, levelled)
             ─► held to real time ─► one MP3 encoder ─► SHOUTcast / Icecast
  • Gapless. Tracks are joined as raw audio before one encoder, so there's no gap and no reconnect between songs.
  • Volume levelling uses the ReplayGain or iTunes Sound Check values in each file (read by station-player), never boosting more than 10 dB or past the track's peak. Files without them play as they are for now.
  • Titles reach the server when the track is actually heard, not when its audio is first sent.
  • Dropped connection. If the server goes away, Station Server keeps playing and reconnects every 5 seconds. A track it can't read is skipped.

Releasing

Bump the version in server/pyproject.toml and server/station_server/__init__.py, merge, then run Actions › Publish Station Server on main. It tests, makes a draft server-v<version> release, builds the Mac and Windows downloads onto it, and publishes it once they're all there.

Development

cd server
python -m pytest -q

The tests run without ffmpeg, skipping the end-to-end ones; with ffmpeg installed they also play real audio through fake SHOUTcast and Icecast servers.

Metadata

Release files for station-server 0.4.0

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

Source distribution (sdist)

Source distribution for station-server 0.4.0
File Size Uploaded Provenance
station_server-0.4.0.tar.gz 234.6 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for station-server 0.4.0
File Interpreter ABI Platform
station_server-0.4.0-py3-none-any.whl Python 3 none any Details

Total release size: 477.4 kB

Release files / station_server-0.4.0.tar.gz

Download URL station_server-0.4.0.tar.gz
Size 234.6 kB
Tags Source
SHA-256 checksum
How to use checksums
abc5964b934dfa9ffea137c12f5c461f782d025f51495d231abcc283aed03fef
BLAKE2b-256 checksum
How to use checksums
e009da59f0f4d55f2c4135a621eaf077c6e925dfd02b31136a433fd2cd509e53
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 25, 2026.

Transparency log

Release files / station_server-0.4.0-py3-none-any.whl

Download URL station_server-0.4.0-py3-none-any.whl
Size 242.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a57e29359a82b12d7674cdc60d8c33141fbb1b57b0f688038720a7e40d21507d
BLAKE2b-256 checksum
How to use checksums
e35d2a3213fcb6479d58563ebab2caa45da6e075ce7f52b890d1365c2fe7e2b0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 25, 2026.

Transparency log

Security for station-server 0.4.0

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.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for station_server-0.4.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 25, 2026.

Transparency log

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.4.0 This release

2 release files Full 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