mirror of
https://github.com/fergalmoran/picard.git
synced 2026-01-06 00:23:58 +00:00
PICARD-2396: Submit metadata to AcoustID on duration mismatch
If a file's duration does clearly not match the MB recording duration allow AcoustID submission anyway. But instead of submitting the recording MBID submit only the metadata. This prevents clear mismatches while still allowing fingerprint submission. The submitted metadata can give a hint on the recording.
This commit is contained in:
@@ -31,8 +31,8 @@ from picard import log
|
||||
from picard.util import load_json
|
||||
|
||||
|
||||
# Maximum difference between file duration and MB metadata length.
|
||||
# If the match is above this threshold the fingerprint will not get submitted.
|
||||
# Maximum difference between file duration and MB recording length.
|
||||
# If the match is above this threshold the MBID will not get submitted.
|
||||
# Compare also acoustid/const.py in acoustid-server sources
|
||||
FINGERPRINT_MAX_ALLOWED_LENGTH_DIFF_MS = 30000
|
||||
|
||||
@@ -111,7 +111,7 @@ class AcoustIDManager(QtCore.QObject):
|
||||
|
||||
def _unsubmitted(self, reset=False):
|
||||
for file, submission in self._submissions.items():
|
||||
if not submission.is_submitted and submission.valid_duration:
|
||||
if not submission.is_submitted:
|
||||
if reset:
|
||||
submission.attempts = 0
|
||||
yield (file, submission)
|
||||
|
||||
@@ -297,12 +297,28 @@ class AcoustIdAPIHelper(APIHelper):
|
||||
def _submissions_to_args(submissions):
|
||||
config = get_config()
|
||||
args = {'user': config.setting["acoustid_apikey"]}
|
||||
|
||||
def set_arg(name, i, value):
|
||||
if value:
|
||||
args[".".join((name, str(i)))] = value
|
||||
|
||||
for i, submission in enumerate(submissions):
|
||||
args['fingerprint.%d' % i] = submission.fingerprint
|
||||
args['duration.%d' % i] = str(submission.duration)
|
||||
args['mbid.%d' % i] = submission.recordingid
|
||||
if submission.puid:
|
||||
args['puid.%d' % i] = submission.puid
|
||||
set_arg('fingerprint', i, submission.fingerprint)
|
||||
set_arg('duration', i, str(submission.duration))
|
||||
set_arg('puid', i, submission.puid)
|
||||
if submission.valid_duration:
|
||||
set_arg('mbid', i, submission.recordingid)
|
||||
else:
|
||||
metadata = submission.metadata
|
||||
set_arg('track', i, metadata['title'])
|
||||
set_arg('artist', i, metadata['artist'])
|
||||
set_arg('album', i, metadata['album'])
|
||||
set_arg('albumartist', i, metadata['albumartist'])
|
||||
year = metadata['year'] or metadata['date'][:4]
|
||||
if year and year.isdecimal():
|
||||
set_arg('year', i, year)
|
||||
set_arg('trackno', i, metadata['tracknumber'])
|
||||
set_arg('discno', i, metadata['discnumber'])
|
||||
return args
|
||||
|
||||
def submit_acoustid_fingerprints(self, submissions, handler):
|
||||
|
||||
@@ -27,6 +27,7 @@ from unittest.mock import MagicMock
|
||||
from test.picardtestcase import PicardTestCase
|
||||
|
||||
from picard.acoustid.manager import Submission
|
||||
from picard.metadata import Metadata
|
||||
from picard.webservice import WebService
|
||||
from picard.webservice.api_helpers import (
|
||||
AcoustIdAPIHelper,
|
||||
@@ -239,11 +240,11 @@ class AcoustdIdAPITest(PicardTestCase):
|
||||
|
||||
def test_submissions_to_args(self):
|
||||
submissions = [
|
||||
Submission('f1', 1, recordingid='r1', metadata={'musicip_puid': 'p1'}),
|
||||
Submission('f2', 2, recordingid='r2', metadata={'musicip_puid': 'p2'}),
|
||||
Submission('f1', 1, recordingid='or1', metadata=Metadata(musicip_puid='p1')),
|
||||
Submission('f2', 2, recordingid='or2', metadata=Metadata(musicip_puid='p2')),
|
||||
]
|
||||
submissions[0].orig_recordingid = 'or1'
|
||||
submissions[1].orig_recordingid = 'or2'
|
||||
submissions[0].recordingid = 'r1'
|
||||
submissions[1].recordingid = 'r2'
|
||||
result = self.api._submissions_to_args(submissions)
|
||||
expected = {
|
||||
'user': 'apikey',
|
||||
@@ -251,3 +252,53 @@ class AcoustdIdAPITest(PicardTestCase):
|
||||
'fingerprint.1': 'f2', 'duration.1': '2', 'mbid.1': 'r2', 'puid.1': 'p2'
|
||||
}
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_submissions_to_args_invalid_duration(self):
|
||||
metadata1 = Metadata({
|
||||
'title': 'The Track',
|
||||
'artist': 'The Artist',
|
||||
'album': 'The Album',
|
||||
'albumartist': 'The Album Artist',
|
||||
'tracknumber': '4',
|
||||
'discnumber': '2',
|
||||
}, length=100000)
|
||||
metadata2 = Metadata({
|
||||
'year': '2022'
|
||||
}, length=100000)
|
||||
metadata3 = Metadata({
|
||||
'date': '1980-08-30'
|
||||
}, length=100000)
|
||||
metadata4 = Metadata({
|
||||
'date': '08-30'
|
||||
}, length=100000)
|
||||
submissions = [
|
||||
Submission('f1', 500000, recordingid='or1', metadata=metadata1),
|
||||
Submission('f2', 500000, recordingid='or2', metadata=metadata2),
|
||||
Submission('f3', 500000, recordingid='or3', metadata=metadata3),
|
||||
Submission('f4', 500000, recordingid='or4', metadata=metadata4),
|
||||
]
|
||||
submissions[0].recordingid = 'r1'
|
||||
submissions[1].recordingid = 'r2'
|
||||
submissions[1].recordingid = 'r3'
|
||||
submissions[1].recordingid = 'r4'
|
||||
result = self.api._submissions_to_args(submissions)
|
||||
expected = {
|
||||
'user': 'apikey',
|
||||
'fingerprint.0': 'f1',
|
||||
'duration.0': '500000',
|
||||
'track.0': metadata1['title'],
|
||||
'artist.0': metadata1['artist'],
|
||||
'album.0': metadata1['album'],
|
||||
'albumartist.0': metadata1['albumartist'],
|
||||
'trackno.0': metadata1['tracknumber'],
|
||||
'discno.0': metadata1['discnumber'],
|
||||
'fingerprint.1': 'f2',
|
||||
'duration.1': '500000',
|
||||
'year.1': '2022',
|
||||
'fingerprint.2': 'f3',
|
||||
'duration.2': '500000',
|
||||
'year.2': '1980',
|
||||
'fingerprint.3': 'f4',
|
||||
'duration.3': '500000',
|
||||
}
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
Reference in New Issue
Block a user