Skip to content

Commit 6e485ba

Browse files
authored
feat: add recursive directory support (#11)
* feat: add recursive directory support Mirror source folder hierarchy (Artist/Album) in all output directories. Flat source folders continue to work unchanged. Closes #10 * fix: address CodeRabbit review feedback - Handle directory move/delete events in watcher (clean mirrored subtrees) - Guard orphan cleanup when source has no audio files (prevent data loss) - Log exception in _cleanup_orphans instead of bare except - Clean empty output subdirectories immediately on file deletion - NFC-normalize directory paths in verify_sync get_rel_stem - Add text language tag to README code fence - Fix unused variable warnings (Ruff B007) * fix: guard directory deletion against root/outside paths and unblock watcher thread - Reject rel_dir=="." or ".." prefixes in _handle_directory_delete to prevent wiping entire output directories when source root is deleted - Add safety_guard_active check to directory-level deletions - Offload directory move reprocessing to a background thread so the watchdog dispatcher is not blocked by per-file sleep+encode - Move os import to module scope, remove unused get_output_file_path import
1 parent c6c94ed commit 6e485ba

11 files changed

Lines changed: 519 additions & 202 deletions

File tree

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
name: Docker Hub Description
2+
3+
on:
4+
push:
5+
branches: [main]
6+
paths: [README.md]
7+
workflow_dispatch:
8+
9+
jobs:
10+
update-description:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v4
14+
15+
- uses: peter-evans/dockerhub-description@v4
16+
with:
17+
username: ${{ secrets.DOCKERHUB_USERNAME }}
18+
password: ${{ secrets.DOCKERHUB_TOKEN }}
19+
repository: drumsergio/audio-transcoder

‎README.md‎

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ Perfect for maintaining a music library in multiple formats -- lossless for arch
3434
## Features
3535

3636
- **Real-time file watching** -- Detects new, modified, renamed, or deleted files via watchdog
37+
- **Recursive directory support** -- Mirrors source folder hierarchy (Artist/Album) in all outputs
3738
- **Multiple simultaneous outputs** -- Transcode to any number of formats in a single pass
3839
- **Six codecs** -- ALAC, AAC, MP3, Opus, FLAC, WAV with configurable bitrates
3940
- **Synced lyrics** -- Auto-fetches `.lrc` lyrics with Whisper speech-to-text fallback
@@ -75,7 +76,7 @@ outputs:
7576
```yaml
7677
services:
7778
audio-transcoder:
78-
image: drumsergio/audio-transcoder:0.4.1
79+
image: drumsergio/audio-transcoder:0.5.0
7980
container_name: audio_transcoder
8081
environment:
8182
- TZ=Europe/Madrid
@@ -106,7 +107,7 @@ docker run -d \
106107
-v /path/to/flac:/music/flac:ro \
107108
-v /path/to/mp3:/music/mp3 \
108109
--restart unless-stopped \
109-
drumsergio/audio-transcoder:0.4.1
110+
drumsergio/audio-transcoder:0.5.0
110111
```
111112

112113
## Configuration
@@ -198,6 +199,26 @@ environment:
198199
3. **Orphan cleanup** -- Removes output files that no longer have a matching source.
199200
4. **Lyrics sync** -- Fetches synced `.lrc` lyrics from online databases; falls back to Whisper transcription when no lyrics are found.
200201

202+
### Recursive Directory Support
203+
204+
Source folder hierarchy is automatically mirrored in all outputs. Both flat and nested structures work out of the box -- no configuration needed.
205+
206+
```text
207+
Source: Output (MP3):
208+
/music/flac/ /music/mp3/
209+
├── Artist A/ ├── Artist A/
210+
│ ├── Album 1/ │ ├── Album 1/
211+
│ │ ├── 01 - Track.flac │ │ ├── 01 - Track.mp3
212+
│ │ └── 02 - Track.flac │ │ └── 02 - Track.mp3
213+
│ └── Album 2/ │ └── Album 2/
214+
│ └── 01 - Song.flac │ └── 01 - Song.mp3
215+
└── Artist B/ └── Artist B/
216+
└── Live Album/ └── Live Album/
217+
└── 01 - Intro.flac └── 01 - Intro.mp3
218+
```
219+
220+
When source files or directories are deleted, the corresponding outputs and empty directories are cleaned up automatically.
221+
201222
### Safety Guards
202223

203224
The service includes multiple guards to prevent data loss:

‎docs/ROADMAP.md‎

Lines changed: 35 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,91 +1,71 @@
11
# Roadmap
22

3-
Future improvements and features for audio-transcode-watcher.
3+
Current version: **0.5.0**
44

5-
## v0.2.0 - Quality of Life
5+
## Completed
6+
7+
- **Parallel encoding** with configurable workers (v0.1.0)
8+
- **Lossless source priority** over MP3 duplicates (v0.1.1)
9+
- **Stale temp file cleanup** on startup (v0.1.2)
10+
- **Synced lyrics sidecar** (.lrc) copying to outputs (v0.2.0)
11+
- **Auto-fetch synced lyrics** via syncedlyrics providers (v0.3.0)
12+
- **Whisper local transcription fallback** for lyrics (v0.4.0)
13+
- **Recursive directory support** -- mirror source folder hierarchy in outputs (v0.5.0)
14+
15+
## v0.6.0 -- Quality of Life
616

717
- [ ] **Progress reporting during initial sync**
8-
- Show progress bar or percentage during bulk encoding
9-
- Estimated time remaining
18+
- Show file count progress (e.g. 42/500)
19+
- Log estimated time remaining for large libraries
20+
21+
- [ ] **Graceful shutdown**
22+
- Complete in-progress encodes before stopping
23+
- Resume interrupted syncs on next startup
24+
25+
- [ ] **Dry-run mode**
26+
- Preview what would be encoded without doing it
27+
- Useful for testing configuration changes
28+
29+
## v0.7.0 -- Observability
1030

1131
- [ ] **Health check endpoint**
1232
- HTTP endpoint for container health monitoring
1333
- Prometheus metrics (files processed, errors, queue size)
1434

15-
- [ ] **Graceful shutdown**
16-
- Complete in-progress encodes before stopping
17-
- Resume interrupted syncs
18-
19-
## v0.3.0 - Advanced Features
35+
- [ ] **Notifications**
36+
- Webhook/Shoutrrr support for encoding events
37+
- Error alerts for failed encodes
2038

21-
- [ ] **Folder structure preservation**
22-
- Option to mirror source folder hierarchy in outputs
23-
- Support for Artist/Album/Track structure
39+
## v0.8.0 -- Smart Encoding
2440

25-
- [ ] **Quality profiles**
26-
- Pre-defined quality presets (high, medium, low)
27-
- Per-folder quality overrides
41+
- [ ] **FFmpeg multi-output (tee muxer)**
42+
- Single decode pass, multiple encodes
43+
- Significant CPU reduction for multi-output configurations
2844

29-
- [ ] **Smart re-encoding**
30-
- Detect source file changes (checksum-based)
31-
- Only re-encode when source actually changed, not just touched
45+
- [ ] **Checksum-based re-encoding**
46+
- Detect actual content changes vs. metadata-only touches
47+
- Skip re-encode when source content is unchanged
3248

3349
- [ ] **Replay gain support**
3450
- Calculate and embed replay gain tags
3551
- Album and track gain modes
3652

37-
## v0.4.0 - Performance & Scalability
38-
39-
- [ ] **FFmpeg multi-output**
40-
- Single decode, multiple encodes (FFmpeg tee muxer)
41-
- Reduces CPU usage for multiple outputs from same source
42-
43-
- [ ] **Distributed encoding**
44-
- Queue-based architecture (Redis/RabbitMQ)
45-
- Multiple worker nodes for large libraries
46-
47-
- [ ] **GPU acceleration**
48-
- NVENC/VAAPI support for compatible codecs
49-
- Hardware-accelerated AAC encoding
50-
51-
## v0.5.0 - User Experience
52-
53-
- [ ] **Web UI dashboard**
54-
- Real-time encoding status
55-
- Queue management
56-
- Configuration editor
57-
58-
- [ ] **Notifications**
59-
- Webhook support for encoding events
60-
- Discord/Telegram/Email notifications
61-
- Error alerts
62-
63-
- [ ] **Dry-run mode**
64-
- Preview what would be encoded without doing it
65-
- Useful for testing configuration changes
66-
6753
## Future Ideas (Backlog)
6854

6955
### Format Support
7056
- [ ] Ogg Vorbis output codec
71-
- [ ] WavPack input support
7257
- [ ] DSD/DSF input support (convert to PCM first)
73-
- [ ] Multi-channel audio handling (5.1 → stereo downmix option)
58+
- [ ] Multi-channel audio handling (5.1 to stereo downmix option)
7459

7560
### Metadata
76-
- [ ] Lyrics preservation (embedded and .lrc sidecar)
7761
- [ ] MusicBrainz integration for missing metadata
78-
- [ ] Custom metadata mapping rules
7962
- [ ] Chapter markers for audiobooks
8063

8164
### Integration
8265
- [ ] Plex/Jellyfin library refresh triggers
8366
- [ ] Lidarr/Beets integration
84-
- [ ] S3/MinIO source and destination support
85-
- [ ] SFTP/SMB remote sources
8667

8768
### Analysis
88-
- [ ] Audio quality analysis (clipping detection)
8969
- [ ] Loudness normalization (EBU R128)
9070
- [ ] Silence trimming option
9171
- [ ] Duplicate detection

‎pyproject.toml‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ build-backend = "hatchling.build"
44

55
[project]
66
name = "audio-transcode-watcher"
7-
version = "0.4.2"
7+
8+
version = "0.5.0"
9+
810
description = "Watch a source folder and automatically transcode audio files to multiple formats"
911
readme = "README.md"
1012
license = "GPL-3.0-or-later"

0 commit comments

Comments
 (0)