RadioPipe is a lightweight command-line recorder for Ham, CB, and GMRS radio streams delivered over Shoutcast or Icecast. It monitors incoming audio and only records when signal is present using root-mean-square (RMS) activation, so you capture actual transmissions instead of long stretches of silence. It can also read audio from stdin, making it easy to pipe in soundcard input, a DigiRig feed, or any other audio source.
Built for unattended logging, RadioPipe stores WAV clips in date-based folders and names each file with the stream title and timestamp for quick browsing. You can run multiple instances to the same output directory without conflicts as long as each stream name is unique.
--url) or piped audio (--stdin, including raw PCM)--stdout / --stdout-raw)--on-write) for conversion/upload workflows-o ./recordings)A recording path will look like:
./recordings/2026-03-12/2026-03-12_024630_RadPi.wav
Regular builds can be found at radio-pipe downloads (scroll to the bottom)

php/recordings.php provides a web interface for browsing and reviewing recordings.
You only need a PHP-capable web server with these extensions:
The page can be moved or renamed. Point it at your recordings directory by setting a config file.
Create php/config.php (recommended) with the following variables:
<?php
// Settings
$recordingsRoot = '/mnt/Media/recordings';
$PAGE_TITLE = 'Icecast Stream Recordings';
// End Settings
If you are on Windows and want a quick setup, there is an experimental stand-alone package that sets up everything in %APPDATA%.
recordings-browser Installer
You will likely see security warnings because it is a 7zip self-extracting archive.
There is no uninstall, but you can right-click the shortcut, open its location, and delete the folder.

php/rtl_sdr.php is a single-page RTL-SDR control panel + JSON API. It starts and monitors rtl_fm pipelines, then routes audio into radio-pipe (recording), ffmpeg (live Icecast streaming), or both.
It is designed for unattended radio capture setups where you need to tune, monitor, and recover multiple RTL-SDR pipelines from one page.
rtl_sdr.phprtl_fm (rtl-sdr package)radio-pipe in PATH (required for recording and stream conditioning)ffmpeg in PATH (required when stream output is enabled)curl in PATH (required only for After Record upload modes)php/rtl_sdr.php on a PHP-capable web server.php/config.php and set your recordings directory:<?php
$recordingsRoot = '/mnt/Media/recordings';
Local test from this repo:
$ cd php
$ ./server.sh
# then open http://localhost:8000/rtl_sdr.php
rtl_sdr.phprtl_sdr_state.json / rtl_sdr_desired_state.json - running and desired device statertl_sdr_logs/ - per-device launch/runtime logsstreaming_servers.json - saved Icecast targetsrecording_servers.json - saved upload targets for after-record actionsrtl_sdr_templates.json - saved templates/presetsrtl_sdr_ui_settings.json - saved per-device UI settingsRetune actions are queued and applied by watchdog ticks. For unattended operation, install the included systemd timer/service:
$ sudo ./scripts/install_rtl_sdr_watchdog.sh --endpoint http://127.0.0.1/rtl_sdr.php
The watchdog posts action=list&source=watchdog on an interval to process queued retunes and periodic state cleanup.
Basic usage example:

You can run the recorder against either a Shoutcast/Icecast stream URL or audio from stdin.
Recordings are broken into WAV files whenever the stream goes silent and are placed in day‑based folders.
URL example:
$ ./radio-pipe \
-u http://example.com:8000/stream.mp3 \
-o ./recordings \
-x /usr/local/bin/on-clip-written.sh \
-r 8000 -c 1 -b 16
on-clip-written.sh runs after each clip is produced. The full WAV path is passed as argument 1.
stdin example (arecord):
$ arecord -f S16_LE -c 1 -r 8000 -t wav - \
| ./radio-pipe --stdin -o ./recordings
stdin example (sox):
$ sox /path/to/input.mp3 -t wav - \
| ./radio-pipe --stdin -o ./recordings
raw PCM stdin example (arecord):
$ arecord -f S16_LE -c 1 -r 8000 -t raw - \
| ./radio-pipe --stdin --stdin-raw \
--stdin-rate 8000 --stdin-channels 1 --stdin-bits 16 \
-o ./recordings
raw PCM stdout example (gate audio for another program):
$ rtl_fm -f 462.550M -M fm -s 12000 -r 8000 -E deemp -l 25 \
| ./radio-pipe --stdin --stdin-raw \
--stdin-rate 8000 --stdin-channels 1 --stdin-bits 16 \
--dcs 023 \
--stdout --stdout-raw --stdout-pad \
--stdout-rate 8000 --stdout-channels 1 --stdout-bits 16 \
| your-program-that-reads-raw-pcm
The scripts/ directory contains helper scripts for converting recorded WAV files to compressed formats. All scripts require exiftool (sudo apt install -y libimage-exiftool-perl) to preserve the stream title and comment metadata during conversion.
x-convert-mp3.sh — Per-clip MP3 conversion (for -x / --on-write)Converts a single WAV file to MP3 and removes the original on success. Designed to be passed directly to the -x option so each clip is compressed immediately after it is written.
Requires: exiftool, lame (sudo apt install -y lame)
$ ./radio-pipe -u http://example.com:8000/stream.mp3 \
-o ./recordings \
-x ./scripts/x-convert-mp3.sh
x-convert-ogg.sh — Per-clip OGG conversion (for -x / --on-write)Same as x-convert-mp3.sh but produces an Ogg Vorbis file instead of MP3.
Requires: exiftool, oggenc (sudo apt install -y vorbis-tools)
$ ./radio-pipe -u http://example.com:8000/stream.mp3 \
-o ./recordings \
-x ./scripts/x-convert-ogg.sh
bulk-compress-to-mp3.sh — Batch WAV → MP3 conversionWalks a directory tree (passed as the first argument) and converts every WAV file it finds to MP3, removing the original after a successful conversion. Useful as a scheduled cron job to compress an existing archive of recordings.
Requires: exiftool, lame
$ ./scripts/bulk-compress-to-mp3.sh ./recordings
bulk-compress-to-ogg.sh — Batch WAV → OGG conversionSame as bulk-compress-to-mp3.sh but converts to Ogg Vorbis. Can also be run as a cron job.
Requires: exiftool, oggenc
$ ./scripts/bulk-compress-to-ogg.sh ./recordings
rtl-fm-record.sh — RTL-SDR capture helperRuns rtl_fm and pipes raw PCM into radio-pipe using --stdin --stdin-raw.
The script sets stream names as RTLSDR - (<frequency>), so each tuned frequency
is clearly labeled in output filenames and metadata.
Requires:
rtl_fm (from rtl-sdr) (sudo apt install -y rtl-sdr)radio-pipe binary in PATH or pass -e <path>Common examples:
$ ./scripts/rtl-fm-record.sh -f 146.520M -q 20 -o ./recordings
$ ./scripts/rtl-fm-record.sh -f 462.550M -q 25 -R 12000 -o ./recordings
$ ./scripts/rtl-fm-record.sh -f 462.550M -q 25 -D 023 -o ./recordings
$ ./scripts/rtl-fm-record.sh -f 462.550M -q 25 -C 100.0 -o ./recordings
Script options:
-f,--frequency <freq> – required frequency to tune-q,--squelch <level> – rtl_fm squelch level (default 0)-D,--dcs <code> – optional DCS gate code (octal, example 023)-C,--ctcss <hz> – optional CTCSS gate tone in Hz (example 100.0)-R,--sample-rate <hz> – sample rate for both rtl_fm and recorder (default 8000)-o,--out <dir> – output recordings directory (default ./recordings)-e,--exec <path> – path/name of radio-pipe executable-m,--mode <mode> – rtl_fm mode (default fm)-d,--device <index> – rtl_fm device index-g,--gain <gain> – rtl_fm gain value-t,--threshold <db> – recorder silence threshold dB (default -50)-s,--silence <seconds> – recorder silence duration in seconds (default 2)-x,--on-write <program> – recorder on-write hookEvery output format (.wav, .mp3, .ogg) can carry a Comment metadata field.
For the Live Listen feature in the PHP recordings interface, this field must contain
Source URL: http://xyz/abc.mp3, pointing to the original stream.
When recording from --url, RadioPipe writes this source URL into WAV metadata.
If you convert files later, preserve this metadata so Live Listen continues to work.
Use this section as a full reference. If you are skimming, start with the quick map below.
--url or --stdin (exactly one is required)--stdin-raw, --stdin-rate, --stdin-channels, --stdin-bits, --stdin-big-endian, --stdin-unsigned, --input-dejitter-o, clip/WAV stdout with --stdout, raw stdout with --stdout-raw, continuous padded raw stream with --stdout-pad-t, -s, -r, -c, -b--dcs, --ctcss, --gate-holdNaming/automation: -n, -x
-u,--url
250)500)$RADIOPIPE_RECORDINGS or ./recordings; if --stdout is used without -o, file recording is disabled) – optional DCS gate code (octal, example 023); clip audio only while matching DCS is detected100.0); clip audio only while matching tone is detected1)Exactly one input source is required: --url or --stdin.
When using --stdin without --stdin-raw, provide a Java Sound readable stream format (WAV is recommended).
Raw format flags (--stdin-rate, --stdin-channels, --stdin-bits, --stdin-big-endian, --stdin-unsigned) require --stdin-raw.
--input-dejitter adds an input-side jitter buffer so short producer timing gaps (for example, some RTL-SDR pipe bursts) do not immediately create choppy downstream output.
Raw stdout format flags (--stdout-rate, --stdout-channels, --stdout-bits, --stdout-big-endian, --stdout-unsigned) require --stdout-raw.
--stdout-pad requires raw stdout output (--stdout-raw) and emits a continuous gapless stream by maintaining a fixed-depth delay buffer (default 500 ms) pre-filled with silence.
--stdout-pad-delay sets the delay buffer depth in ms; the output stream is always delayed by this amount but never interrupted, even at startup or during input stalls.
When using --dcs, output PCM bit depth must be 16 (--bitrate 16).
When using --ctcss, output PCM bit depth must be 16 (--bitrate 16).
When using both --dcs and --ctcss, both gates must match for clips to open.
--gate-hold adds extra hold time after DCS/CTCSS detection loss to prevent brief weak/noisy decode dropouts from closing the gate immediately (default 1 second).
When using --stdout without -o, recordings are not written to disk (stdout-only mode).
If RADIOPIPE_RECORDINGS is set (and non-empty), it is used as the default recordings directory whenever file recording is enabled and -o does not provide a path (including bare -o).
On Linux/macOS shells, this value must be exported (for example, export RADIOPIPE_RECORDINGS=/path) so child processes like radio-pipe can read it.
Examples for RADIOPIPE_RECORDINGS:
Linux/macOS (bash):
export RADIOPIPE_RECORDINGS=/mnt/Media/recordings
./radio-pipe --url http://example.com/stream.mp3
./radio-pipe --url http://example.com/stream.mp3 --stdout -o
Windows PowerShell:
$env:RADIOPIPE_RECORDINGS = 'D:\Recordings'
.\radio-pipe.exe --url http://example.com/stream.mp3
.\radio-pipe.exe --url http://example.com/stream.mp3 --stdout -o
Windows Command Prompt (cmd.exe):
set RADIOPIPE_RECORDINGS=D:\Recordings
radio-pipe.exe --url http://example.com/stream.mp3
radio-pipe.exe --url http://example.com/stream.mp3 --stdout -o
--stdout by itself remains stdout-only (no disk writes); adding bare -o enables file recording using $RADIOPIPE_RECORDINGS (or ./recordings when unset).
--on-write requires file recording (-o) and is ignored in stdout-only mode.
When recording from --url, filenames default to stream metadata (icy-name/x-audiocast-name/ice-name) unless --name is provided.
WAV files include stream name metadata in the title field.
WAV files written from --url input also include a comment metadata field with the original source URL.
Examples for --on-write:
To compile this project, run:
$ mvn package
from a terminal.
Latest Update: March 19 2026 04:00:04 PM EDT
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.