Add recording cleanup container to remove noise files
Alpine-based sdr-cleanup container runs a find loop every 5 minutes, deleting MP3 files under 3 KB (configurable via SIZE_THRESHOLD env var) to keep the web browser and Samba share free of false-positive recordings. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
16
cleanup-recordings.sh
Executable file
16
cleanup-recordings.sh
Executable file
@@ -0,0 +1,16 @@
|
||||
#!/bin/sh
|
||||
# Deletes small MP3 recordings that are likely noise/false positives.
|
||||
# Runs in a loop, intended for use inside a Docker container.
|
||||
#
|
||||
# Environment variables:
|
||||
# SIZE_THRESHOLD - find -size format, e.g. 3k, 5k, 10k (default: 3k)
|
||||
# INTERVAL - seconds between runs (default: 300)
|
||||
|
||||
RECORDINGS_DIR="/recordings"
|
||||
SIZE_THRESHOLD="${SIZE_THRESHOLD:-3k}"
|
||||
INTERVAL="${INTERVAL:-300}"
|
||||
|
||||
while true; do
|
||||
find "$RECORDINGS_DIR" -type f -name '*.mp3' -size "-${SIZE_THRESHOLD}" -mmin +1 -delete
|
||||
sleep "$INTERVAL"
|
||||
done
|
||||
@@ -18,3 +18,15 @@ services:
|
||||
volumes:
|
||||
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
|
||||
- /home/m/recordings:/recordings:ro
|
||||
|
||||
cleanup:
|
||||
image: alpine:latest
|
||||
container_name: sdr-cleanup
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- SIZE_THRESHOLD=3k
|
||||
- INTERVAL=300
|
||||
volumes:
|
||||
- ./cleanup-recordings.sh:/cleanup-recordings.sh:ro
|
||||
- /home/m/recordings:/recordings
|
||||
command: ["/bin/sh", "/cleanup-recordings.sh"]
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-03-21
|
||||
@@ -0,0 +1,42 @@
|
||||
## Context
|
||||
|
||||
The SDR recorder running in Docker on `sdr-pi` writes MP3 files to `/home/m/recordings/` (mounted from the host). Despite squelch tuning, many files are noise — today's data shows 91 files totaling 476 KB, with the majority under 2 KB. These clutter the Nginx web browser and Samba share, making it hard to find real transmissions.
|
||||
|
||||
The recorder container runs as root (required for USB/SDR hardware access) and writes files owned by root, so cleanup must also run as root.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
- Automatically remove recordings that are too small to contain real audio
|
||||
- Make the size threshold easily adjustable via environment variable
|
||||
- Keep everything version-controlled in docker-compose
|
||||
- Run frequently enough that the web/Samba views stay clean
|
||||
|
||||
**Non-Goals:**
|
||||
- Duration-based or content-based analysis (too complex, needs extra tools)
|
||||
- Age-based retention policy (handled manually for now)
|
||||
|
||||
## Decisions
|
||||
|
||||
### Dedicated cleanup container in docker-compose
|
||||
Add a lightweight Alpine container (`sdr-cleanup`) to docker-compose that shares the `/home/m/recordings` volume. This follows Docker's separation-of-concerns model — one container per responsibility. The container runs a simple `find -delete` loop with `sleep` instead of requiring a cron daemon. Since it runs as root (Alpine default), it can delete the root-owned files written by the recorder.
|
||||
|
||||
Alternatives considered:
|
||||
- **Host crontab**: Simplest, but files are root-owned so needs `sudo crontab`, and isn't version-controlled in docker-compose
|
||||
- **Cron inside recorder container**: Not our image, would need custom build
|
||||
- **Systemd timer on host**: More ceremony than cron for the same result
|
||||
|
||||
### File size threshold as the filter heuristic
|
||||
Use file size (default 3 KB) rather than MP3 duration. This avoids needing `ffprobe` or similar tools. From today's data, files under 3 KB are consistently noise — real transmissions start around 5 KB. Configurable via `SIZE_THRESHOLD` environment variable in docker-compose.
|
||||
|
||||
### 5-minute sleep loop
|
||||
Run every 5 minutes via `sleep 300` in a loop. Lightweight and keeps the browsing experience clean.
|
||||
|
||||
### Only delete files older than 1 minute
|
||||
Add a minimum age filter (`-mmin +1`) to avoid deleting files still being written by rtl_airband.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- **Threshold too aggressive** → Real short transmissions deleted. Mitigation: start conservative at 3 KB, tune via environment variable.
|
||||
- **Race condition with active writes** → The `-mmin +1` guard ensures we never delete a file rtl_airband is still writing.
|
||||
- **Container restart** → If the cleanup container crashes, `restart: unless-stopped` brings it back. No state to lose.
|
||||
@@ -0,0 +1,25 @@
|
||||
## Why
|
||||
|
||||
Despite tuning squelch thresholds and FFT settings, the SDR recorder still produces many small files triggered by noise rather than real CB transmissions. These clutter the web browser and Samba share, making it tedious to find actual recordings. A periodic cleanup job will automatically remove files that are too small to contain meaningful audio.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Add a cleanup shell script that deletes MP3 files below a configurable size threshold (default: 3 KB)
|
||||
- Install a cron job on the Pi host that runs the script frequently (every 5 minutes)
|
||||
- The script and cron entry are version-controlled in this repo for documentation and tunability
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
- `recording-cleanup`: Automated periodic deletion of recordings below a configurable file-size threshold
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
None.
|
||||
|
||||
## Impact
|
||||
|
||||
- New file: cleanup script in the repo, deployed to the Pi host
|
||||
- Host crontab on `sdr-pi` will be modified to schedule the job
|
||||
- Recordings directory (`/home/m/recordings/`) will have small files automatically removed
|
||||
- No container or docker-compose changes required — this runs directly on the host
|
||||
@@ -0,0 +1,37 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Cleanup script removes small recordings
|
||||
The system SHALL provide a shell script that deletes MP3 files below a configurable size threshold from the recordings directory. The default threshold SHALL be 3 KB (3072 bytes).
|
||||
|
||||
#### Scenario: File below threshold is deleted
|
||||
- **WHEN** a `.mp3` file in `/home/m/recordings/` is smaller than the configured size threshold and older than 1 minute
|
||||
- **THEN** the file is deleted
|
||||
|
||||
#### Scenario: File above threshold is preserved
|
||||
- **WHEN** a `.mp3` file in `/home/m/recordings/` is equal to or larger than the configured size threshold
|
||||
- **THEN** the file is not deleted
|
||||
|
||||
#### Scenario: File currently being written is preserved
|
||||
- **WHEN** a `.mp3` file in `/home/m/recordings/` was modified less than 1 minute ago
|
||||
- **THEN** the file is not deleted, regardless of size
|
||||
|
||||
### Requirement: Cleanup runs on a schedule
|
||||
The system SHALL execute the cleanup script via a cron job on the Pi host, running every 5 minutes.
|
||||
|
||||
#### Scenario: Periodic execution
|
||||
- **WHEN** 5 minutes have elapsed since the last run
|
||||
- **THEN** the cleanup script executes and removes qualifying files
|
||||
|
||||
### Requirement: Size threshold is configurable
|
||||
The cleanup script SHALL accept the size threshold as a parameter, allowing adjustment without editing the script.
|
||||
|
||||
#### Scenario: Custom threshold
|
||||
- **WHEN** the script is invoked with a size argument (e.g., `5k`)
|
||||
- **THEN** only files below that size are deleted instead of the default 3 KB
|
||||
|
||||
### Requirement: Cleanup script is version-controlled
|
||||
The cleanup script SHALL be stored in the project repository so that changes are tracked and deployable.
|
||||
|
||||
#### Scenario: Script lives in repo
|
||||
- **WHEN** a developer checks the repository
|
||||
- **THEN** the cleanup script is present at a well-known path with documentation of its purpose
|
||||
@@ -0,0 +1,18 @@
|
||||
## 1. Cleanup Script
|
||||
|
||||
- [x] 1.1 Create `cleanup-recordings.sh` in the repo with configurable size threshold (default 3k), `-mmin +1` safety guard, targeting `/recordings`
|
||||
- [x] 1.2 Make the script executable and add a usage comment at the top
|
||||
|
||||
## 2. Docker Compose
|
||||
|
||||
- [x] 2.1 Update `cleanup-recordings.sh` to run as a loop with sleep instead of one-shot, read threshold from `SIZE_THRESHOLD` env var
|
||||
- [x] 2.2 Add `sdr-cleanup` service to `docker-compose.yml` using `alpine` image, mounting the recordings volume and running the script
|
||||
|
||||
## 3. Deployment Cleanup
|
||||
|
||||
- [x] 3.1 Remove the host crontab entry installed earlier on `sdr-pi`
|
||||
- [x] 3.2 Remove the script copy from `/home/m/cleanup-recordings.sh` on `sdr-pi`
|
||||
|
||||
## 4. Verification
|
||||
|
||||
- [x] 4.1 Deploy updated docker-compose to `sdr-pi` and confirm the cleanup container starts and deletes small files
|
||||
35
openspec/specs/recording-cleanup/spec.md
Normal file
35
openspec/specs/recording-cleanup/spec.md
Normal file
@@ -0,0 +1,35 @@
|
||||
### Requirement: Cleanup script removes small recordings
|
||||
The system SHALL provide a shell script that deletes MP3 files below a configurable size threshold from the recordings directory. The default threshold SHALL be 3 KB (3072 bytes).
|
||||
|
||||
#### Scenario: File below threshold is deleted
|
||||
- **WHEN** a `.mp3` file in `/home/m/recordings/` is smaller than the configured size threshold and older than 1 minute
|
||||
- **THEN** the file is deleted
|
||||
|
||||
#### Scenario: File above threshold is preserved
|
||||
- **WHEN** a `.mp3` file in `/home/m/recordings/` is equal to or larger than the configured size threshold
|
||||
- **THEN** the file is not deleted
|
||||
|
||||
#### Scenario: File currently being written is preserved
|
||||
- **WHEN** a `.mp3` file in `/home/m/recordings/` was modified less than 1 minute ago
|
||||
- **THEN** the file is not deleted, regardless of size
|
||||
|
||||
### Requirement: Cleanup runs on a schedule
|
||||
The system SHALL execute the cleanup script via a cron job on the Pi host, running every 5 minutes.
|
||||
|
||||
#### Scenario: Periodic execution
|
||||
- **WHEN** 5 minutes have elapsed since the last run
|
||||
- **THEN** the cleanup script executes and removes qualifying files
|
||||
|
||||
### Requirement: Size threshold is configurable
|
||||
The cleanup script SHALL accept the size threshold as a parameter, allowing adjustment without editing the script.
|
||||
|
||||
#### Scenario: Custom threshold
|
||||
- **WHEN** the script is invoked with a size argument (e.g., `5k`)
|
||||
- **THEN** only files below that size are deleted instead of the default 3 KB
|
||||
|
||||
### Requirement: Cleanup script is version-controlled
|
||||
The cleanup script SHALL be stored in the project repository so that changes are tracked and deployable.
|
||||
|
||||
#### Scenario: Script lives in repo
|
||||
- **WHEN** a developer checks the repository
|
||||
- **THEN** the cleanup script is present at a well-known path with documentation of its purpose
|
||||
Reference in New Issue
Block a user