Use TinyTag for local files to speedup pulling tags from media files

Use TinyTag instead of gstream to significantly speedup collecting tags
from media files. It especially helpfull with slow CPU
This commit is contained in:
Andrey Perminov 2019-07-02 13:31:46 -07:00
parent 49a08f1701
commit 76395522d0
3 changed files with 1234 additions and 56 deletions

View File

@ -10,6 +10,9 @@ from mopidy.audio import tags as tags_lib, utils
from mopidy.internal import encoding, log
from mopidy.internal.gi import Gst, GstPbutils
from mopidy.audio.tinytag import TinyTag
from urllib import unquote
# GST_ELEMENT_FACTORY_LIST:
_DECODER = 1 << 0
_AUDIO = 1 << 50
@ -62,6 +65,55 @@ class Scanner(object):
:class:`None` if the URI has no duration. ``seekable`` is boolean.
indicating if a seek would succeed.
"""
if uri[:4] == 'file':
duration, seekable, mime = None, None, None
tags = {}
try:
fname = unquote(uri[7:]).encode('raw_unicode_escape').decode('utf-8')
supported = False
extensions = ['.mp3', '.oga', '.ogg', '.opus', '.wav', '.flac', '.wma', '.m4b', '.m4a', '.mp4']
for fileextension in extensions:
if fname.lower().endswith(fileextension):
supported = True
break
if supported:
tag = TinyTag.get(fname, image=False)
if tag.album: tags['album'] = tag.album.rstrip('\0') # album as string
if tag.albumartist: tags['albumartist'] = tag.albumartist.rstrip('\0') # album artist as string
if tag.artist: tags['artist'] = tag.artist.rstrip('\0') # artist name as string
#if tag.audio_offset # number of bytes before audio data begins
if tag.bitrate: tags['bitrate'] = int(tag.bitrate) # bitrate in kBits/s
if tag.disc: tags['disc'] = int(tag.disc.rstrip('\0')) # disk number in album
if tag.disc_total: tags['disc_total'] = int(tag.disc_total.rstrip('\0')) # the total number of discs
duration=int(float(tag.duration) * 1000) # duration of the song in seconds
#if tag.filesize # file size in bytes
if tag.genre: tags['genre'] = tag.genre.rstrip('\0') # genre as string
#if tag.samplerate # samples per second
if tag.title: tags['title'] = tag.title.rstrip('\0') # title of the song
if tag.track: tags['track'] = int(tag.track.rstrip('\0')) # track number as string
if tag.track_total: tags['track_total'] = int(tag.track_total.rstrip('\0')) # total number of tracks as string
if tag.composer: tags['composer'] = tag.composer.rstrip('\0')
#try:
# image_data = tag.get_image()
#except IOError:
# pass
#if image_data:
# tags['image'] = image_data
#if tag.year # year or data as string
have_audio = duration > 0
seekable = True
else: # not supported
duration = 0
have_audio = 0
seekable = False
finally:
pass
return _Result(uri, tags, duration, seekable, mime, have_audio)
else:
timeout = int(timeout or self._timeout_ms)
tags, duration, seekable, mime = None, None, None, None
pipeline, signals = _setup_pipeline(uri, self._proxy_config)

View File

@ -90,6 +90,7 @@ def convert_tags_to_track(tags):
album_kwargs = {}
track_kwargs = {}
try:
track_kwargs['composers'] = _artists(tags, Gst.TAG_COMPOSER)
track_kwargs['performers'] = _artists(tags, Gst.TAG_PERFORMER)
track_kwargs['artists'] = _artists(tags, Gst.TAG_ARTIST,
@ -134,8 +135,42 @@ def convert_tags_to_track(tags):
if album_kwargs.get('name'):
track_kwargs['album'] = Album(**album_kwargs)
return Track(**track_kwargs)
except:
if 'title' in tags: track_kwargs['name'] = tags['title']
if 'genre' in tags: track_kwargs['genre'] = tags['genre']
if 'track' in tags: track_kwargs['track_no'] = tags['track']
if 'bitrate' in tags: track_kwargs['bitrate'] = tags['bitrate']
if 'artist' in tags:
album_kwargs['artists'] = [Artist({'name': tags['artist']})]
if 'album' in tags: album_kwargs['name'] = tags['album']
# Clear out any empty values we found
if 'composer' in tags:
track_kwargs['composers'] = [Artist({'name': tags['composer']})]
if 'disc' in tags: track_kwargs['disc_no'] = tags['disc']
if 'disc_total' in tags: album_kwargs['num_discs'] = tags['disc_total']
if 'track_total' in tags: album_kwargs['num_tracks'] = tags['track_total']
#if 'image' in tags: track_kwargs['image'] = tags['image']
track_kwargs = {k: v for k, v in track_kwargs.items() if v}
album_kwargs = {k: v for k, v in album_kwargs.items() if v}
# Only bother with album if we have a name to show.
if album_kwargs.get('name'):
track_kwargs['album'] = Album(**album_kwargs)
#if 'album' in tags:
# track_kwargs['album'] = Album(name=tags['album'])
if 'artist' in tags:
track_kwargs['artists'] = [Artist(name=tags['artist'])]
#for i in track_kwargs:
# if not i == 'image' : print(i, track_kwargs[i])
finally:
return Track(**track_kwargs)
def _artists(tags, artist_name, artist_id=None, artist_sortname=None):
# Name missing, don't set artist

1091
mopidy/audio/tinytag.py Normal file

File diff suppressed because it is too large Load Diff