audiolibrarian 0.16.2__tar.gz → 0.16.4__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.
- {audiolibrarian-0.16.2 → audiolibrarian-0.16.4}/.github/workflows/main.yml +0 -2
- {audiolibrarian-0.16.2 → audiolibrarian-0.16.4}/.gitignore +2 -0
- {audiolibrarian-0.16.2 → audiolibrarian-0.16.4}/CONTRIBUTING.md +2 -2
- {audiolibrarian-0.16.2 → audiolibrarian-0.16.4}/Makefile +4 -1
- {audiolibrarian-0.16.2 → audiolibrarian-0.16.4}/PKG-INFO +117 -118
- {audiolibrarian-0.16.2 → audiolibrarian-0.16.4}/README.md +115 -116
- {audiolibrarian-0.16.2 → audiolibrarian-0.16.4}/git_hooks/README.md +0 -1
- {audiolibrarian-0.16.2 → audiolibrarian-0.16.4}/pyproject.toml +8 -1
- {audiolibrarian-0.16.2 → audiolibrarian-0.16.4}/src/audiolibrarian/__init__.py +1 -1
- {audiolibrarian-0.16.2 → audiolibrarian-0.16.4}/src/picard_src/README.md +3 -3
- {audiolibrarian-0.16.2 → audiolibrarian-0.16.4}/uv.lock +80 -0
- {audiolibrarian-0.16.2 → audiolibrarian-0.16.4}/.python-version +0 -0
- {audiolibrarian-0.16.2 → audiolibrarian-0.16.4}/COPYING +0 -0
- {audiolibrarian-0.16.2 → audiolibrarian-0.16.4}/LICENSE +0 -0
- {audiolibrarian-0.16.2 → audiolibrarian-0.16.4}/git_hooks/pre-push +0 -0
- {audiolibrarian-0.16.2 → audiolibrarian-0.16.4}/scripts/update_links.sh +0 -0
- {audiolibrarian-0.16.2 → audiolibrarian-0.16.4}/src/audiolibrarian/audiofile/__init__.py +0 -0
- {audiolibrarian-0.16.2 → audiolibrarian-0.16.4}/src/audiolibrarian/audiofile/audiofile.py +0 -0
- {audiolibrarian-0.16.2 → audiolibrarian-0.16.4}/src/audiolibrarian/audiofile/formats/__init__.py +0 -0
- {audiolibrarian-0.16.2 → audiolibrarian-0.16.4}/src/audiolibrarian/audiofile/formats/flac.py +0 -0
- {audiolibrarian-0.16.2 → audiolibrarian-0.16.4}/src/audiolibrarian/audiofile/formats/m4a.py +0 -0
- {audiolibrarian-0.16.2 → audiolibrarian-0.16.4}/src/audiolibrarian/audiofile/formats/mp3.py +0 -0
- {audiolibrarian-0.16.2 → audiolibrarian-0.16.4}/src/audiolibrarian/audiofile/tags.py +0 -0
- {audiolibrarian-0.16.2 → audiolibrarian-0.16.4}/src/audiolibrarian/audiosource.py +0 -0
- {audiolibrarian-0.16.2 → audiolibrarian-0.16.4}/src/audiolibrarian/base.py +0 -0
- {audiolibrarian-0.16.2 → audiolibrarian-0.16.4}/src/audiolibrarian/cli.py +0 -0
- {audiolibrarian-0.16.2 → audiolibrarian-0.16.4}/src/audiolibrarian/commands.py +0 -0
- {audiolibrarian-0.16.2 → audiolibrarian-0.16.4}/src/audiolibrarian/genremanager.py +0 -0
- {audiolibrarian-0.16.2 → audiolibrarian-0.16.4}/src/audiolibrarian/musicbrainz.py +0 -0
- {audiolibrarian-0.16.2 → audiolibrarian-0.16.4}/src/audiolibrarian/output.py +0 -0
- {audiolibrarian-0.16.2 → audiolibrarian-0.16.4}/src/audiolibrarian/records.py +0 -0
- {audiolibrarian-0.16.2 → audiolibrarian-0.16.4}/src/audiolibrarian/settings.py +0 -0
- {audiolibrarian-0.16.2 → audiolibrarian-0.16.4}/src/audiolibrarian/sh.py +0 -0
- {audiolibrarian-0.16.2 → audiolibrarian-0.16.4}/src/audiolibrarian/text.py +0 -0
- {audiolibrarian-0.16.2 → audiolibrarian-0.16.4}/src/picard_src/__init__.py +0 -0
- {audiolibrarian-0.16.2 → audiolibrarian-0.16.4}/src/picard_src/textencoding.py +0 -0
- {audiolibrarian-0.16.2 → audiolibrarian-0.16.4}/tools/__init__.py +0 -0
- {audiolibrarian-0.16.2 → audiolibrarian-0.16.4}/tools/diff.py +0 -0
- {audiolibrarian-0.16.2 → audiolibrarian-0.16.4}/tools/show_tags.py +0 -0
@@ -2,9 +2,9 @@
|
|
2
2
|
|
3
3
|
## Git Hooks
|
4
4
|
|
5
|
-
The project includes a git_hooks directory with a pre-push hook that verifies that all code is
|
5
|
+
The project includes a git_hooks directory with a pre-push hook that verifies that all code is
|
6
6
|
linted and tests pass. To have git use the hooks in this directory, run:
|
7
7
|
|
8
8
|
```bash
|
9
9
|
git config core.hooksPath git_hooks
|
10
|
-
```
|
10
|
+
```
|
@@ -4,6 +4,7 @@
|
|
4
4
|
PRESET_VARS := $(.VARIABLES)
|
5
5
|
|
6
6
|
# Project variables
|
7
|
+
MD_FILES := $(shell find . -name '*.md' | grep -v "/.venv/" | grep -v "/dist/")
|
7
8
|
PROJECT_NAME := $(shell grep -e '^name =' pyproject.toml | cut -d'"' -f2)
|
8
9
|
PY_FILES := $(shell find . -name '*.py' | grep -v "/.venv/" | grep -v "/dist/")
|
9
10
|
PYTHON_VERSION_ := $(shell cat .python-version)
|
@@ -15,6 +16,7 @@ BROWSER := $(shell command -v chromium || command -v google-chrome-stable || co
|
|
15
16
|
PYTHON := $(shell command -v python$(PYTHON_VERSION_))
|
16
17
|
UV := $(shell command -v uv)
|
17
18
|
COVERAGE := $(UV) run coverage
|
19
|
+
MDLINT := $(UV) run pymarkdownlnt
|
18
20
|
MYPY := $(UV) run mypy
|
19
21
|
PIP := $(UV) pip
|
20
22
|
PYTEST := $(UV) run pytest
|
@@ -71,6 +73,7 @@ lint: format ## Lint the code.
|
|
71
73
|
@$(RUFF) format --check src
|
72
74
|
@$(RUFF) check src
|
73
75
|
@$(MYPY) --non-interactive $(PY_FILES)
|
76
|
+
@$(MDLINT) scan $(MD_FILES)
|
74
77
|
|
75
78
|
.PHONY: publish
|
76
79
|
publish: $(WHEEL) ## Publish the package to PyPI.
|
@@ -107,7 +110,7 @@ ifndef PYTHON_VERSION
|
|
107
110
|
endif
|
108
111
|
endif
|
109
112
|
|
110
|
-
uv.lock:
|
113
|
+
uv.lock: pyproject.toml
|
111
114
|
@$(UV) lock
|
112
115
|
|
113
116
|
$(WHEEL): $(PY_FILES) pyproject.toml uv.lock dep
|
@@ -1,8 +1,8 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: audiolibrarian
|
3
|
-
Version: 0.16.
|
3
|
+
Version: 0.16.4
|
4
4
|
Summary: Manage my audio library.
|
5
|
-
Project-URL: Repository, https://
|
5
|
+
Project-URL: Repository, https://github.com/toadstule/audiolibrarian
|
6
6
|
Author-email: Steve Jibson <steve@jibson.com>
|
7
7
|
License-File: COPYING
|
8
8
|
License-File: LICENSE
|
@@ -27,8 +27,9 @@ Description-Content-Type: text/markdown
|
|
27
27
|
|
28
28
|
## Overview ##
|
29
29
|
|
30
|
-
`audiolibrarian` is a
|
31
|
-
|
30
|
+
`audiolibrarian` is a command-line tool for ripping audio from CDs (or taking
|
31
|
+
high-quality audio from local files), tagging them with comprehensive metadata from MusicBrainz,
|
32
|
+
converting them to multiple formats, and organizing them in a clean directory structure.
|
32
33
|
|
33
34
|
### Key Features ###
|
34
35
|
|
@@ -45,77 +46,78 @@ workflow for ripping, converting, organizing, and tagging audio files with high-
|
|
45
46
|
- **Consistent Quality**: Maintains audio quality through the conversion process
|
46
47
|
- **Accurate Metadata**: Leverages MusicBrainz for comprehensive music information
|
47
48
|
- **Automated Workflow**: Reduces manual work in organizing and tagging music
|
48
|
-
- **Scriptable**: Perfect for automating large music library management tasks
|
49
49
|
- **Open Source**: Free to use and modify under the GPL-3.0 license
|
50
50
|
|
51
|
-
Whether you're digitizing a CD collection, organizing existing music files, or managing a large
|
52
|
-
`audiolibrarian` provides the tools you need to keep your music collection
|
53
|
-
|
51
|
+
Whether you're digitizing a CD collection, organizing existing music files, or managing a large
|
52
|
+
digital library, `audiolibrarian` provides the tools you need to keep your music collection
|
53
|
+
well-organized and properly tagged.
|
54
54
|
|
55
55
|
## Installation ##
|
56
56
|
|
57
|
+
> **NOTE:** This library has only been tested on Linux. It may not work on other operating
|
58
|
+
> systems.
|
59
|
+
|
57
60
|
### External Requirements ###
|
58
61
|
|
59
62
|
`audiolibrarian` uses a few command-line tools to run:
|
60
63
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
### Install from PyPI ###
|
64
|
+
- [cd-paranoia](https://www.gnu.org/software/libcdio/)
|
65
|
+
- [util-linux](https://github.com/util-linux/util-linux)
|
66
|
+
- [faad2](https://github.com/knik0/faad2)
|
67
|
+
- [fdkaac](https://github.com/nu774/fdkaac)
|
68
|
+
- [flac](https://github.com/xiph/flac)
|
69
|
+
- [lame](https://lame.sourceforge.io/)
|
70
|
+
- [mpg123](https://www.mpg123.de/)
|
71
|
+
- [libsndfile](https://github.com/libsndfile/libsndfile)
|
72
|
+
- [wavegain](https://github.com/MestreLion/wavegain)
|
72
73
|
|
73
|
-
|
74
|
+
It also requires the [libdiscid](https://musicbrainz.org/doc/libdiscid) library.
|
74
75
|
|
75
|
-
|
76
|
-
pip install --user --extra-index-url=https://pypi.example.com/simple audiolibrarian
|
77
|
-
```
|
76
|
+
### Install from PyPI ###
|
78
77
|
|
79
|
-
|
78
|
+
`audiolibrarian` is available on PyPI:
|
80
79
|
|
81
80
|
```bash
|
82
|
-
pip install
|
81
|
+
pip install audiolibrarian
|
83
82
|
```
|
84
83
|
|
85
84
|
## Configuration ##
|
86
85
|
|
87
|
-
`audiolibrarian` uses a flexible configuration system that supports multiple configuration sources,
|
86
|
+
`audiolibrarian` uses a flexible configuration system that supports multiple configuration sources,
|
87
|
+
listed in order of precedence:
|
88
88
|
|
89
89
|
1. **Environment Variables** (highest precedence)
|
90
90
|
- Prefix: `AUDIOLIBRARIAN__`
|
91
91
|
- Nested fields: Use `__` as delimiter (e.g., `AUDIOLIBRARIAN__MUSICBRAINZ__USERNAME`)
|
92
92
|
- Example:
|
93
|
+
|
93
94
|
```bash
|
94
|
-
# Override library directory
|
95
|
+
# Override library directory (library_dir)
|
95
96
|
export AUDIOLIBRARIAN__LIBRARY_DIR="/mnt/music/library"
|
96
97
|
|
97
|
-
# Set MusicBrainz credentials
|
98
|
+
# Set MusicBrainz credentials (musicbrainz.username and musicbrainz.password)
|
98
99
|
export AUDIOLIBRARIAN__MUSICBRAINZ__USERNAME="your_username"
|
99
100
|
export AUDIOLIBRARIAN__MUSICBRAINZ__PASSWORD="your_password"
|
100
101
|
```
|
101
102
|
|
102
|
-
2. **YAML Configuration File**
|
103
|
-
-
|
103
|
+
2. **YAML Configuration File** (medium precedence)
|
104
|
+
- Default location: `~/.config/audiolibrarian/config.yaml`
|
104
105
|
- Example:
|
106
|
+
|
105
107
|
```yaml
|
106
108
|
# Base directory for your music library
|
107
109
|
library_dir: "~/music/library"
|
108
|
-
|
110
|
+
|
109
111
|
# Cache and working directory
|
110
112
|
work_dir: "~/.cache/audiolibrarian"
|
111
|
-
|
113
|
+
|
112
114
|
# CD/DVD device path (use null for default device)
|
113
115
|
discid_device: null
|
114
|
-
|
116
|
+
|
115
117
|
# Audio normalization settings
|
116
118
|
normalize_gain: 5 # dB gain for normalization
|
117
119
|
normalize_preset: "radio" # "album" or "radio"
|
118
|
-
|
120
|
+
|
119
121
|
# MusicBrainz API settings (optional)
|
120
122
|
musicbrainz:
|
121
123
|
username: "your_username" # For personal genre preferences
|
@@ -128,18 +130,23 @@ pip install --user git+https://bitbucket.org/toadstule/audiolibrarian
|
|
128
130
|
|
129
131
|
### Available Settings ###
|
130
132
|
|
131
|
-
| Setting | Default
|
132
|
-
|
133
|
-
| `library_dir` |
|
134
|
-
| `work_dir` |
|
135
|
-
| `discid_device` | `null`
|
136
|
-
| `normalize_gain` | `5`
|
137
|
-
| `normalize_preset` | `"radio"`
|
138
|
-
| `musicbrainz.username` | (not set)
|
139
|
-
| `musicbrainz.password` | (not set)
|
140
|
-
| `musicbrainz.rate_limit` | `1.5`
|
141
|
-
|
142
|
-
> **
|
133
|
+
| Setting | Default | Description |
|
134
|
+
|--------------------------|---------------------------|-------------------------------------------|
|
135
|
+
| `library_dir` | `./library` | Directory for storing audio files |
|
136
|
+
| `work_dir` | `~/.cache/audiolibrarian` | Directory for temporary files |
|
137
|
+
| `discid_device` | `null` | CD device path (null for default device) |
|
138
|
+
| `normalize_gain` | `5` | Normalization gain in dB |
|
139
|
+
| `normalize_preset` | `"radio"` | Normalization preset ("album" or "radio") |
|
140
|
+
| `musicbrainz.username` | (not set) | MusicBrainz username |
|
141
|
+
| `musicbrainz.password` | (not set) | MusicBrainz password |
|
142
|
+
| `musicbrainz.rate_limit` | `1.5` | Seconds between requests |
|
143
|
+
|
144
|
+
> **Notes**:
|
145
|
+
>
|
146
|
+
> - The `musicbrainz` username and password are optional but recommended for accessing personal genre
|
147
|
+
> preferences on [MusicBrainz](https://musicbrainz.org/).
|
148
|
+
> - The `work_dir` default is actually `$XDG_CACHE_HOME/audiolibrarian`, which defaults to
|
149
|
+
> `~/.cache/audiolibrarian` on Linux and macOS.
|
143
150
|
|
144
151
|
## Usage ##
|
145
152
|
|
@@ -168,31 +175,40 @@ audiolibrarian genre /path/to/audio/directories --tag # Update tags with MB gen
|
|
168
175
|
audiolibrarian --help
|
169
176
|
```
|
170
177
|
|
171
|
-
###
|
172
|
-
|
173
|
-
Configuration sources are combined with the following precedence (highest to lowest):
|
174
|
-
1. Environment variables
|
175
|
-
2. YAML configuration file
|
176
|
-
3. Default values
|
177
|
-
|
178
|
-
For example, with this `config.yaml`:
|
178
|
+
### Directory Structure ###
|
179
179
|
|
180
|
-
|
181
|
-
# config.yaml
|
182
|
-
library_dir: /media/music/library
|
183
|
-
normalize_gain: 5.0
|
184
|
-
```
|
180
|
+
`audiolibrarian` organizes files in the following structure:
|
185
181
|
|
186
|
-
|
187
|
-
```bash
|
188
|
-
export AUDIOLIBRARIAN__NORMALIZE_GAIN="8.0"
|
189
|
-
```
|
182
|
+
**Processed audio files** (organized by format):
|
190
183
|
|
191
|
-
|
184
|
+
```text
|
185
|
+
library/
|
186
|
+
├── flac/
|
187
|
+
│ └── Artist/
|
188
|
+
│ └── YYYY__Album/
|
189
|
+
│ ├── 01__Track_Title.flac
|
190
|
+
│ └── 02__Another_Track.flac
|
191
|
+
├── m4a/
|
192
|
+
│ └── Artist/
|
193
|
+
│ └── YYYY__Album/
|
194
|
+
│ ├── 01__Track_Title.m4a
|
195
|
+
│ └── 02__Another_Track.m4a
|
196
|
+
├── mp3/
|
197
|
+
│ └── Artist/
|
198
|
+
│ └── YYYY__Album/
|
199
|
+
│ ├── 01__Track_Title.mp3
|
200
|
+
│ └── 02__Another_Track.mp3
|
201
|
+
├── source/
|
202
|
+
│ └── Artist/
|
203
|
+
│ └── YYYY__Album/
|
204
|
+
│ ├── 01__Track_Title.flac
|
205
|
+
│ ├── 02__Another_Track.flac
|
206
|
+
│ └── Manifest.yaml
|
207
|
+
```
|
192
208
|
|
193
209
|
### Advanced Usage ###
|
194
210
|
|
195
|
-
|
211
|
+
#### Ripping CDs ####
|
196
212
|
|
197
213
|
```bash
|
198
214
|
# Basic CD rip
|
@@ -208,7 +224,7 @@ audiolibrarian rip --mb-release-id "12345678-1234-1234-1234-123456789012"
|
|
208
224
|
audiolibrarian rip --disc "1/2" # First disc of two
|
209
225
|
```
|
210
226
|
|
211
|
-
|
227
|
+
#### Converting Audio Files ####
|
212
228
|
|
213
229
|
```bash
|
214
230
|
# Convert with specific artist and album
|
@@ -221,7 +237,7 @@ audiolibrarian convert --mb-release-id "12345678-1234-1234-1234-123456789012" /p
|
|
221
237
|
audiolibrarian convert --disc "1/2" /path/to/disc1/files
|
222
238
|
```
|
223
239
|
|
224
|
-
|
240
|
+
#### Working with Manifests ####
|
225
241
|
|
226
242
|
```bash
|
227
243
|
# Create manifest for existing files
|
@@ -231,11 +247,13 @@ audiolibrarian manifest /path/to/audio/files
|
|
231
247
|
audiolibrarian manifest --cd /path/to/audio/files
|
232
248
|
|
233
249
|
# Specify MusicBrainz artist and release IDs
|
234
|
-
audiolibrarian manifest
|
235
|
-
--mb-
|
250
|
+
audiolibrarian manifest \
|
251
|
+
--mb-artist-id "12345678-1234-1234-1234-123456789012" \
|
252
|
+
--mb-release-id "87654321-4321-4321-4321-210987654321" \
|
253
|
+
/path/to/audio/files
|
236
254
|
```
|
237
255
|
|
238
|
-
|
256
|
+
#### Reconverting Files ####
|
239
257
|
|
240
258
|
```bash
|
241
259
|
# Reconvert all files in directory
|
@@ -245,7 +263,7 @@ audiolibrarian reconvert /path/to/source/directories
|
|
245
263
|
audiolibrarian reconvert --dry-run /path/to/source/directories
|
246
264
|
```
|
247
265
|
|
248
|
-
|
266
|
+
#### Renaming Files ####
|
249
267
|
|
250
268
|
```bash
|
251
269
|
# Rename files based on tags
|
@@ -255,7 +273,7 @@ audiolibrarian rename /path/to/audio/directories
|
|
255
273
|
audiolibrarian rename --dry-run /path/to/audio/directories
|
256
274
|
```
|
257
275
|
|
258
|
-
|
276
|
+
#### Using Different Normalization Presets ####
|
259
277
|
|
260
278
|
```bash
|
261
279
|
# Use radio normalization preset (default)
|
@@ -265,9 +283,33 @@ export AUDIOLIBRARIAN__NORMALIZE_PRESET="radio"
|
|
265
283
|
export AUDIOLIBRARIAN__NORMALIZE_PRESET="album"
|
266
284
|
```
|
267
285
|
|
286
|
+
#### Combining Configuration Sources ####
|
287
|
+
|
288
|
+
Configuration sources are combined with the following precedence (highest to lowest):
|
289
|
+
1. Environment variables
|
290
|
+
2. YAML configuration file
|
291
|
+
3. Default values
|
292
|
+
|
293
|
+
For example, with this `config.yaml`:
|
294
|
+
|
295
|
+
```yaml
|
296
|
+
# config.yaml
|
297
|
+
library_dir: /media/music/library
|
298
|
+
normalize_gain: 5.0
|
299
|
+
```
|
300
|
+
|
301
|
+
And this environment variable:
|
302
|
+
|
303
|
+
```bash
|
304
|
+
export AUDIOLIBRARIAN__NORMALIZE_GAIN="8.0"
|
305
|
+
```
|
306
|
+
|
307
|
+
The effective value of `normalize_gain` will be `8.0` (from the environment variable), while
|
308
|
+
`library_dir` will be set to `/media/music/library` from the YAML file.
|
309
|
+
|
268
310
|
### Troubleshooting ###
|
269
311
|
|
270
|
-
|
312
|
+
#### Increasing Verbosity ####
|
271
313
|
|
272
314
|
```bash
|
273
315
|
# Show more detailed output
|
@@ -277,58 +319,15 @@ audiolibrarian --log-level INFO cd
|
|
277
319
|
audiolibrarian --log-level DEBUG cd
|
278
320
|
```
|
279
321
|
|
280
|
-
|
281
|
-
|
282
|
-
```bash
|
283
|
-
# Verify all required tools are installed
|
284
|
-
audiolibrarian --log-level DEBUG cd
|
285
|
-
```
|
286
|
-
|
287
|
-
3. **MusicBrainz Issues**
|
322
|
+
#### MusicBrainz Issues ####
|
288
323
|
|
289
324
|
If you encounter MusicBrainz-related errors:
|
290
325
|
|
291
326
|
1. Verify your credentials are correct
|
292
|
-
2. Check your
|
327
|
+
2. Check your Internet connection
|
293
328
|
3. Use the debug log level to get more information
|
294
329
|
4. Increase the rate limit if you're hitting rate limits
|
295
330
|
|
296
331
|
```bash
|
297
332
|
export AUDIOLIBRARIAN__MUSICBRAINZ__RATE_LIMIT="2.0"
|
298
333
|
```
|
299
|
-
|
300
|
-
### Directory Structure ###
|
301
|
-
|
302
|
-
`audiolibrarian` organizes files in the following structure:
|
303
|
-
|
304
|
-
1. **Source files** (original audio files):
|
305
|
-
```
|
306
|
-
library/source/
|
307
|
-
└── Artist/
|
308
|
-
└── YYYY__Album/
|
309
|
-
├── 01__Track_Title.flac
|
310
|
-
├── 02__Another_Track.flac
|
311
|
-
└── Manifest.yaml
|
312
|
-
```
|
313
|
-
|
314
|
-
2. **Processed audio files** (organized by format):
|
315
|
-
```
|
316
|
-
library/
|
317
|
-
├── flac/
|
318
|
-
│ └── Artist/
|
319
|
-
│ └── YYYY__Album/
|
320
|
-
│ ├── 01__Track_Title.flac
|
321
|
-
│ └── 02__Another_Track.flac
|
322
|
-
├── m4a/
|
323
|
-
│ └── Artist/
|
324
|
-
│ └── YYYY__Album/
|
325
|
-
│ ├── 01__Track_Title.m4a
|
326
|
-
│ └── 02__Another_Track.m4a
|
327
|
-
└── mp3/
|
328
|
-
└── Artist/
|
329
|
-
└── YYYY__Album/
|
330
|
-
├── 01__Track_Title.mp3
|
331
|
-
└── 02__Another_Track.mp3
|
332
|
-
```
|
333
|
-
|
334
|
-
Each track filename follows the format: `track_number__track_name.extension` (e.g., `01__Call_to_Arms.flac`).
|
@@ -2,8 +2,9 @@
|
|
2
2
|
|
3
3
|
## Overview ##
|
4
4
|
|
5
|
-
`audiolibrarian` is a
|
6
|
-
|
5
|
+
`audiolibrarian` is a command-line tool for ripping audio from CDs (or taking
|
6
|
+
high-quality audio from local files), tagging them with comprehensive metadata from MusicBrainz,
|
7
|
+
converting them to multiple formats, and organizing them in a clean directory structure.
|
7
8
|
|
8
9
|
### Key Features ###
|
9
10
|
|
@@ -20,77 +21,78 @@ workflow for ripping, converting, organizing, and tagging audio files with high-
|
|
20
21
|
- **Consistent Quality**: Maintains audio quality through the conversion process
|
21
22
|
- **Accurate Metadata**: Leverages MusicBrainz for comprehensive music information
|
22
23
|
- **Automated Workflow**: Reduces manual work in organizing and tagging music
|
23
|
-
- **Scriptable**: Perfect for automating large music library management tasks
|
24
24
|
- **Open Source**: Free to use and modify under the GPL-3.0 license
|
25
25
|
|
26
|
-
Whether you're digitizing a CD collection, organizing existing music files, or managing a large
|
27
|
-
`audiolibrarian` provides the tools you need to keep your music collection
|
28
|
-
|
26
|
+
Whether you're digitizing a CD collection, organizing existing music files, or managing a large
|
27
|
+
digital library, `audiolibrarian` provides the tools you need to keep your music collection
|
28
|
+
well-organized and properly tagged.
|
29
29
|
|
30
30
|
## Installation ##
|
31
31
|
|
32
|
+
> **NOTE:** This library has only been tested on Linux. It may not work on other operating
|
33
|
+
> systems.
|
34
|
+
|
32
35
|
### External Requirements ###
|
33
36
|
|
34
37
|
`audiolibrarian` uses a few command-line tools to run:
|
35
38
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
### Install from PyPI ###
|
39
|
+
- [cd-paranoia](https://www.gnu.org/software/libcdio/)
|
40
|
+
- [util-linux](https://github.com/util-linux/util-linux)
|
41
|
+
- [faad2](https://github.com/knik0/faad2)
|
42
|
+
- [fdkaac](https://github.com/nu774/fdkaac)
|
43
|
+
- [flac](https://github.com/xiph/flac)
|
44
|
+
- [lame](https://lame.sourceforge.io/)
|
45
|
+
- [mpg123](https://www.mpg123.de/)
|
46
|
+
- [libsndfile](https://github.com/libsndfile/libsndfile)
|
47
|
+
- [wavegain](https://github.com/MestreLion/wavegain)
|
47
48
|
|
48
|
-
|
49
|
+
It also requires the [libdiscid](https://musicbrainz.org/doc/libdiscid) library.
|
49
50
|
|
50
|
-
|
51
|
-
pip install --user --extra-index-url=https://pypi.example.com/simple audiolibrarian
|
52
|
-
```
|
51
|
+
### Install from PyPI ###
|
53
52
|
|
54
|
-
|
53
|
+
`audiolibrarian` is available on PyPI:
|
55
54
|
|
56
55
|
```bash
|
57
|
-
pip install
|
56
|
+
pip install audiolibrarian
|
58
57
|
```
|
59
58
|
|
60
59
|
## Configuration ##
|
61
60
|
|
62
|
-
`audiolibrarian` uses a flexible configuration system that supports multiple configuration sources,
|
61
|
+
`audiolibrarian` uses a flexible configuration system that supports multiple configuration sources,
|
62
|
+
listed in order of precedence:
|
63
63
|
|
64
64
|
1. **Environment Variables** (highest precedence)
|
65
65
|
- Prefix: `AUDIOLIBRARIAN__`
|
66
66
|
- Nested fields: Use `__` as delimiter (e.g., `AUDIOLIBRARIAN__MUSICBRAINZ__USERNAME`)
|
67
67
|
- Example:
|
68
|
+
|
68
69
|
```bash
|
69
|
-
# Override library directory
|
70
|
+
# Override library directory (library_dir)
|
70
71
|
export AUDIOLIBRARIAN__LIBRARY_DIR="/mnt/music/library"
|
71
72
|
|
72
|
-
# Set MusicBrainz credentials
|
73
|
+
# Set MusicBrainz credentials (musicbrainz.username and musicbrainz.password)
|
73
74
|
export AUDIOLIBRARIAN__MUSICBRAINZ__USERNAME="your_username"
|
74
75
|
export AUDIOLIBRARIAN__MUSICBRAINZ__PASSWORD="your_password"
|
75
76
|
```
|
76
77
|
|
77
|
-
2. **YAML Configuration File**
|
78
|
-
-
|
78
|
+
2. **YAML Configuration File** (medium precedence)
|
79
|
+
- Default location: `~/.config/audiolibrarian/config.yaml`
|
79
80
|
- Example:
|
81
|
+
|
80
82
|
```yaml
|
81
83
|
# Base directory for your music library
|
82
84
|
library_dir: "~/music/library"
|
83
|
-
|
85
|
+
|
84
86
|
# Cache and working directory
|
85
87
|
work_dir: "~/.cache/audiolibrarian"
|
86
|
-
|
88
|
+
|
87
89
|
# CD/DVD device path (use null for default device)
|
88
90
|
discid_device: null
|
89
|
-
|
91
|
+
|
90
92
|
# Audio normalization settings
|
91
93
|
normalize_gain: 5 # dB gain for normalization
|
92
94
|
normalize_preset: "radio" # "album" or "radio"
|
93
|
-
|
95
|
+
|
94
96
|
# MusicBrainz API settings (optional)
|
95
97
|
musicbrainz:
|
96
98
|
username: "your_username" # For personal genre preferences
|
@@ -103,18 +105,23 @@ pip install --user git+https://bitbucket.org/toadstule/audiolibrarian
|
|
103
105
|
|
104
106
|
### Available Settings ###
|
105
107
|
|
106
|
-
| Setting | Default
|
107
|
-
|
108
|
-
| `library_dir` |
|
109
|
-
| `work_dir` |
|
110
|
-
| `discid_device` | `null`
|
111
|
-
| `normalize_gain` | `5`
|
112
|
-
| `normalize_preset` | `"radio"`
|
113
|
-
| `musicbrainz.username` | (not set)
|
114
|
-
| `musicbrainz.password` | (not set)
|
115
|
-
| `musicbrainz.rate_limit` | `1.5`
|
116
|
-
|
117
|
-
> **
|
108
|
+
| Setting | Default | Description |
|
109
|
+
|--------------------------|---------------------------|-------------------------------------------|
|
110
|
+
| `library_dir` | `./library` | Directory for storing audio files |
|
111
|
+
| `work_dir` | `~/.cache/audiolibrarian` | Directory for temporary files |
|
112
|
+
| `discid_device` | `null` | CD device path (null for default device) |
|
113
|
+
| `normalize_gain` | `5` | Normalization gain in dB |
|
114
|
+
| `normalize_preset` | `"radio"` | Normalization preset ("album" or "radio") |
|
115
|
+
| `musicbrainz.username` | (not set) | MusicBrainz username |
|
116
|
+
| `musicbrainz.password` | (not set) | MusicBrainz password |
|
117
|
+
| `musicbrainz.rate_limit` | `1.5` | Seconds between requests |
|
118
|
+
|
119
|
+
> **Notes**:
|
120
|
+
>
|
121
|
+
> - The `musicbrainz` username and password are optional but recommended for accessing personal genre
|
122
|
+
> preferences on [MusicBrainz](https://musicbrainz.org/).
|
123
|
+
> - The `work_dir` default is actually `$XDG_CACHE_HOME/audiolibrarian`, which defaults to
|
124
|
+
> `~/.cache/audiolibrarian` on Linux and macOS.
|
118
125
|
|
119
126
|
## Usage ##
|
120
127
|
|
@@ -143,31 +150,40 @@ audiolibrarian genre /path/to/audio/directories --tag # Update tags with MB gen
|
|
143
150
|
audiolibrarian --help
|
144
151
|
```
|
145
152
|
|
146
|
-
###
|
147
|
-
|
148
|
-
Configuration sources are combined with the following precedence (highest to lowest):
|
149
|
-
1. Environment variables
|
150
|
-
2. YAML configuration file
|
151
|
-
3. Default values
|
152
|
-
|
153
|
-
For example, with this `config.yaml`:
|
153
|
+
### Directory Structure ###
|
154
154
|
|
155
|
-
|
156
|
-
# config.yaml
|
157
|
-
library_dir: /media/music/library
|
158
|
-
normalize_gain: 5.0
|
159
|
-
```
|
155
|
+
`audiolibrarian` organizes files in the following structure:
|
160
156
|
|
161
|
-
|
162
|
-
```bash
|
163
|
-
export AUDIOLIBRARIAN__NORMALIZE_GAIN="8.0"
|
164
|
-
```
|
157
|
+
**Processed audio files** (organized by format):
|
165
158
|
|
166
|
-
|
159
|
+
```text
|
160
|
+
library/
|
161
|
+
├── flac/
|
162
|
+
│ └── Artist/
|
163
|
+
│ └── YYYY__Album/
|
164
|
+
│ ├── 01__Track_Title.flac
|
165
|
+
│ └── 02__Another_Track.flac
|
166
|
+
├── m4a/
|
167
|
+
│ └── Artist/
|
168
|
+
│ └── YYYY__Album/
|
169
|
+
│ ├── 01__Track_Title.m4a
|
170
|
+
│ └── 02__Another_Track.m4a
|
171
|
+
├── mp3/
|
172
|
+
│ └── Artist/
|
173
|
+
│ └── YYYY__Album/
|
174
|
+
│ ├── 01__Track_Title.mp3
|
175
|
+
│ └── 02__Another_Track.mp3
|
176
|
+
├── source/
|
177
|
+
│ └── Artist/
|
178
|
+
│ └── YYYY__Album/
|
179
|
+
│ ├── 01__Track_Title.flac
|
180
|
+
│ ├── 02__Another_Track.flac
|
181
|
+
│ └── Manifest.yaml
|
182
|
+
```
|
167
183
|
|
168
184
|
### Advanced Usage ###
|
169
185
|
|
170
|
-
|
186
|
+
#### Ripping CDs ####
|
171
187
|
|
172
188
|
```bash
|
173
189
|
# Basic CD rip
|
@@ -183,7 +199,7 @@ audiolibrarian rip --mb-release-id "12345678-1234-1234-1234-123456789012"
|
|
183
199
|
audiolibrarian rip --disc "1/2" # First disc of two
|
184
200
|
```
|
185
201
|
|
186
|
-
|
202
|
+
#### Converting Audio Files ####
|
187
203
|
|
188
204
|
```bash
|
189
205
|
# Convert with specific artist and album
|
@@ -196,7 +212,7 @@ audiolibrarian convert --mb-release-id "12345678-1234-1234-1234-123456789012" /p
|
|
196
212
|
audiolibrarian convert --disc "1/2" /path/to/disc1/files
|
197
213
|
```
|
198
214
|
|
199
|
-
|
215
|
+
#### Working with Manifests ####
|
200
216
|
|
201
217
|
```bash
|
202
218
|
# Create manifest for existing files
|
@@ -206,11 +222,13 @@ audiolibrarian manifest /path/to/audio/files
|
|
206
222
|
audiolibrarian manifest --cd /path/to/audio/files
|
207
223
|
|
208
224
|
# Specify MusicBrainz artist and release IDs
|
209
|
-
audiolibrarian manifest
|
210
|
-
--mb-
|
225
|
+
audiolibrarian manifest \
|
226
|
+
--mb-artist-id "12345678-1234-1234-1234-123456789012" \
|
227
|
+
--mb-release-id "87654321-4321-4321-4321-210987654321" \
|
228
|
+
/path/to/audio/files
|
211
229
|
```
|
212
230
|
|
213
|
-
|
231
|
+
#### Reconverting Files ####
|
214
232
|
|
215
233
|
```bash
|
216
234
|
# Reconvert all files in directory
|
@@ -220,7 +238,7 @@ audiolibrarian reconvert /path/to/source/directories
|
|
220
238
|
audiolibrarian reconvert --dry-run /path/to/source/directories
|
221
239
|
```
|
222
240
|
|
223
|
-
|
241
|
+
#### Renaming Files ####
|
224
242
|
|
225
243
|
```bash
|
226
244
|
# Rename files based on tags
|
@@ -230,7 +248,7 @@ audiolibrarian rename /path/to/audio/directories
|
|
230
248
|
audiolibrarian rename --dry-run /path/to/audio/directories
|
231
249
|
```
|
232
250
|
|
233
|
-
|
251
|
+
#### Using Different Normalization Presets ####
|
234
252
|
|
235
253
|
```bash
|
236
254
|
# Use radio normalization preset (default)
|
@@ -240,9 +258,33 @@ export AUDIOLIBRARIAN__NORMALIZE_PRESET="radio"
|
|
240
258
|
export AUDIOLIBRARIAN__NORMALIZE_PRESET="album"
|
241
259
|
```
|
242
260
|
|
261
|
+
#### Combining Configuration Sources ####
|
262
|
+
|
263
|
+
Configuration sources are combined with the following precedence (highest to lowest):
|
264
|
+
1. Environment variables
|
265
|
+
2. YAML configuration file
|
266
|
+
3. Default values
|
267
|
+
|
268
|
+
For example, with this `config.yaml`:
|
269
|
+
|
270
|
+
```yaml
|
271
|
+
# config.yaml
|
272
|
+
library_dir: /media/music/library
|
273
|
+
normalize_gain: 5.0
|
274
|
+
```
|
275
|
+
|
276
|
+
And this environment variable:
|
277
|
+
|
278
|
+
```bash
|
279
|
+
export AUDIOLIBRARIAN__NORMALIZE_GAIN="8.0"
|
280
|
+
```
|
281
|
+
|
282
|
+
The effective value of `normalize_gain` will be `8.0` (from the environment variable), while
|
283
|
+
`library_dir` will be set to `/media/music/library` from the YAML file.
|
284
|
+
|
243
285
|
### Troubleshooting ###
|
244
286
|
|
245
|
-
|
287
|
+
#### Increasing Verbosity ####
|
246
288
|
|
247
289
|
```bash
|
248
290
|
# Show more detailed output
|
@@ -252,58 +294,15 @@ audiolibrarian --log-level INFO cd
|
|
252
294
|
audiolibrarian --log-level DEBUG cd
|
253
295
|
```
|
254
296
|
|
255
|
-
|
256
|
-
|
257
|
-
```bash
|
258
|
-
# Verify all required tools are installed
|
259
|
-
audiolibrarian --log-level DEBUG cd
|
260
|
-
```
|
261
|
-
|
262
|
-
3. **MusicBrainz Issues**
|
297
|
+
#### MusicBrainz Issues ####
|
263
298
|
|
264
299
|
If you encounter MusicBrainz-related errors:
|
265
300
|
|
266
301
|
1. Verify your credentials are correct
|
267
|
-
2. Check your
|
302
|
+
2. Check your Internet connection
|
268
303
|
3. Use the debug log level to get more information
|
269
304
|
4. Increase the rate limit if you're hitting rate limits
|
270
305
|
|
271
306
|
```bash
|
272
307
|
export AUDIOLIBRARIAN__MUSICBRAINZ__RATE_LIMIT="2.0"
|
273
308
|
```
|
274
|
-
|
275
|
-
### Directory Structure ###
|
276
|
-
|
277
|
-
`audiolibrarian` organizes files in the following structure:
|
278
|
-
|
279
|
-
1. **Source files** (original audio files):
|
280
|
-
```
|
281
|
-
library/source/
|
282
|
-
└── Artist/
|
283
|
-
└── YYYY__Album/
|
284
|
-
├── 01__Track_Title.flac
|
285
|
-
├── 02__Another_Track.flac
|
286
|
-
└── Manifest.yaml
|
287
|
-
```
|
288
|
-
|
289
|
-
2. **Processed audio files** (organized by format):
|
290
|
-
```
|
291
|
-
library/
|
292
|
-
├── flac/
|
293
|
-
│ └── Artist/
|
294
|
-
│ └── YYYY__Album/
|
295
|
-
│ ├── 01__Track_Title.flac
|
296
|
-
│ └── 02__Another_Track.flac
|
297
|
-
├── m4a/
|
298
|
-
│ └── Artist/
|
299
|
-
│ └── YYYY__Album/
|
300
|
-
│ ├── 01__Track_Title.m4a
|
301
|
-
│ └── 02__Another_Track.m4a
|
302
|
-
└── mp3/
|
303
|
-
└── Artist/
|
304
|
-
└── YYYY__Album/
|
305
|
-
├── 01__Track_Title.mp3
|
306
|
-
└── 02__Another_Track.mp3
|
307
|
-
```
|
308
|
-
|
309
|
-
Each track filename follows the format: `track_number__track_name.extension` (e.g., `01__Call_to_Arms.flac`).
|
@@ -7,6 +7,7 @@ dev = [
|
|
7
7
|
"coverage",
|
8
8
|
"hatchling",
|
9
9
|
"mypy",
|
10
|
+
"pymarkdownlnt",
|
10
11
|
"pytest",
|
11
12
|
"ruff",
|
12
13
|
"types-pyyaml",
|
@@ -46,7 +47,7 @@ requires-python = "==3.13.*"
|
|
46
47
|
audiolibrarian = "audiolibrarian:cli.main"
|
47
48
|
|
48
49
|
[project.urls]
|
49
|
-
Repository = "https://
|
50
|
+
Repository = "https://github.com/toadstule/audiolibrarian"
|
50
51
|
|
51
52
|
[tool.hatch.build.targets.sdist]
|
52
53
|
exclude= [
|
@@ -77,6 +78,12 @@ strict = true
|
|
77
78
|
module = "picard_src.*"
|
78
79
|
ignore_errors = true # This is not our code.
|
79
80
|
|
81
|
+
[tool.pymarkdown]
|
82
|
+
plugins.md013.line_length = 100
|
83
|
+
plugins.md013.code_block_line_length = 100
|
84
|
+
#plugins.md007.enabled = true
|
85
|
+
#plugins.md007.code_block_line_length = 160
|
86
|
+
|
80
87
|
[tool.ruff]
|
81
88
|
extend-exclude = [
|
82
89
|
"picard_src", # This is not our code.
|
@@ -2,10 +2,10 @@
|
|
2
2
|
|
3
3
|
Code in this directory comes from (or is derived from) the super-cool Picard project.
|
4
4
|
|
5
|
-
https://github.com/metabrainz/picard
|
5
|
+
[Picard](https://github.com/metabrainz/picard)
|
6
6
|
|
7
7
|
I'd like to express my thanks to all of have contributed to that project.
|
8
8
|
|
9
|
-
Note: we could have just set the Picard library as a dependency of audiolibrarian, but
|
10
|
-
it includes other dependencies (such as PyQT) that add a lot of overhead not required
|
9
|
+
Note: we could have just set the Picard library as a dependency of audiolibrarian, but
|
10
|
+
it includes other dependencies (such as PyQT) that add a lot of overhead not required
|
11
11
|
by this project.
|
@@ -20,6 +20,20 @@ wheels = [
|
|
20
20
|
{ url = "https://files.pythonhosted.org/packages/53/18/a56e2fe47b259bb52201093a3a9d4a32014f9d85071ad07e9d60600890ca/ansicolors-1.1.8-py2.py3-none-any.whl", hash = "sha256:00d2dde5a675579325902536738dd27e4fac1fd68f773fe36c21044eb559e187", size = 13847, upload-time = "2017-06-02T21:22:12.67Z" },
|
21
21
|
]
|
22
22
|
|
23
|
+
[[package]]
|
24
|
+
name = "application-properties"
|
25
|
+
version = "0.8.2"
|
26
|
+
source = { registry = "https://pypi.jibson.com/simple" }
|
27
|
+
dependencies = [
|
28
|
+
{ name = "pyyaml" },
|
29
|
+
{ name = "tomli" },
|
30
|
+
{ name = "typing-extensions" },
|
31
|
+
]
|
32
|
+
sdist = { url = "https://files.pythonhosted.org/packages/c1/5e/29ec0fa553ee5befc6a1e47eb0c8ffea75eed941251524678700e2d3e747/application_properties-0.8.2.tar.gz", hash = "sha256:e5e6918c8e29ab57175567d51dfa39c00a1d75b3205625559bb02250f50f0420", size = 29595, upload-time = "2024-01-28T23:43:07.403Z" }
|
33
|
+
wheels = [
|
34
|
+
{ url = "https://files.pythonhosted.org/packages/06/27/ea2b77232385ec1c4b5cb766ee13b5a3085ed2fa789d61374e7af36b79e1/application_properties-0.8.2-py3-none-any.whl", hash = "sha256:a4fe684e4d95fc45054d3316acf763a7b0f29342ccea02eee09de53004f0139c", size = 18399, upload-time = "2024-01-28T23:43:05.631Z" },
|
35
|
+
]
|
36
|
+
|
23
37
|
[[package]]
|
24
38
|
name = "audiolibrarian"
|
25
39
|
source = { editable = "." }
|
@@ -42,6 +56,7 @@ dev = [
|
|
42
56
|
{ name = "coverage" },
|
43
57
|
{ name = "hatchling" },
|
44
58
|
{ name = "mypy" },
|
59
|
+
{ name = "pymarkdownlnt" },
|
45
60
|
{ name = "pytest" },
|
46
61
|
{ name = "ruff" },
|
47
62
|
{ name = "types-pyyaml" },
|
@@ -69,6 +84,7 @@ dev = [
|
|
69
84
|
{ name = "coverage" },
|
70
85
|
{ name = "hatchling" },
|
71
86
|
{ name = "mypy" },
|
87
|
+
{ name = "pymarkdownlnt" },
|
72
88
|
{ name = "pytest" },
|
73
89
|
{ name = "ruff" },
|
74
90
|
{ name = "types-pyyaml" },
|
@@ -116,6 +132,19 @@ wheels = [
|
|
116
132
|
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
|
117
133
|
]
|
118
134
|
|
135
|
+
[[package]]
|
136
|
+
name = "columnar"
|
137
|
+
version = "1.4.1"
|
138
|
+
source = { registry = "https://pypi.jibson.com/simple" }
|
139
|
+
dependencies = [
|
140
|
+
{ name = "toolz" },
|
141
|
+
{ name = "wcwidth" },
|
142
|
+
]
|
143
|
+
sdist = { url = "https://files.pythonhosted.org/packages/5e/0d/a0b2fd781050d29c9df64ac6df30b5f18b775724b79779f56fc5a8298fe9/Columnar-1.4.1.tar.gz", hash = "sha256:c3cb57273333b2ff9cfaafc86f09307419330c97faa88dcfe23df05e6fbb9c72", size = 11386, upload-time = "2021-12-27T21:58:56.123Z" }
|
144
|
+
wheels = [
|
145
|
+
{ url = "https://files.pythonhosted.org/packages/06/00/a17a5657bf090b9dffdb310ac273c553a38f9252f60224da9fe62d9b60e9/Columnar-1.4.1-py3-none-any.whl", hash = "sha256:8efb692a7e6ca07dcc8f4ea889960421331a5dffa8e5af81f0a67ad8ea1fc798", size = 11845, upload-time = "2021-12-27T21:58:54.388Z" },
|
146
|
+
]
|
147
|
+
|
119
148
|
[[package]]
|
120
149
|
name = "coverage"
|
121
150
|
version = "7.8.2"
|
@@ -370,6 +399,20 @@ wheels = [
|
|
370
399
|
{ url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293, upload-time = "2025-01-06T17:26:25.553Z" },
|
371
400
|
]
|
372
401
|
|
402
|
+
[[package]]
|
403
|
+
name = "pymarkdownlnt"
|
404
|
+
version = "0.9.30"
|
405
|
+
source = { registry = "https://pypi.jibson.com/simple" }
|
406
|
+
dependencies = [
|
407
|
+
{ name = "application-properties" },
|
408
|
+
{ name = "columnar" },
|
409
|
+
{ name = "typing-extensions" },
|
410
|
+
]
|
411
|
+
sdist = { url = "https://files.pythonhosted.org/packages/86/00/4156086d7f32e3058cebb6b813e93f5a227ae2590ac528b2344d2c669973/pymarkdownlnt-0.9.30.tar.gz", hash = "sha256:cf274935b128abd7f30c44314510d0f4d36965149bb9dae84f6cac9491dc1f58", size = 416281, upload-time = "2025-05-20T02:26:30.652Z" }
|
412
|
+
wheels = [
|
413
|
+
{ url = "https://files.pythonhosted.org/packages/28/92/81059c9eecd973168890e6b730f852abfd310389f67d4fb6b132a3976338/pymarkdownlnt-0.9.30-py3-none-any.whl", hash = "sha256:29b881434def9d3796be4a89cb277ab9f8f4fbb558379ce7836c653c9c351d2c", size = 500322, upload-time = "2025-05-20T02:26:29.098Z" },
|
414
|
+
]
|
415
|
+
|
373
416
|
[[package]]
|
374
417
|
name = "pytest"
|
375
418
|
version = "8.4.0"
|
@@ -487,6 +530,34 @@ wheels = [
|
|
487
530
|
{ url = "https://files.pythonhosted.org/packages/ec/bf/b273dd11673fed8a6bd46032c0ea2a04b2ac9bfa9c628756a5856ba113b0/ruff-0.11.13-py3-none-win_arm64.whl", hash = "sha256:b4385285e9179d608ff1d2fb9922062663c658605819a6876d8beef0c30b7f3b", size = 10683928, upload-time = "2025-06-05T21:00:13.758Z" },
|
488
531
|
]
|
489
532
|
|
533
|
+
[[package]]
|
534
|
+
name = "tomli"
|
535
|
+
version = "2.2.1"
|
536
|
+
source = { registry = "https://pypi.jibson.com/simple" }
|
537
|
+
sdist = { url = "https://files.pythonhosted.org/packages/18/87/302344fed471e44a87289cf4967697d07e532f2421fdaf868a303cbae4ff/tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff", size = 17175, upload-time = "2024-11-27T22:38:36.873Z" }
|
538
|
+
wheels = [
|
539
|
+
{ url = "https://files.pythonhosted.org/packages/04/90/2ee5f2e0362cb8a0b6499dc44f4d7d48f8fff06d28ba46e6f1eaa61a1388/tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7", size = 132708, upload-time = "2024-11-27T22:38:21.659Z" },
|
540
|
+
{ url = "https://files.pythonhosted.org/packages/c0/ec/46b4108816de6b385141f082ba99e315501ccd0a2ea23db4a100dd3990ea/tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c", size = 123582, upload-time = "2024-11-27T22:38:22.693Z" },
|
541
|
+
{ url = "https://files.pythonhosted.org/packages/a0/bd/b470466d0137b37b68d24556c38a0cc819e8febe392d5b199dcd7f578365/tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13", size = 232543, upload-time = "2024-11-27T22:38:24.367Z" },
|
542
|
+
{ url = "https://files.pythonhosted.org/packages/d9/e5/82e80ff3b751373f7cead2815bcbe2d51c895b3c990686741a8e56ec42ab/tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281", size = 241691, upload-time = "2024-11-27T22:38:26.081Z" },
|
543
|
+
{ url = "https://files.pythonhosted.org/packages/05/7e/2a110bc2713557d6a1bfb06af23dd01e7dde52b6ee7dadc589868f9abfac/tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272", size = 251170, upload-time = "2024-11-27T22:38:27.921Z" },
|
544
|
+
{ url = "https://files.pythonhosted.org/packages/64/7b/22d713946efe00e0adbcdfd6d1aa119ae03fd0b60ebed51ebb3fa9f5a2e5/tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140", size = 236530, upload-time = "2024-11-27T22:38:29.591Z" },
|
545
|
+
{ url = "https://files.pythonhosted.org/packages/38/31/3a76f67da4b0cf37b742ca76beaf819dca0ebef26d78fc794a576e08accf/tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2", size = 258666, upload-time = "2024-11-27T22:38:30.639Z" },
|
546
|
+
{ url = "https://files.pythonhosted.org/packages/07/10/5af1293da642aded87e8a988753945d0cf7e00a9452d3911dd3bb354c9e2/tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744", size = 243954, upload-time = "2024-11-27T22:38:31.702Z" },
|
547
|
+
{ url = "https://files.pythonhosted.org/packages/5b/b9/1ed31d167be802da0fc95020d04cd27b7d7065cc6fbefdd2f9186f60d7bd/tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec", size = 98724, upload-time = "2024-11-27T22:38:32.837Z" },
|
548
|
+
{ url = "https://files.pythonhosted.org/packages/c7/32/b0963458706accd9afcfeb867c0f9175a741bf7b19cd424230714d722198/tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69", size = 109383, upload-time = "2024-11-27T22:38:34.455Z" },
|
549
|
+
{ url = "https://files.pythonhosted.org/packages/6e/c2/61d3e0f47e2b74ef40a68b9e6ad5984f6241a942f7cd3bbfbdbd03861ea9/tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc", size = 14257, upload-time = "2024-11-27T22:38:35.385Z" },
|
550
|
+
]
|
551
|
+
|
552
|
+
[[package]]
|
553
|
+
name = "toolz"
|
554
|
+
version = "1.0.0"
|
555
|
+
source = { registry = "https://pypi.jibson.com/simple" }
|
556
|
+
sdist = { url = "https://files.pythonhosted.org/packages/8a/0b/d80dfa675bf592f636d1ea0b835eab4ec8df6e9415d8cfd766df54456123/toolz-1.0.0.tar.gz", hash = "sha256:2c86e3d9a04798ac556793bced838816296a2f085017664e4995cb40a1047a02", size = 66790, upload-time = "2024-10-04T16:17:04.001Z" }
|
557
|
+
wheels = [
|
558
|
+
{ url = "https://files.pythonhosted.org/packages/03/98/eb27cc78ad3af8e302c9d8ff4977f5026676e130d28dd7578132a457170c/toolz-1.0.0-py3-none-any.whl", hash = "sha256:292c8f1c4e7516bf9086f8850935c799a874039c8bcf959d47b600e4c44a6236", size = 56383, upload-time = "2024-10-04T16:17:01.533Z" },
|
559
|
+
]
|
560
|
+
|
490
561
|
[[package]]
|
491
562
|
name = "trove-classifiers"
|
492
563
|
version = "2025.5.9.12"
|
@@ -556,6 +627,15 @@ wheels = [
|
|
556
627
|
{ url = "https://files.pythonhosted.org/packages/6b/11/cc635220681e93a0183390e26485430ca2c7b5f9d33b15c74c2861cb8091/urllib3-2.4.0-py3-none-any.whl", hash = "sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813", size = 128680, upload-time = "2025-04-10T15:23:37.377Z" },
|
557
628
|
]
|
558
629
|
|
630
|
+
[[package]]
|
631
|
+
name = "wcwidth"
|
632
|
+
version = "0.2.13"
|
633
|
+
source = { registry = "https://pypi.jibson.com/simple" }
|
634
|
+
sdist = { url = "https://files.pythonhosted.org/packages/6c/63/53559446a878410fc5a5974feb13d31d78d752eb18aeba59c7fef1af7598/wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5", size = 101301, upload-time = "2024-01-06T02:10:57.829Z" }
|
635
|
+
wheels = [
|
636
|
+
{ url = "https://files.pythonhosted.org/packages/fd/84/fd2ba7aafacbad3c4201d395674fc6348826569da3c0937e75505ead3528/wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859", size = 34166, upload-time = "2024-01-06T02:10:55.763Z" },
|
637
|
+
]
|
638
|
+
|
559
639
|
[[package]]
|
560
640
|
name = "xdg-base-dirs"
|
561
641
|
version = "6.0.2"
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{audiolibrarian-0.16.2 → audiolibrarian-0.16.4}/src/audiolibrarian/audiofile/formats/__init__.py
RENAMED
File without changes
|
{audiolibrarian-0.16.2 → audiolibrarian-0.16.4}/src/audiolibrarian/audiofile/formats/flac.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|