bcgenre
A beets plugin that fetches genre tags from Bandcamp release pages and merges them into your library’s genres field.
It is meant to complement lastgenre: Last.fm often misses artist-authored Bandcamp tags (and Bandcamp’s hyphenated forms like hip-hop / neo-soul). bcgenre reads those tags from the release page, normalizes them with lastgenre’s helpers, and filters them against a MusicBrainz genre whitelist.
Requirements
- beets (includes the
lastgenrepackage used for whitelist / aliases / canonicalization data) - beetcamp (
bandcampplugin) for Bandcamp HTML parsing and slug helpers - A Bandcamp URL in each item’s
commentsfield (artist root or album URL), e.g.Visit https://artist.bandcamp.com
Install
Clone or copy this package so beets can see beetsplug/bcgenre:
beetsplug/
bcgenre/
__init__.py
genres.py
resolve.py
README.md
Point pluginpath at the parent of that beetsplug directory (or at the beetsplug directory itself — both work with beets), then enable the plugin:
plugins: lastgenre bandcamp bcgenre
pluginpath: /path/to/parent # directory that contains beetsplug/
Confirm it loads:
beet bcgenre -h
Configuration
Options live under bcgenre: and mirror lastgenre’s shared settings (they do not inherit from your lastgenre: block):
bcgenre:
auto: no
force: no
keep_existing: no
count: 1
whitelist: yes # yes = lastgenre's genres.txt; or a path to your own list
aliases: yes # yes = lastgenre's aliases.yaml; no = off; or an inline mapping
canonical: no # yes = add parent genres from lastgenre's genres-tree.yaml
title_case: yes
fallback: # optional genre when Bandcamp yields nothing
pretend: no
| Option | Meaning |
|---|---|
force |
Modify items that already have genres |
keep_existing |
When forcing, union Bandcamp genres with existing ones |
count |
Max genres kept from Bandcamp after filtering (union with keep_existing can exceed this) |
whitelist |
Genre allow-list; yes uses lastgenre’s bundled MusicBrainz list |
aliases |
Spelling normalization (hip-hop → hip hop, etc.) |
canonical |
Expand matched tags with parent genres from the genre tree |
auto |
Run during import (off by default; prefer batch runs) |
title_case |
Title-case written genres |
File writes follow your global import.write setting (same as lastgenre).
Usage
# Preview changes (no DB / file writes)
beet bcgenre -p
# Apply (uses config force / keep_existing)
beet bcgenre
# Force + replace existing genres
beet bcgenre -f -K
# Force + union with existing genres
beet bcgenre -f -k
# Limit to a query (albums by default)
beet bcgenre -p albumartist:Aesop\ Rock
beet bcgenre -A artist:Aesop\ Rock # items instead of albums
CLI flags match lastgenre: -p/--pretend, -f/-F (force), -k/-K (keep-existing), -a/-A (albums/items).
Output shows the same per-track genres: + / - diffs as lastgenre.
How URL resolution works
For each album, bcgenre:
- Reuses a cached
bandcamp_album_urlflex field if present - Uses a deep
/album/...(or/track/...) URL fromcommentswhen available - Otherwise takes the Bandcamp root from
commentsand guesses/album/{slug} - On miss, scrapes
{root}/musicand fuzzy-matches the album title (handles Bandcamp’s-2slug collisions)
Resolved URLs are stored in bandcamp_album_url so re-runs avoid most network work.
Requests are paced at about 1 per second (not configurable), with backoff and abort on repeated HTTP 429 responses.
Tips
- Prefer a pretend pass first:
beet bcgenre -p -f -k - Albums without a Bandcamp URL in
commentsare skipped - Translated or heavily renamed titles may not match Bandcamp’s discography listing; set
bandcamp_album_urlmanually or restore a closer title lastgenredoes not need to be enabled for bcgenre to use its data files, but enabling both is the usual setup
Metadata
Release files for beets-bcgenre 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| beets_bcgenre-0.1.0.tar.gz | 11.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| beets_bcgenre-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 23.1 kB
Release files / beets_bcgenre-0.1.0.tar.gz
| Download URL | beets_bcgenre-0.1.0.tar.gz |
|---|---|
| Size | 11.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
798c0799a62bb5ef07f79ac98f000f54eb0f51ee581d9b1c3e22898a8c0e1e42
|
|
BLAKE2b-256 checksum How to use checksums |
b8b544414335ef81ac4ee03f65c993cf37587adba9772c57218e21cfe57a095d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.13
|
Release files / beets_bcgenre-0.1.0-py3-none-any.whl
| Download URL | beets_bcgenre-0.1.0-py3-none-any.whl |
|---|---|
| Size | 12.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ef8b086b192891aff2679733fa46011ba9b27c666d2a858194a116375102d4c0
|
|
BLAKE2b-256 checksum How to use checksums |
2d0ae83f6c0642499fe1986cb3c701d307039b8d7c4bd1ca5941cc87376b6cb4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.13
|