Record WCPE "The Classical Station" and play it back delayed so the programming lands at the same local clock time for a listener in another timezone. A listener in Bucharest hears the 8 a.m. morning show at their 8 a.m., not at 3 p.m.
Built for a Raspberry Pi: a recorder captures the live stream into hourly segments, and a small HTTP server streams those segments back with a per-listener delay computed from the listener's timezone.
recorder.py → segments/wcpe_YYYYMMDD_HHMMSS.mp3 → server.py → /stream?tz=Europe/Bucharest
↑ ↓
cleanup.py (retention) ffmpeg seek + real-time pipe
- recorder.py —
ffmpegrecords the source stream into 1-hour segments, auto-reconnecting on drop. - server.py — HTTP server. Computes the delay from the listener's timezone (or a fallback), finds the matching segment, and streams it from the right offset via
ffmpeg. - cleanup.py — deletes segments older than the retention window (run on a timer).
- duckdns.sh — optional dynamic-DNS updater so the Pi is reachable by name.
| Path | Purpose |
|---|---|
/ |
Landing page; auto-detects browser timezone, preview player + VLC link |
/stream?tz=<IANA tz> |
Delayed audio stream (e.g. tz=Europe/Bucharest) |
/listen.m3u?tz=<IANA tz> |
Playlist file for VLC / audio apps |
/status?tz=<IANA tz> |
JSON: delay, segment count, buffered hours, readiness |
./setup.sh # installs ffmpeg, venv, systemd units
nano config.yaml # set stream_url, delay, retention, port
sudo systemctl enable --now wcpe-recorder wcpe-server wcpe-cleanup.timer
curl http://localhost:8234/statusThe stream is usable once the buffer has filled past the configured delay
(buffered_hours >= delay_hours in /status).
cp duckdns.env.example duckdns.env # fill in DUCKDNS_DOMAIN + DUCKDNS_TOKEN
crontab -e # */5 * * * * /path/to/cpe/duckdns.shduckdns.env is gitignored — keep your token out of version control.
See config.yaml: source stream_url, storage_dir, segment_seconds,
delay_hours (fallback when no tz given), retention_hours, server_port,
stream_bitrate_kbps.
- Python 3.9+ (
zoneinfo),ffmpeg,pyyaml
- No connection limiting. Each
/streamconnection spawns its ownffmpegprocess; many simultaneous listeners can exhaust a small device. Front with a reverse proxy (nginx) and/or a connection cap for any real exposure. - No TLS / auth. Intended for personal, low-traffic use. Put it behind a reverse proxy if exposing it publicly.
This tool records and time-shifts a third-party broadcast for personal, private listening. WCPE's stream and programming are property of The Classical Station. Respect their terms of use and your local copyright law; do not redistribute recordings.
MIT — see LICENSE. © Eloquentix Inc.