audio-transcode-watcher 0.4.2__tar.gz → 0.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. audio_transcode_watcher-0.5.0/.coderabbit.yaml +45 -0
  2. audio_transcode_watcher-0.5.0/.github/workflows/dockerhub-description.yml +19 -0
  3. {audio_transcode_watcher-0.4.2 → audio_transcode_watcher-0.5.0}/.github/workflows/release.yml +23 -3
  4. audio_transcode_watcher-0.5.0/.github/workflows/stale.yml +19 -0
  5. {audio_transcode_watcher-0.4.2 → audio_transcode_watcher-0.5.0}/.github/workflows/tests.yml +2 -2
  6. audio_transcode_watcher-0.5.0/AGENTS.md +18 -0
  7. {audio_transcode_watcher-0.4.2 → audio_transcode_watcher-0.5.0}/PKG-INFO +24 -3
  8. {audio_transcode_watcher-0.4.2 → audio_transcode_watcher-0.5.0}/README.md +23 -2
  9. audio_transcode_watcher-0.5.0/docs/ROADMAP.md +88 -0
  10. {audio_transcode_watcher-0.4.2 → audio_transcode_watcher-0.5.0}/pyproject.toml +3 -1
  11. {audio_transcode_watcher-0.4.2 → audio_transcode_watcher-0.5.0}/src/audio_transcode_watcher/sync.py +123 -101
  12. {audio_transcode_watcher-0.4.2 → audio_transcode_watcher-0.5.0}/src/audio_transcode_watcher/utils.py +57 -1
  13. {audio_transcode_watcher-0.4.2 → audio_transcode_watcher-0.5.0}/src/audio_transcode_watcher/watcher.py +45 -9
  14. {audio_transcode_watcher-0.4.2 → audio_transcode_watcher-0.5.0}/tests/test_sync.py +84 -23
  15. {audio_transcode_watcher-0.4.2 → audio_transcode_watcher-0.5.0}/tests/test_utils.py +106 -0
  16. {audio_transcode_watcher-0.4.2 → audio_transcode_watcher-0.5.0}/tools/verify_sync.py +21 -9
  17. {audio_transcode_watcher-0.4.2 → audio_transcode_watcher-0.5.0}/uv.lock +6 -4
  18. audio_transcode_watcher-0.4.2/docs/ROADMAP.md +0 -108
  19. {audio_transcode_watcher-0.4.2 → audio_transcode_watcher-0.5.0}/.github/FUNDING.yml +0 -0
  20. {audio_transcode_watcher-0.4.2 → audio_transcode_watcher-0.5.0}/.github/dependabot.yml +0 -0
  21. {audio_transcode_watcher-0.4.2 → audio_transcode_watcher-0.5.0}/.gitignore +0 -0
  22. {audio_transcode_watcher-0.4.2 → audio_transcode_watcher-0.5.0}/Dockerfile +0 -0
  23. {audio_transcode_watcher-0.4.2 → audio_transcode_watcher-0.5.0}/LICENSE +0 -0
  24. {audio_transcode_watcher-0.4.2 → audio_transcode_watcher-0.5.0}/SECURITY.md +0 -0
  25. {audio_transcode_watcher-0.4.2 → audio_transcode_watcher-0.5.0}/config.example.yaml +0 -0
  26. {audio_transcode_watcher-0.4.2 → audio_transcode_watcher-0.5.0}/docs/images/banner.svg +0 -0
  27. {audio_transcode_watcher-0.4.2 → audio_transcode_watcher-0.5.0}/docs/images/icon.png +0 -0
  28. {audio_transcode_watcher-0.4.2 → audio_transcode_watcher-0.5.0}/docs/images/icon.svg +0 -0
  29. {audio_transcode_watcher-0.4.2 → audio_transcode_watcher-0.5.0}/src/audio_transcode_watcher/__init__.py +0 -0
  30. {audio_transcode_watcher-0.4.2 → audio_transcode_watcher-0.5.0}/src/audio_transcode_watcher/config.py +0 -0
  31. {audio_transcode_watcher-0.4.2 → audio_transcode_watcher-0.5.0}/src/audio_transcode_watcher/encoder.py +0 -0
  32. {audio_transcode_watcher-0.4.2 → audio_transcode_watcher-0.5.0}/src/audio_transcode_watcher/lyrics.py +0 -0
  33. {audio_transcode_watcher-0.4.2 → audio_transcode_watcher-0.5.0}/src/audio_transcode_watcher/main.py +0 -0
  34. {audio_transcode_watcher-0.4.2 → audio_transcode_watcher-0.5.0}/tests/__init__.py +0 -0
  35. {audio_transcode_watcher-0.4.2 → audio_transcode_watcher-0.5.0}/tests/conftest.py +0 -0
  36. {audio_transcode_watcher-0.4.2 → audio_transcode_watcher-0.5.0}/tests/test_config.py +0 -0
  37. {audio_transcode_watcher-0.4.2 → audio_transcode_watcher-0.5.0}/tests/test_encoder.py +0 -0
  38. {audio_transcode_watcher-0.4.2 → audio_transcode_watcher-0.5.0}/tests/test_lyrics.py +0 -0
@@ -0,0 +1,45 @@
1
+ language: "en-US"
2
+ tone_instructions: "Be direct and concise. No fluff."
3
+
4
+ reviews:
5
+ profile: "chill"
6
+ high_level_summary: true
7
+ collapse_walkthrough: true
8
+ poem: false
9
+ sequence_diagrams: false
10
+ suggested_reviewers: false
11
+ auto_review:
12
+ enabled: true
13
+ drafts: false
14
+ ignore_title_keywords:
15
+ - "WIP"
16
+ - "DO NOT REVIEW"
17
+ path_filters:
18
+ - "!dist/**"
19
+ - "!**/__pycache__/**"
20
+ - "!**/*.pyc"
21
+ tools:
22
+ gitleaks:
23
+ enabled: true
24
+ hadolint:
25
+ enabled: true
26
+ actionlint:
27
+ enabled: true
28
+ yamllint:
29
+ enabled: true
30
+ markdownlint:
31
+ enabled: true
32
+ shellcheck:
33
+ enabled: true
34
+
35
+ chat:
36
+ auto_reply: true
37
+
38
+ knowledge_base:
39
+ learnings:
40
+ scope: "local"
41
+ code_guidelines:
42
+ enabled: true
43
+ filePatterns:
44
+ - "AGENTS.md"
45
+ - "CLAUDE.md"
@@ -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
@@ -35,6 +35,8 @@ jobs:
35
35
  permissions:
36
36
  contents: write
37
37
  packages: write
38
+ env:
39
+ PYPI_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
38
40
 
39
41
  steps:
40
42
  - uses: actions/checkout@v4
@@ -83,13 +85,31 @@ jobs:
83
85
  generate_release_notes: true
84
86
  body: |
85
87
  ## Docker Image
86
-
88
+
87
89
  ```bash
88
90
  docker pull ${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}
89
91
  ```
90
-
92
+
91
93
  ## What's Changed
92
-
94
+
93
95
  See the automatically generated release notes below.
94
96
  env:
95
97
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
98
+
99
+ - name: Set up Python
100
+ uses: actions/setup-python@v5
101
+ with:
102
+ python-version: '3.14'
103
+
104
+ - name: Install build tools
105
+ run: pip install build twine
106
+
107
+ - name: Build Python package
108
+ run: python3 -m build
109
+
110
+ - name: Publish to PyPI
111
+ if: ${{ env.PYPI_TOKEN != '' }}
112
+ env:
113
+ TWINE_USERNAME: __token__
114
+ TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
115
+ run: twine upload dist/*
@@ -0,0 +1,19 @@
1
+ name: Close stale issues
2
+ on:
3
+ schedule:
4
+ - cron: '0 0 * * *'
5
+
6
+ jobs:
7
+ stale:
8
+ runs-on: ubuntu-latest
9
+ steps:
10
+ - uses: actions/stale@v9
11
+ with:
12
+ stale-issue-message: 'This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs.'
13
+ close-issue-message: 'This issue was closed because it has been stale for 14 days with no activity.'
14
+ days-before-issue-stale: 14
15
+ days-before-issue-close: 14
16
+ stale-issue-label: 'stale'
17
+ exempt-issue-labels: 'pinned'
18
+ days-before-pr-stale: -1
19
+ days-before-pr-close: -1
@@ -1,6 +1,7 @@
1
1
  name: Tests
2
2
 
3
3
  on:
4
+ workflow_dispatch:
4
5
  push:
5
6
  branches: [main]
6
7
  pull_request:
@@ -28,9 +29,8 @@ jobs:
28
29
  pytest --cov --cov-report=xml --cov-report=term-missing
29
30
 
30
31
  - name: Upload coverage to Codecov
31
- uses: codecov/codecov-action@v4
32
+ uses: codecov/codecov-action@v5
32
33
  with:
33
- token: ${{ secrets.CODECOV_TOKEN }}
34
34
  files: ./coverage.xml
35
35
  fail_ci_if_error: false
36
36
 
@@ -0,0 +1,18 @@
1
+ # AGENTS.md — Audio Transcode Watcher
2
+
3
+ ## Project Overview
4
+
5
+ Automated multi-format audio transcoding service with real-time file watching and lyrics fetching.
6
+
7
+ - **Repo:** [GeiserX/audio-transcode-watcher](https://github.com/GeiserX/audio-transcode-watcher)
8
+ - **Language:** Python
9
+ - **License:** GPL-3.0
10
+
11
+ ## Security
12
+
13
+ > **Do not commit secrets to the repository.**
14
+ > Use environment variables or secure vaults for credentials.
15
+
16
+ ---
17
+
18
+ *Generated by [LynxPrompt](https://lynxprompt.com) CLI*
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: audio-transcode-watcher
3
- Version: 0.4.2
3
+ Version: 0.5.0
4
4
  Summary: Watch a source folder and automatically transcode audio files to multiple formats
5
5
  Project-URL: Homepage, https://github.com/GeiserX/audio-transcode-watcher
6
6
  Project-URL: Repository, https://github.com/GeiserX/audio-transcode-watcher
@@ -65,6 +65,7 @@ Perfect for maintaining a music library in multiple formats -- lossless for arch
65
65
  ## Features
66
66
 
67
67
  - **Real-time file watching** -- Detects new, modified, renamed, or deleted files via watchdog
68
+ - **Recursive directory support** -- Mirrors source folder hierarchy (Artist/Album) in all outputs
68
69
  - **Multiple simultaneous outputs** -- Transcode to any number of formats in a single pass
69
70
  - **Six codecs** -- ALAC, AAC, MP3, Opus, FLAC, WAV with configurable bitrates
70
71
  - **Synced lyrics** -- Auto-fetches `.lrc` lyrics with Whisper speech-to-text fallback
@@ -106,7 +107,7 @@ outputs:
106
107
  ```yaml
107
108
  services:
108
109
  audio-transcoder:
109
- image: drumsergio/audio-transcoder:0.4.1
110
+ image: drumsergio/audio-transcoder:0.5.0
110
111
  container_name: audio_transcoder
111
112
  environment:
112
113
  - TZ=Europe/Madrid
@@ -137,7 +138,7 @@ docker run -d \
137
138
  -v /path/to/flac:/music/flac:ro \
138
139
  -v /path/to/mp3:/music/mp3 \
139
140
  --restart unless-stopped \
140
- drumsergio/audio-transcoder:0.4.1
141
+ drumsergio/audio-transcoder:0.5.0
141
142
  ```
142
143
 
143
144
  ## Configuration
@@ -229,6 +230,26 @@ environment:
229
230
  3. **Orphan cleanup** -- Removes output files that no longer have a matching source.
230
231
  4. **Lyrics sync** -- Fetches synced `.lrc` lyrics from online databases; falls back to Whisper transcription when no lyrics are found.
231
232
 
233
+ ### Recursive Directory Support
234
+
235
+ Source folder hierarchy is automatically mirrored in all outputs. Both flat and nested structures work out of the box -- no configuration needed.
236
+
237
+ ```text
238
+ Source: Output (MP3):
239
+ /music/flac/ /music/mp3/
240
+ ├── Artist A/ ├── Artist A/
241
+ │ ├── Album 1/ │ ├── Album 1/
242
+ │ │ ├── 01 - Track.flac │ │ ├── 01 - Track.mp3
243
+ │ │ └── 02 - Track.flac │ │ └── 02 - Track.mp3
244
+ │ └── Album 2/ │ └── Album 2/
245
+ │ └── 01 - Song.flac │ └── 01 - Song.mp3
246
+ └── Artist B/ └── Artist B/
247
+ └── Live Album/ └── Live Album/
248
+ └── 01 - Intro.flac └── 01 - Intro.mp3
249
+ ```
250
+
251
+ When source files or directories are deleted, the corresponding outputs and empty directories are cleaned up automatically.
252
+
232
253
  ### Safety Guards
233
254
 
234
255
  The service includes multiple guards to prevent data loss:
@@ -34,6 +34,7 @@ Perfect for maintaining a music library in multiple formats -- lossless for arch
34
34
  ## Features
35
35
 
36
36
  - **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
37
38
  - **Multiple simultaneous outputs** -- Transcode to any number of formats in a single pass
38
39
  - **Six codecs** -- ALAC, AAC, MP3, Opus, FLAC, WAV with configurable bitrates
39
40
  - **Synced lyrics** -- Auto-fetches `.lrc` lyrics with Whisper speech-to-text fallback
@@ -75,7 +76,7 @@ outputs:
75
76
  ```yaml
76
77
  services:
77
78
  audio-transcoder:
78
- image: drumsergio/audio-transcoder:0.4.1
79
+ image: drumsergio/audio-transcoder:0.5.0
79
80
  container_name: audio_transcoder
80
81
  environment:
81
82
  - TZ=Europe/Madrid
@@ -106,7 +107,7 @@ docker run -d \
106
107
  -v /path/to/flac:/music/flac:ro \
107
108
  -v /path/to/mp3:/music/mp3 \
108
109
  --restart unless-stopped \
109
- drumsergio/audio-transcoder:0.4.1
110
+ drumsergio/audio-transcoder:0.5.0
110
111
  ```
111
112
 
112
113
  ## Configuration
@@ -198,6 +199,26 @@ environment:
198
199
  3. **Orphan cleanup** -- Removes output files that no longer have a matching source.
199
200
  4. **Lyrics sync** -- Fetches synced `.lrc` lyrics from online databases; falls back to Whisper transcription when no lyrics are found.
200
201
 
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
+
201
222
  ### Safety Guards
202
223
 
203
224
  The service includes multiple guards to prevent data loss:
@@ -0,0 +1,88 @@
1
+ # Roadmap
2
+
3
+ Current version: **0.5.0**
4
+
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
16
+
17
+ - [ ] **Progress reporting during initial sync**
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
30
+
31
+ - [ ] **Health check endpoint**
32
+ - HTTP endpoint for container health monitoring
33
+ - Prometheus metrics (files processed, errors, queue size)
34
+
35
+ - [ ] **Notifications**
36
+ - Webhook/Shoutrrr support for encoding events
37
+ - Error alerts for failed encodes
38
+
39
+ ## v0.8.0 -- Smart Encoding
40
+
41
+ - [ ] **FFmpeg multi-output (tee muxer)**
42
+ - Single decode pass, multiple encodes
43
+ - Significant CPU reduction for multi-output configurations
44
+
45
+ - [ ] **Checksum-based re-encoding**
46
+ - Detect actual content changes vs. metadata-only touches
47
+ - Skip re-encode when source content is unchanged
48
+
49
+ - [ ] **Replay gain support**
50
+ - Calculate and embed replay gain tags
51
+ - Album and track gain modes
52
+
53
+ ## Future Ideas (Backlog)
54
+
55
+ ### Format Support
56
+ - [ ] Ogg Vorbis output codec
57
+ - [ ] DSD/DSF input support (convert to PCM first)
58
+ - [ ] Multi-channel audio handling (5.1 to stereo downmix option)
59
+
60
+ ### Metadata
61
+ - [ ] MusicBrainz integration for missing metadata
62
+ - [ ] Chapter markers for audiobooks
63
+
64
+ ### Integration
65
+ - [ ] Plex/Jellyfin library refresh triggers
66
+ - [ ] Lidarr/Beets integration
67
+
68
+ ### Analysis
69
+ - [ ] Loudness normalization (EBU R128)
70
+ - [ ] Silence trimming option
71
+ - [ ] Duplicate detection
72
+
73
+ ## Contributing
74
+
75
+ Have an idea not listed here? Open an issue on GitHub to discuss!
76
+
77
+ Priority is given to:
78
+ 1. Bug fixes
79
+ 2. Performance improvements
80
+ 3. Features with clear use cases
81
+ 4. Backwards-compatible changes
82
+
83
+ ## Versioning
84
+
85
+ This project follows [Semantic Versioning](https://semver.org/):
86
+ - **MAJOR**: Breaking changes to config format or behavior
87
+ - **MINOR**: New features, backwards compatible
88
+ - **PATCH**: Bug fixes, performance improvements
@@ -4,7 +4,9 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "audio-transcode-watcher"
7
- version = "0.4.2"
7
+
8
+ version = "0.5.0"
9
+
8
10
  description = "Watch a source folder and automatically transcode audio files to multiple formats"
9
11
  readme = "README.md"
10
12
  license = "GPL-3.0-or-later"