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:
Philipp Wolfer
2022-01-20 23:33:43 +01:00
parent 11d71bcc8c
commit 574e7a90c1
3 changed files with 79 additions and 12 deletions

View File

@@ -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)

View File

@@ -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):

View File

@@ -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)