feat: name cut clips by wall-clock time; fix recording filename format
Cut downloads were named by byte offsets (`..._cut_740s-750s.flac`). They are now named by the actual recording time the slice covers, e.g. `20260523_22-31-30_22-32-30.flac` for a 22:31:30->22:32:30 cut of a recording started at 22:00:00. To make this reliable, the recording filename is now a fixed `%Y%m%d_%H%M%S` start-time format (`FILENAME_FORMAT`) shared by isr.py and web.py, replacing the user-configurable `filename_pattern` (web.py never reads config.ini, so a custom pattern could not be parsed back). web.py parses the start time out of the filename via `_recording_start()` and builds cut names with `_cut_filename()`. The DATE column now also comes from the filename (falling back to mtime only for non-standard names), since mtime is the last write, not the start. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -67,7 +67,6 @@ docker compose up -d --build
|
||||
|-----|---------|-------------|
|
||||
| `output_directory` | `recordings` | Output path relative to the working directory (or absolute). The Docker setup mounts `./recordings` at `/app/recordings` so this default works unchanged. |
|
||||
| `split_minutes` | `60` | Split into a new file every N minutes, aligned to clock boundaries (e.g. 60 → files start at :00, 30 → at :00 and :30). |
|
||||
| `filename_pattern` | `%Y%m%d_%H%M%S` | strftime pattern; file extension is appended automatically. |
|
||||
| `max_retries` | `10` | Give up after this many consecutive failures per source. |
|
||||
| `retry_delay_seconds` | `5` | Wait between retries. |
|
||||
| `log_level` | `INFO` | `DEBUG` / `INFO` / `WARNING` / `ERROR` / `CRITICAL` |
|
||||
@@ -124,25 +123,17 @@ split_minutes = 60
|
||||
[radio1]
|
||||
type = stream
|
||||
url = http://radio.example.com:8000/stream1
|
||||
filename_pattern = radio1_%Y%m%d_%H%M%S
|
||||
|
||||
[system_audio]
|
||||
type = soundcard
|
||||
device = hw:0,0
|
||||
filename_pattern = system_%Y%m%d_%H%M%S
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Filename patterns
|
||||
## Filenames
|
||||
|
||||
strftime codes are substituted at split time. The file extension is added automatically.
|
||||
|
||||
| Pattern | Example |
|
||||
|---------|---------|
|
||||
| `%Y%m%d_%H%M%S` | `20241225_143000.mp3` |
|
||||
| `radio_%Y-%m-%d_%H%M` | `radio_2024-12-25_1430.mp3` |
|
||||
| `%Y/%m/%d/rec_%H%M%S` | `2024/12/25/rec_143000.mp3` *(subdirs created automatically)* |
|
||||
Recordings are named `<YYYYMMDD>_<HHMMSS>.<ext>` from the time the file is opened — its **start** time — e.g. `20241225_143000.flac`. This format is fixed and not configurable: the web UI parses the start time back out of the filename to show the recording date and to name cut clips with real wall-clock times (see below).
|
||||
|
||||
---
|
||||
|
||||
@@ -169,7 +160,7 @@ Shows recordings grouped by day with collapsible sections. Features:
|
||||
- **Grace period** — configurable in the controls bar (default 2 s). Loud sections separated by less than this gap are merged into one. Raise this (e.g. to 15–30 s) when a single event generates many timestamps due to brief quiet gaps within it.
|
||||
- **Min duration** — configurable in the controls bar (default 0.5 s). Loud sections shorter than this (after grace-period merging) are discarded, so isolated sub-second pops — a click, a single raindrop — don't flood a day with thousands of near-zero-length sections. Set to 0 to disable.
|
||||
- **Clip playback** — clicking a loud-section chip plays a short server-rendered WAV clip (`/api/clip`, pre-roll included) in a player bar at the bottom of the page. Playback starts instantly even for sections deep inside multi-hundred-MB FLACs, because the browser never has to seek the full file. **J** / **K** (or the **Prev** / **Next** buttons) step through the queued sections — one file's, or a whole day's after **Highlights** — and **Auto-advance** plays the next section when one ends, turning a day's detections into a continuous review reel. **Open in file** switches to the full recording at the same position for context; each chip click also pre-fills the cut panel.
|
||||
- **Cut & download** — `Cut` button opens the player row and reveals a cut panel. Enter start and end times in `m:ss` or `h:mm:ss` format and click **Download cut** to receive an ffmpeg-trimmed copy without re-encoding. Requires ffmpeg (included in the Docker image).
|
||||
- **Cut & download** — `Cut` button opens the player row and reveals a cut panel. Enter start and end times in `m:ss` or `h:mm:ss` format and click **Download cut** to receive an ffmpeg-trimmed copy without re-encoding. Requires ffmpeg (included in the Docker image). The cut is named with the real wall-clock span it covers — `<YYYYMMDD>_<HH-MM-SS>_<HH-MM-SS>.<ext>`, e.g. a 22:31:30→22:32:30 slice of a recording started at 22:00:00 becomes `20260523_22-31-30_22-32-30.flac`.
|
||||
- **Filters** — live filename search and from/to date pickers above the table; applied client-side with no additional requests. Shows `N of M shown` when a filter is active.
|
||||
- **Delete** — `Delete` button per row with confirmation prompt; disabled for files currently being recorded; sends `DELETE /api/files/<name>` and re-renders the table.
|
||||
- **Live REC badge** — files currently being written by `isr.py` show an animated REC indicator, polled every 5 seconds via `/api/status`. Duration for in-progress files shows `—` in the table (header is unfinalized until recording stops). The file list refreshes automatically when a recording starts, stops, or rolls over to a new split file (unless audio is playing).
|
||||
|
||||
Reference in New Issue
Block a user