mirror of
https://github.com/beetbox/beets.git
synced 2026-01-29 19:43:20 +01:00
store Acoustid data in DB & file
This is accomplished via a new event, "import_task_apply", which is called right after metadata is applied to newly-imported items. This change makes chroma REQUIRE a new version (0.6) of pyacoustid. Users with older versions installed will see complaints about a missing method "fingerprint_file".
This commit is contained in:
parent
82a4bafc3e
commit
01dce53212
5 changed files with 48 additions and 16 deletions
|
|
@ -557,7 +557,7 @@ def initial_lookup(config):
|
|||
if task.sentinel:
|
||||
continue
|
||||
|
||||
plugins.send('start_import_task', task=task, config=config)
|
||||
plugins.send('import_task_start', task=task, config=config)
|
||||
|
||||
log.debug('Looking up: %s' % task.path)
|
||||
try:
|
||||
|
|
@ -653,6 +653,7 @@ def apply_choices(config):
|
|||
autotag.apply_metadata(task.items, task.info)
|
||||
else:
|
||||
autotag.apply_item_metadata(task.item, task.info)
|
||||
plugins.send('import_task_apply', config=config, task=task)
|
||||
|
||||
# Infer album-level fields.
|
||||
if task.is_album:
|
||||
|
|
@ -813,7 +814,7 @@ def item_lookup(config):
|
|||
if task.sentinel:
|
||||
continue
|
||||
|
||||
plugins.send('start_import_task', task=task, config=config)
|
||||
plugins.send('import_task_start', task=task, config=config)
|
||||
|
||||
task.set_item_match(*autotag.tag_item(task.item, config.timid))
|
||||
|
||||
|
|
|
|||
|
|
@ -36,18 +36,27 @@ log = logging.getLogger('beets')
|
|||
# was found.
|
||||
_matches = {}
|
||||
|
||||
# Stores the fingerprint and Acoustid ID for each track. This is stored
|
||||
# as metadata for each track for later use but is not relevant for
|
||||
# autotagging.
|
||||
_fingerprints = {}
|
||||
_acoustids = {}
|
||||
|
||||
|
||||
def acoustid_match(path):
|
||||
"""Gets metadata for a file from Acoustid. Returns a recording ID
|
||||
and a list of release IDs if a match is found; otherwise, returns
|
||||
None.
|
||||
"""Gets metadata for a file from Acoustid and populates the
|
||||
_matches, _fingerprints, and _acoustids dictionaries accordingly.
|
||||
"""
|
||||
try:
|
||||
res = acoustid.match(API_KEY, path, meta='recordings releases',
|
||||
parse=False)
|
||||
duration, fp = acoustid.fingerprint_file(path)
|
||||
except acoustid.FingerprintGenerationError, exc:
|
||||
log.error('fingerprinting of %s failed: %s' %
|
||||
(repr(path), str(exc)))
|
||||
return None
|
||||
_fingerprints[path] = fp
|
||||
try:
|
||||
res = acoustid.lookup(API_KEY, fp, duration,
|
||||
meta='recordings releases')
|
||||
except acoustid.AcoustidError, exc:
|
||||
log.debug('fingerprint matching %s failed: %s' %
|
||||
(repr(path), str(exc)))
|
||||
|
|
@ -59,8 +68,14 @@ def acoustid_match(path):
|
|||
log.debug('chroma: no match found')
|
||||
return None
|
||||
result = res['results'][0]
|
||||
if result['score'] < SCORE_THRESH or not result.get('recordings'):
|
||||
log.debug('chroma: no recordings above threshold')
|
||||
if result['score'] < SCORE_THRESH:
|
||||
log.debug('chroma: no results above threshold')
|
||||
return None
|
||||
_acoustids[path] = result['id']
|
||||
|
||||
# Get recordings from the result.
|
||||
if not result.get('recordings'):
|
||||
log.debug('chroma: no recordings found')
|
||||
return None
|
||||
recording = result['recordings'][0]
|
||||
recording_id = recording['id']
|
||||
|
|
@ -70,7 +85,7 @@ def acoustid_match(path):
|
|||
release_ids = []
|
||||
|
||||
log.debug('chroma: matched recording {}'.format(recording_id))
|
||||
return recording_id, release_ids
|
||||
_matches[path] = recording_id, release_ids
|
||||
|
||||
def _all_releases(items):
|
||||
"""Given an iterable of Items, determines (according to Acoustid)
|
||||
|
|
@ -126,12 +141,20 @@ class AcoustidPlugin(plugins.BeetsPlugin):
|
|||
log.debug('no acoustid item candidate found')
|
||||
return []
|
||||
|
||||
@AcoustidPlugin.listen('start_import_task')
|
||||
@AcoustidPlugin.listen('import_task_start')
|
||||
def fingerprint_task(config=None, task=None):
|
||||
"""Fingerprint each item in the task for later use during the
|
||||
autotagging candidate search.
|
||||
"""
|
||||
for item in task.all_items():
|
||||
match = acoustid_match(item.path)
|
||||
if match:
|
||||
_matches[item.path] = match
|
||||
acoustid_match(item.path)
|
||||
|
||||
@AcoustidPlugin.listen('import_task_apply')
|
||||
def apply_acoustid_metadata(config=None, task=None):
|
||||
"""Apply Acoustid metadata (fingerprint and ID) to the task's items.
|
||||
"""
|
||||
for item in task.all_items():
|
||||
if item.path in _fingerprints:
|
||||
item.acoustid_fingerprint = _fingerprints[item.path]
|
||||
if item.path in _acoustids:
|
||||
item.acoustid_id = _acoustids[item.path]
|
||||
|
|
|
|||
|
|
@ -14,6 +14,9 @@ Changelog
|
|||
fields, ``artist_sort`` and ``albumartist_sort``, that contain sortable artist
|
||||
names like "Beatles, The". These fields are also used to sort albums and items
|
||||
when using the ``list`` command. Thanks to Paul Provost.
|
||||
* :doc:`/plugins/chroma`: The Chromaprint fingerprint and Acoustid ID are now
|
||||
stored for all fingerprinted tracks. This version of beets *requires* at least
|
||||
version 0.6 of `pyacoustid`_ for fingerprinting to work.
|
||||
* New :doc:`/plugins/rdm`: Randomly select albums and tracks from your library.
|
||||
Thanks to Philippe Mongeau.
|
||||
* The :doc:`/plugins/mbcollection` by Jeffrey Aylesworth was added to the core
|
||||
|
|
@ -27,6 +30,8 @@ Changelog
|
|||
* Filenames are normalized with Unicode Normal Form D (NFD) on Mac OS X and NFC
|
||||
on all other platforms.
|
||||
|
||||
.. _pyacoustid: https://github.com/sampsyo/pyacoustid
|
||||
|
||||
|
||||
1.0b13 (March 16, 2012)
|
||||
-----------------------
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ Installing Dependencies
|
|||
|
||||
To get fingerprinting working, you'll need to install three things: the
|
||||
`Chromaprint`_ library or command-line tool, an audio decoder, and the
|
||||
`pyacoustid`_ Python library.
|
||||
`pyacoustid`_ Python library (version 0.6 or later).
|
||||
|
||||
First, you will need to install `Chromaprint`_, either as a dynamic library or
|
||||
in the form of a command-line tool (``fpcalc``). The Chromaprint site has links
|
||||
|
|
|
|||
|
|
@ -134,9 +134,12 @@ currently available are:
|
|||
* *write*: called with an ``Item`` and a ``MediaFile`` object just before a
|
||||
file's metadata is written to disk.
|
||||
|
||||
* *start_import_task*: called when before an import task begins processing.
|
||||
* *import_task_start*: called when before an import task begins processing.
|
||||
Parameters: ``task`` and ``config``.
|
||||
|
||||
* *import_task_apply*: called after metadata changes have been applied in an
|
||||
import task. Parameters: ``task`` and ``config``.
|
||||
|
||||
The included ``mpdupdate`` plugin provides an example use case for event listeners.
|
||||
|
||||
Extend the Autotagger
|
||||
|
|
|
|||
Loading…
Reference in a new issue