pianobar is a free/open-source, console-based client for the personalized online radio Pandora.
Remote Pianobar — a fork of the original pianobar with remote control capabilities. See the Remote Pianobar Features section below for details. Original repository: https://github.com/PromyLOPh/pianobar
- play and manage (create, add more music, delete, rename, …) stations
- rate songs and explain why they have been selected
- upcoming songs/song history
- customize keybindings and text output (see configuration example)
- remote control and eventcmd interface (send tracks to last.fm, for example)
- Remote API for building custom UIs (web, mobile, desktop)
- included modern web UI built with Lit components
- proxy support for listeners outside the USA
Pre-built packages are available on the Releases page. If you have the original pianobar installed, remove it first to avoid conflicts.
Linux (Debian/Ubuntu .deb)
-
Remove existing pianobar if installed:
sudo apt remove pianobar # or, if you installed a .deb named pianobar: # sudo dpkg --remove pianobar
-
Open https://github.com/mr-light-show/remote-pianobar/releases and download the .deb that matches your system:
- Ubuntu 24.04 (Noble), amd64:
remote-pianobar_noble_amd64.deb - Debian Bookworm or similar, arm64:
remote-pianobar_bookworm_arm64.deb - Debian Trixie or similar, arm64:
remote-pianobar_trixie_arm64.deb
- Ubuntu 24.04 (Noble), amd64:
-
Install (substitute your file name):
sudo dpkg -i remote-pianobar_noble_amd64.deb # If you see dependency errors: sudo apt install -f
macOS (.dmg)
-
Remove existing pianobar if installed via Homebrew:
brew uninstall pianobar
-
Open https://github.com/mr-light-show/remote-pianobar/releases and download
remote-pianobar_macos14.dmg. -
Open the DMG, then run the included
install.sh(with sudo) or copy the app to your desired location (see INSTALL.txt in the DMG).
You need the following software to build pianobar:
Linux-specific:
- libasound2 (ALSA library for system volume control)
For WebSocket/Remote API builds (enabled by default):
- libwebsockets ≥ 4.0
- openssl
- Node.js and npm (for building the web UI)
Package installation examples:
On Debian/Ubuntu:
sudo apt-get install build-essential libao-dev libcurl4-openssl-dev \
libgcrypt20-dev libjson-c-dev libavcodec-dev libavformat-dev \
libavutil-dev libavfilter-dev libswresample-dev libasound2-devFor WebSocket builds, also install:
sudo apt-get install libwebsockets-dev nodejs npmOn macOS (via Homebrew):
brew install libao curl libgcrypt json-c ffmpegFor WebSocket builds, also install:
brew install libwebsockets nodeThen type:
gmake clean && gmakeWebSocket/Remote API is included by default. To build without it:
make NOWEBSOCKET=1 clean && make NOWEBSOCKET=1You can run the client directly from the source directory now:
./pianobarOr install it to /usr/local by issuing:
gmake installRemote Pianobar enables real-time communication for custom user interfaces. Build web, mobile, or desktop UIs that control pianobar and receive live updates.
- Real-time playback state updates
- Song metadata (title, artist, album, art URL)
- Station management (list, create, delete, switch)
- Playback control (play, pause, skip, volume)
- Song actions (love, ban, tired, create station)
- Two-way communication via Socket.IO protocol
Audio Library: Remote Pianobar uses miniaudio for audio playback, which provides automatic device switching and cross-platform support. The library is included in the source tree (src/miniaudio.h) and requires no additional dependencies.
To build Remote Pianobar (WebSocket is enabled by default):
make clean && makeOr use the included build script for development:
./build.sh # Standard build
./build.sh debug # Debug build with crash captureAdd these settings to your ~/.config/pianobar/config:
ui_mode = both
websocket_port = 8080
webui_path = ./dist/webuiUI mode options:
cli: Command-line interface only, no remote APIweb: Web-only (daemonizes, runs in background)both: Both CLI and remote API (default, runs in foreground)
When using web mode, pianobar runs as a daemon and you should specify:
ui_mode = web
websocket_port = 8080
webui_path = ./dist/webui
pid_file = /tmp/pianobar.pid
log_file = /tmp/pianobar.logThen start pianobar and it will run in the background. Open http://localhost:8080 in your browser.
When using log_file in daemon mode, the log grows indefinitely. On Linux you
can use logrotate to rotate it by size so the file stays small and rotation is
automatic.
-
Confirm your log file path. In your pianobar config (
~/.config/pianobar/configor~/.pianobar/config), find thelog_filesetting. You need the absolute path for logrotate (e.g./home/pi/.config/pianobar/pianobar.log). If you use~, runecho ~/.config/pianobar/pianobar.logand use the output. -
Install logrotate (if needed). On Debian/Ubuntu/Raspberry Pi OS it is often already installed. Check with
which logrotate. If missing:sudo apt update && sudo apt install logrotate -
Create the logrotate config. Create
/etc/logrotate.d/pianobar:sudo nano /etc/logrotate.d/pianobar
Paste the following. Replace
/path/to/pianobar.logwith your absolute log path from step 1. ReplaceUSERandGROUPwith the owner of the log file. Thesudirective is required when the log is in a world-writable directory (e.g./tmp):/path/to/pianobar.log { su USER GROUP size 5M copytruncate rotate 3 missingok }To find USER and GROUP: run
ls -l /path/to/pianobar.log(third and fourth columns), orid -unandid -gn. -
Set permissions. Logrotate ignores configs writable by group/others:
sudo chmod 644 /etc/logrotate.d/pianobar
-
Test (dry-run). Check for errors without rotating:
sudo logrotate -d /etc/logrotate.d/pianobar
If the log file does not exist yet, that is fine (
missingokallows that). -
Optional: force one rotation. To confirm it works:
sudo logrotate -f /etc/logrotate.d/pianobar
The pianobar daemon keeps running without restart.
-
Automatic runs. logrotate is usually run daily by cron (e.g.
/etc/cron.daily/logrotate). When your log reaches 5 MB (or on the daily run), it will be rotated automatically; up to 3 old files are kept.
Troubleshooting: If rotation never runs, check that the daily job exists
(ls /etc/cron.daily/logrotate) and that the config is not ignored
(permissions 0644; correct su when the log is in /tmp). Run
sudo logrotate -f /etc/logrotate.d/pianobar to force a rotation.
A modern, lightweight web interface is included:
- Built with Lit web components (5KB framework)
- Material Design styling with dark mode
- Real-time updates via remote API
- Mobile-responsive design
- Album art display
- Volume control and playback controls
- Station management
Example of the web UI in web mode (album art, track info, progress, volume, playback controls, station selector):
See webui/README.md for development and build instructions.
The Remote API uses Socket.IO and provides events for:
Client → Server (Commands):
- play, pause, skip
- love_song, ban_song, tired_song
- set_volume
- list_stations, play_station
- create_station, delete_station
Server → Client (Events):
- state_update: Playback state changes
- song_update: New song metadata
- station_update: Station list changes
- volume_update: Volume changes
Connect to ws://localhost:8080 using any Socket.IO client library.
Full protocol documentation available in WEBSOCKET_PROTOCOL.md.
For more information, see:
- Web UI development:
webui/README.md - API protocol:
WEBSOCKET_PROTOCOL.md - Original repository: https://github.com/PromyLOPh/pianobar
User-visible strings for the C player, WebSocket error payloads, daemon, and bundled web UI are maintained in one canonical YAML file per language under locale/ (for example locale/en.yaml). Nested groups in YAML are flattened to dot-separated keys (for example web.ui.cancel, error.ws.network).
Regenerate build artifacts after editing YAML (requires Python 3 with PyYAML):
make locale-codegenThis updates, from every locale/<lang>.yaml:
locale/<lang>— single-linekey = valuefiles consumed by the C locale loader (src/l10n.c)webui/src/locales/<lang>.json— flat JSON for the Lit app (webui/src/i18n.tsviat()/tf())src/l10n_defaults_gen.c— compiled-in fallback table when no external file is found
The root Makefile runs locale-codegen before linking the binary and tests. For web UI–only work, npm test / npm run build under webui/ run make -C .. locale-codegen first via pretest / prebuild.
Runtime lookup order for the C player: optional environment PIANOBAR_LOCALE_DIR/<lang>; then locale/<lang> under $XDG_CONFIG_HOME/pianobar or ~/.config/pianobar; then $PIANOBAR_INSTALL_PREFIX/share/pianobar/locale/<lang> (prefix defaults to /usr/local if unset); finally the embedded defaults from l10n_defaults_gen.c. Set the locale key in the pianobar config (for example locale = de) to choose a language id matching locale/<id>.yaml.
Adding a language: add locale/<id>.yaml (copy en.yaml as a template), run make locale-codegen, and install the generated locale/<id> file with the rest of the locale directory. Smoke test: copy locale/en to locale/de, change one string, set locale = de, and confirm that string appears in the CLI or web UI.
Cross-repo note: Home Assistant (remote-pianobar-ha) and the Lovelace card (remote_pianobar_card) keep their own translation files; when the same user-facing concept appears in more than one repo, align keys and English manually (see .cursor/rules/localization-user-facing.mdc).
Port 80 is a privileged port (below 1024) and requires special permissions. Here are your options:
Option 1: Use setcap (Recommended for development/home use)
Grant pianobar permission to bind to privileged ports without running as root:
# Give pianobar capability to bind to privileged ports
sudo setcap 'cap_net_bind_service=+ep' /usr/local/bin/pianobar
# Verify it worked
getcap /usr/local/bin/pianobarThen configure ~/.config/pianobar/config:
websocket_port = 80
websocket_host = 0.0.0.0Note: You'll need to reapply setcap after each pianobar upgrade/rebuild.
Option 2: Port forwarding with iptables
Keep pianobar on a high port and forward port 80 to it:
# Forward port 80 to port 8080
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
# Make persistent
sudo apt install iptables-persistent
sudo netfilter-persistent saveConfigure ~/.config/pianobar/config:
websocket_port = 8080
websocket_host = 0.0.0.0Access at http://your-ip/ (externally routes to port 8080 internally).
Option 3: Reverse proxy with nginx (Recommended for production)
Install and configure nginx:
sudo apt install nginxCreate /etc/nginx/sites-available/pianobar:
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
}Use long timeouts (e.g. 3600s) for proxy_read_timeout and proxy_send_timeout so the proxy does not close idle WebSocket connections before the server or clients do.
Enable the site:
sudo ln -s /etc/nginx/sites-available/pianobar /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginxConfigure ~/.config/pianobar/config:
websocket_port = 8080
websocket_host = 127.0.0.1This provides better security, logging, and SSL support. Note that websocket_host is set to 127.0.0.1 so only nginx can access pianobar directly.
You can use systemd to automatically start pianobar in daemon mode on boot. This works identically on both headless and GUI Ubuntu installations.
Step 1: Configure pianobar for daemon mode
Create or edit ~/.config/pianobar/config:
# Pandora credentials
user = [email protected]
password = your_password
# Daemon mode settings
ui_mode = web
websocket_port = 8080
websocket_host = 0.0.0.0
# Daemon-specific settings
pid_file = /tmp/pianobar.pid
log_file = ~/.config/pianobar/pianobar.logStep 2: Create systemd user service
Create ~/.config/systemd/user/pianobar.service:
[Unit]
Description=Remote Pianobar Daemon
After=network-online.target
Wants=network-online.target
[Service]
Type=forking
ExecStartPre=/bin/sleep 5
ExecStart=/usr/local/bin/pianobar
Restart=on-failure
RestartSec=10
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=default.targetStep 3: Enable and start the service
# Reload systemd configuration
systemctl --user daemon-reload
# Enable service to start on boot
systemctl --user enable pianobar
# Start service now
systemctl --user start pianobar
# Check status
systemctl --user status pianobarStep 4: Enable lingering for headless systems
On headless systems (no GUI login), the user's systemd manager only starts after login, which never happens. Enable "lingering" to start the user manager at boot:
# Required for headless systems (e.g., Raspberry Pi without desktop)
loginctl enable-linger $USER
# Verify lingering is enabled
loginctl show-user $USER | grep LingerSkip this step if you always log in via GUI or SSH before needing pianobar.
Managing the daemon:
# View logs in real-time
journalctl --user -u pianobar -f
# Stop the service
systemctl --user stop pianobar
# Restart the service
systemctl --user restart pianobar
# Disable autostart
systemctl --user disable pianobarAccess the web interface at http://localhost:8080/ (or use your server's IP if websocket_host is set to 0.0.0.0).
pianobar uses libao and most problems are related to a broken libao configuration. Have a look at issue #167 for example.
No, money is not necessary to continue working on pianobar. There are many other ways to support pianobar: Reporting bugs, creating cool stuff based on pianobar, blogging about it and the most important one: Keeping Pandora alive.
- control-pianobar — Scripts that interact with pianobar entirely through notification bubbles and hotkeys
- pianobar.el — Emacs interface for pianobar
- pianobar-mediaplayer2 — Control pianobar like any other media player through DBUS/MPRIS.
- PianobarNowPlayable — Integrate pianobar with the Now Playing feature of macOS
- pithos — Python/GTK desktop client
- pianod — Pandora UNIX daemon, based on pianobar
- Hermes — Pandora Client for OS X
- Remote pianobar — Fork of pianobar, which includes a HTTP server and serves a Websocket-powered frontend for remote control.
- PandoraBar — Beagleboard-based radio device running pianobar
- Pandora’s Box — Raspberry Pi-based standalone devices running pianobar

