mirror of
https://github.com/beetbox/beets.git
synced 2025-12-06 08:39:17 +01:00
226 lines
8.7 KiB
ReStructuredText
226 lines
8.7 KiB
ReStructuredText
LastGenre Plugin
|
||
================
|
||
|
||
The ``lastgenre`` plugin fetches *tags* from Last.fm_ and assigns them as genres
|
||
to your albums and items.
|
||
|
||
.. _last.fm: https://last.fm/
|
||
|
||
Installation
|
||
------------
|
||
|
||
To use the ``lastgenre`` plugin, first enable it in your configuration (see
|
||
:ref:`using-plugins`). Then, install ``beets`` with ``lastgenre`` extra
|
||
|
||
.. code-block:: bash
|
||
|
||
pip install "beets[lastgenre]"
|
||
|
||
Usage
|
||
-----
|
||
|
||
The plugin chooses genres based on a *whitelist*, meaning that only certain tags
|
||
can be considered genres. This way, tags like "my favorite music" or "seen live"
|
||
won't be considered genres. The plugin ships with a fairly extensive `internal
|
||
whitelist`_, but you can set your own in the config file using the ``whitelist``
|
||
configuration value or forgo a whitelist altogether by setting the option to
|
||
``no``.
|
||
|
||
The genre list file should contain one genre per line. Blank lines are ignored.
|
||
For the curious, the default genre list is generated by a `script that scrapes
|
||
Wikipedia`_.
|
||
|
||
.. _internal whitelist: https://raw.githubusercontent.com/beetbox/beets/master/beetsplug/lastgenre/genres.txt
|
||
|
||
.. _script that scrapes wikipedia: https://gist.github.com/1241307
|
||
|
||
Canonicalization
|
||
~~~~~~~~~~~~~~~~
|
||
|
||
The plugin can also *canonicalize* genres, meaning that more obscure genres can
|
||
be turned into coarser-grained ones that are present in the whitelist. This
|
||
works using a `tree of nested genre names`_, represented using YAML_, where the
|
||
leaves of the tree represent the most specific genres.
|
||
|
||
The most common way to use this would be with a custom whitelist containing only
|
||
a desired subset of genres. Consider for a example this minimal whitelist:
|
||
|
||
::
|
||
|
||
rock
|
||
heavy metal
|
||
pop
|
||
|
||
together with the default genre tree. Then an item that has its genre specified
|
||
as *viking metal* would actually be tagged as *heavy metal* because neither
|
||
*viking metal* nor its parent *black metal* are in the whitelist. It always
|
||
tries to use the most specific genre that's available in the whitelist.
|
||
|
||
The relevant subtree path in the default tree looks like this:
|
||
|
||
::
|
||
|
||
- rock:
|
||
- heavy metal:
|
||
- black metal:
|
||
- viking metal
|
||
|
||
Considering that, it's not very useful to use the default whitelist (which
|
||
contains about any genre contained in the tree) with canonicalization because
|
||
nothing would ever be matched to a more generic node since all the specific
|
||
subgenres are in the whitelist to begin with.
|
||
|
||
.. _tree of nested genre names: https://raw.githubusercontent.com/beetbox/beets/master/beetsplug/lastgenre/genres-tree.yaml
|
||
|
||
.. _yaml: https://yaml.org/
|
||
|
||
Genre Source
|
||
~~~~~~~~~~~~
|
||
|
||
When looking up genres for albums or individual tracks, you can choose whether
|
||
to use Last.fm tags on the album, the artist, or the track. For example, you
|
||
might want all the albums for a certain artist to carry the same genre. The
|
||
default is "album". When set to "track", the plugin will fetch *both*
|
||
album-level and track-level genres for your music when importing albums.
|
||
|
||
Multiple Genres
|
||
~~~~~~~~~~~~~~~
|
||
|
||
By default, the plugin chooses the most popular tag on Last.fm as a genre. If
|
||
you prefer to use a *list* of popular genre tags, you can increase the number of
|
||
the ``count`` config option.
|
||
|
||
Lists of up to *count* genres will then be used instead of single genres. The
|
||
genres are separated by commas by default, but you can change this with the
|
||
``separator`` config option.
|
||
|
||
Last.fm_ provides a popularity factor, a.k.a. *weight*, for each tag ranging
|
||
from 100 for the most popular tag down to 0 for the least popular. The plugin
|
||
uses this weight to discard unpopular tags. The default is to ignore tags with a
|
||
weight less then 10. You can change this by setting the ``min_weight`` config
|
||
option.
|
||
|
||
Specific vs. Popular Genres
|
||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
|
||
By default, the plugin sorts genres by popularity. However, you can use the
|
||
``prefer_specific`` option to override this behavior and instead sort genres by
|
||
specificity, as determined by your whitelist and canonicalization tree.
|
||
|
||
For instance, say you have both ``folk`` and ``americana`` in your whitelist and
|
||
canonicalization tree and ``americana`` is a leaf within ``folk``. If Last.fm
|
||
returns both of those tags, lastgenre is going to use the most popular, which is
|
||
often the most generic (in this case ``folk``). By setting ``prefer_specific``
|
||
to true, lastgenre would use ``americana`` instead.
|
||
|
||
Handling pre-populated tags
|
||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
|
||
The ``force``, ``keep_existing`` and ``whitelist`` options control how
|
||
pre-existing genres are handled.
|
||
|
||
As you would assume, setting ``force: no`` **won't touch pre-existing genre
|
||
tags** and will only **fetch new genres for empty tags**. When ``force`` is
|
||
``yes`` the setting of the ``whitelist`` option (as documented in Usage_)
|
||
applies to any existing or newly fetched genres.
|
||
|
||
The following configurations are possible:
|
||
|
||
**Setup 1** (default)
|
||
|
||
Add new last.fm genres when **empty**. Any present tags stay **untouched**.
|
||
|
||
.. code-block:: yaml
|
||
|
||
force: no
|
||
keep_existing: no
|
||
|
||
**Setup 2**
|
||
|
||
**Overwrite all**. Only fresh last.fm genres remain.
|
||
|
||
.. code-block:: yaml
|
||
|
||
force: yes
|
||
keep_existing: no
|
||
|
||
**Setup 3**
|
||
|
||
**Combine** genres in present tags with new ones (be aware of that with an
|
||
enabled ``whitelist`` setting, of course some genres might get cleaned up -
|
||
existing genres take precedence over new ones though. To make sure any existing
|
||
genres remain, set ``whitelist: no``).
|
||
|
||
.. code-block:: yaml
|
||
|
||
force: yes
|
||
keep_existing: yes
|
||
|
||
.. attention::
|
||
|
||
If ``force`` is disabled the ``keep_existing`` option is simply ignored
|
||
(since ``force: no`` means ``not touching`` existing tags anyway).
|
||
|
||
Configuration
|
||
-------------
|
||
|
||
To configure the plugin, make a ``lastgenre:`` section in your configuration
|
||
file. The available options are:
|
||
|
||
- **auto**: Fetch genres automatically during import. Default: ``yes``.
|
||
- **canonical**: Use a canonicalization tree. Setting this to ``yes`` will use a
|
||
built-in tree. You can also set it to a path, like the ``whitelist`` config
|
||
value, to use your own tree. Default: ``no`` (disabled).
|
||
- **count**: Number of genres to fetch. Default: 1
|
||
- **fallback**: A string to use as a fallback genre when no genre is found
|
||
``or`` the original genre is not desired to be kept (``keep_existing: no``).
|
||
You can use the empty string ``''`` to reset the genre. Default: None.
|
||
- **force**: By default, lastgenre will fetch new genres for empty tags only,
|
||
enable this option to always try to fetch new last.fm genres. Enable the
|
||
``keep_existing`` option to combine existing and new genres. (see `Handling
|
||
pre-populated tags`_). Default: ``no``.
|
||
- **keep_existing**: This option alters the ``force`` behavior. If both
|
||
``force`` and ``keep_existing`` are enabled, existing genres are combined with
|
||
new ones. Depending on the ``whitelist`` setting, existing and new genres are
|
||
filtered accordingly. To ensure only fresh last.fm genres, disable this
|
||
option. (see `Handling pre-populated tags`_) Default: ``no``.
|
||
- **min_weight**: Minimum popularity factor below which genres are discarded.
|
||
Default: 10.
|
||
- **prefer_specific**: Sort genres by the most to least specific, rather than
|
||
most to least popular. Note that this option requires a ``canonical`` tree,
|
||
and if not configured it will automatically enable and use the built-in tree.
|
||
Default: ``no``.
|
||
- **source**: Which entity to look up in Last.fm. Can be either ``artist``,
|
||
``album`` or ``track``. Default: ``album``.
|
||
- **separator**: A separator for multiple genres. Default: ``', '``.
|
||
- **whitelist**: The filename of a custom genre list, ``yes`` to use the
|
||
internal whitelist, or ``no`` to consider all genres valid. Default: ``yes``.
|
||
- **title_case**: Convert the new tags to TitleCase before saving. Default:
|
||
``yes``.
|
||
|
||
Running Manually
|
||
----------------
|
||
|
||
In addition to running automatically on import, the plugin can also be run
|
||
manually from the command line. Use the command ``beet lastgenre [QUERY]`` to
|
||
fetch genres for albums or items matching a certain query.
|
||
|
||
By default, ``beet lastgenre`` matches albums. To match individual tracks or
|
||
singletons, use the ``-A`` switch: ``beet lastgenre -A [QUERY]``.
|
||
|
||
To preview the changes that would be made without applying them, use the ``-p``
|
||
or ``--pretend`` flag. This shows which genres would be set but does not write
|
||
or store any changes.
|
||
|
||
To disable automatic genre fetching on import, set the ``auto`` config option to
|
||
false.
|
||
|
||
Tuning Logs
|
||
-----------
|
||
|
||
To enable tuning logs, run ``beet -vvv lastgenre ...`` or ``beet -vvv import
|
||
...``. This enables additional messages at the ``DEBUG`` log level, showing for
|
||
example what data was received from last.fm at each stage of genre fetching
|
||
(artist, album, and track levels) before any canonicalization or whitelist
|
||
filtering is applied. Tuning logs are useful for adjusting the plugin’s settings
|
||
and understanding its behavior, though they can be quite verbose.
|