mirror of
https://github.com/KevinMidboe/spotify-downloader.git
synced 2026-02-10 19:39:25 +00:00
Support FLAC output format (#259)
* Convert to .flac option * Embed metadata to FLAC * Update usage help * Write tests
This commit is contained in:
@@ -1,8 +1,33 @@
|
||||
import logzero
|
||||
|
||||
_log_format = ("%(color)s%(levelname)s:%(end_color)s %(message)s")
|
||||
formatter = logzero.LogFormatter(fmt=_log_format)
|
||||
_formatter = logzero.LogFormatter(fmt=_log_format)
|
||||
|
||||
# options
|
||||
log = logzero.setup_logger(formatter=formatter)
|
||||
log = logzero.setup_logger(formatter=_formatter)
|
||||
args = None
|
||||
|
||||
# Apple has specific tags - see mutagen docs -
|
||||
# http://mutagen.readthedocs.io/en/latest/api/mp4.html
|
||||
M4A_TAG_PRESET = { 'album' : '\xa9alb',
|
||||
'artist' : '\xa9ART',
|
||||
'date' : '\xa9day',
|
||||
'title' : '\xa9nam',
|
||||
'year' : '\xa9day',
|
||||
'originaldate' : 'purd',
|
||||
'comment' : '\xa9cmt',
|
||||
'group' : '\xa9grp',
|
||||
'writer' : '\xa9wrt',
|
||||
'genre' : '\xa9gen',
|
||||
'tracknumber' : 'trkn',
|
||||
'albumartist' : 'aART',
|
||||
'discnumber' : 'disk',
|
||||
'cpil' : 'cpil',
|
||||
'albumart' : 'covr',
|
||||
'copyright' : 'cprt',
|
||||
'tempo' : 'tmpo',
|
||||
'lyrics' : '\xa9lyr' }
|
||||
|
||||
TAG_PRESET = {}
|
||||
for key in M4A_TAG_PRESET.keys():
|
||||
TAG_PRESET[key] = key
|
||||
|
||||
@@ -17,16 +17,16 @@ https://trac.ffmpeg.org/wiki/Encode/AAC
|
||||
|
||||
def song(input_song, output_song, folder, avconv=False):
|
||||
""" Do the audio format conversion. """
|
||||
if not input_song == output_song:
|
||||
convert = Converter(input_song, output_song, folder)
|
||||
log.info('Converting {0} to {1}'.format(
|
||||
input_song, output_song.split('.')[-1]))
|
||||
if avconv:
|
||||
exit_code = convert.with_avconv()
|
||||
else:
|
||||
exit_code = convert.with_ffmpeg()
|
||||
return exit_code
|
||||
return 0
|
||||
if input_song == output_song:
|
||||
return 0
|
||||
convert = Converter(input_song, output_song, folder)
|
||||
log.info('Converting {0} to {1}'.format(
|
||||
input_song, output_song.split('.')[-1]))
|
||||
if avconv:
|
||||
exit_code = convert.with_avconv()
|
||||
else:
|
||||
exit_code = convert.with_ffmpeg()
|
||||
return exit_code
|
||||
|
||||
|
||||
class Converter:
|
||||
@@ -56,6 +56,8 @@ class Converter:
|
||||
_, input_ext = os.path.splitext(self.input_file)
|
||||
_, output_ext = os.path.splitext(self.output_file)
|
||||
|
||||
ffmpeg_params = ''
|
||||
|
||||
if input_ext == '.m4a':
|
||||
if output_ext == '.mp3':
|
||||
ffmpeg_params = '-codec:v copy -codec:a libmp3lame -ar 44100 '
|
||||
@@ -68,6 +70,9 @@ class Converter:
|
||||
elif output_ext == '.m4a':
|
||||
ffmpeg_params = '-cutoff 20000 -codec:a libfdk_aac -ar 44100 '
|
||||
|
||||
if output_ext == '.flac':
|
||||
ffmpeg_params = '-codec:a flac -ar 44100 '
|
||||
|
||||
# add common params for any of the above combination
|
||||
ffmpeg_params += '-b:a 192k -vn '
|
||||
ffmpeg_pre += ' -i'
|
||||
|
||||
@@ -122,10 +122,11 @@ def get_arguments(raw_args=None, to_group=True, to_merge=True):
|
||||
choices={'prompt', 'force', 'skip'})
|
||||
parser.add_argument(
|
||||
'-i', '--input-ext', default=config['input-ext'],
|
||||
help='prefered input format .m4a or .webm (Opus)')
|
||||
help='prefered input format .m4a or .webm (Opus)',
|
||||
choices={'.m4a', '.webm'})
|
||||
parser.add_argument(
|
||||
'-o', '--output-ext', default=config['output-ext'],
|
||||
help='prefered output extension .mp3 or .m4a (AAC)')
|
||||
help='prefered output format .mp3, .m4a (AAC), .flac, etc.')
|
||||
parser.add_argument(
|
||||
'-ff', '--file-format', default=config['file-format'],
|
||||
help='File format to save the downloaded song with, each tag '
|
||||
|
||||
107
core/metadata.py
107
core/metadata.py
@@ -1,7 +1,8 @@
|
||||
from mutagen.easyid3 import EasyID3
|
||||
from mutagen.id3 import ID3, TORY, TYER, TPUB, APIC, USLT, COMM
|
||||
from mutagen.mp4 import MP4, MP4Cover
|
||||
from core.const import log
|
||||
from mutagen.flac import Picture, FLAC
|
||||
from core.const import log, TAG_PRESET, M4A_TAG_PRESET
|
||||
|
||||
import urllib.request
|
||||
|
||||
@@ -31,6 +32,9 @@ def embed(music_file, meta_tags):
|
||||
elif music_file.endswith('.mp3'):
|
||||
log.info('Applying metadata')
|
||||
return embed.as_mp3()
|
||||
elif music_file.endswith('.flac'):
|
||||
log.info('Applying metadata')
|
||||
return embed.as_flac()
|
||||
else:
|
||||
log.warning('Cannot embed metadata into given output extension')
|
||||
return False
|
||||
@@ -50,15 +54,7 @@ class EmbedMetadata:
|
||||
# https://github.com/quodlibet/mutagen/blob/master/mutagen/easyid3.py
|
||||
# Check out somewhere at end of above linked file
|
||||
audiofile = EasyID3(music_file)
|
||||
audiofile['artist'] = meta_tags['artists'][0]['name']
|
||||
audiofile['albumartist'] = meta_tags['artists'][0]['name']
|
||||
audiofile['album'] = meta_tags['album']['name']
|
||||
audiofile['title'] = meta_tags['name']
|
||||
audiofile['tracknumber'] = [meta_tags['track_number'],
|
||||
meta_tags['total_tracks']]
|
||||
audiofile['discnumber'] = [meta_tags['disc_number'], 0]
|
||||
audiofile['date'] = meta_tags['release_date']
|
||||
audiofile['originaldate'] = meta_tags['release_date']
|
||||
self._embed_basic_metadata(audiofile, preset=TAG_PRESET)
|
||||
audiofile['media'] = meta_tags['type']
|
||||
audiofile['author'] = meta_tags['artists'][0]['name']
|
||||
audiofile['lyricist'] = meta_tags['artists'][0]['name']
|
||||
@@ -68,10 +64,6 @@ class EmbedMetadata:
|
||||
audiofile['length'] = str(meta_tags['duration'])
|
||||
if meta_tags['publisher']:
|
||||
audiofile['encodedby'] = meta_tags['publisher']
|
||||
if meta_tags['genre']:
|
||||
audiofile['genre'] = meta_tags['genre']
|
||||
if meta_tags['copyright']:
|
||||
audiofile['copyright'] = meta_tags['copyright']
|
||||
if meta_tags['external_ids']['isrc']:
|
||||
audiofile['isrc'] = meta_tags['external_ids']['isrc']
|
||||
audiofile.save(v2_version=3)
|
||||
@@ -101,48 +93,13 @@ class EmbedMetadata:
|
||||
""" Embed metadata to M4A files. """
|
||||
music_file = self.music_file
|
||||
meta_tags = self.meta_tags
|
||||
# Apple has specific tags - see mutagen docs -
|
||||
# http://mutagen.readthedocs.io/en/latest/api/mp4.html
|
||||
tags = { 'album' : '\xa9alb',
|
||||
'artist' : '\xa9ART',
|
||||
'date' : '\xa9day',
|
||||
'title' : '\xa9nam',
|
||||
'year' : '\xa9day',
|
||||
'originaldate' : 'purd',
|
||||
'comment' : '\xa9cmt',
|
||||
'group' : '\xa9grp',
|
||||
'writer' : '\xa9wrt',
|
||||
'genre' : '\xa9gen',
|
||||
'tracknumber' : 'trkn',
|
||||
'albumartist' : 'aART',
|
||||
'disknumber' : 'disk',
|
||||
'cpil' : 'cpil',
|
||||
'albumart' : 'covr',
|
||||
'copyright' : 'cprt',
|
||||
'tempo' : 'tmpo',
|
||||
'lyrics' : '\xa9lyr' }
|
||||
|
||||
audiofile = MP4(music_file)
|
||||
audiofile[tags['artist']] = meta_tags['artists'][0]['name']
|
||||
audiofile[tags['albumartist']] = meta_tags['artists'][0]['name']
|
||||
audiofile[tags['album']] = meta_tags['album']['name']
|
||||
audiofile[tags['title']] = meta_tags['name']
|
||||
audiofile[tags['tracknumber']] = [(meta_tags['track_number'],
|
||||
meta_tags['total_tracks'])]
|
||||
audiofile[tags['disknumber']] = [(meta_tags['disc_number'], 0)]
|
||||
audiofile[tags['date']] = meta_tags['release_date']
|
||||
audiofile[tags['year']] = meta_tags['year']
|
||||
audiofile[tags['originaldate']] = meta_tags['release_date']
|
||||
audiofile[tags['comment']] = meta_tags['external_urls']['spotify']
|
||||
if meta_tags['genre']:
|
||||
audiofile[tags['genre']] = meta_tags['genre']
|
||||
if meta_tags['copyright']:
|
||||
audiofile[tags['copyright']] = meta_tags['copyright']
|
||||
if meta_tags['lyrics']:
|
||||
audiofile[tags['lyrics']] = meta_tags['lyrics']
|
||||
self._embed_basic_metadata(audiofile, preset=M4A_TAG_PRESET)
|
||||
audiofile[M4A_TAG_PRESET['year']] = meta_tags['year']
|
||||
audiofile[M4A_TAG_PRESET['comment']] = meta_tags['external_urls']['spotify']
|
||||
try:
|
||||
albumart = urllib.request.urlopen(meta_tags['album']['images'][0]['url'])
|
||||
audiofile[tags['albumart']] = [MP4Cover(
|
||||
audiofile[M4A_TAG_PRESET['albumart']] = [MP4Cover(
|
||||
albumart.read(), imageformat=MP4Cover.FORMAT_JPEG)]
|
||||
albumart.close()
|
||||
except IndexError:
|
||||
@@ -150,3 +107,47 @@ class EmbedMetadata:
|
||||
|
||||
audiofile.save()
|
||||
return True
|
||||
|
||||
def as_flac(self):
|
||||
music_file = self.music_file
|
||||
meta_tags = self.meta_tags
|
||||
audiofile = FLAC(music_file)
|
||||
self._embed_basic_metadata(audiofile)
|
||||
audiofile['year'] = meta_tags['year']
|
||||
audiofile['comment'] = meta_tags['external_urls']['spotify']
|
||||
|
||||
image = Picture()
|
||||
image.type = 3
|
||||
image.desc = 'Cover'
|
||||
image.mime = 'image/jpeg'
|
||||
albumart = urllib.request.urlopen(meta_tags['album']['images'][0]['url'])
|
||||
image.data = albumart.read()
|
||||
albumart.close()
|
||||
audiofile.add_picture(image)
|
||||
|
||||
audiofile.save()
|
||||
return True
|
||||
|
||||
def _embed_basic_metadata(self, audiofile, preset=TAG_PRESET):
|
||||
meta_tags = self.meta_tags
|
||||
audiofile[preset['artist']] = meta_tags['artists'][0]['name']
|
||||
audiofile[preset['albumartist']] = meta_tags['artists'][0]['name']
|
||||
audiofile[preset['album']] = meta_tags['album']['name']
|
||||
audiofile[preset['title']] = meta_tags['name']
|
||||
audiofile[preset['date']] = meta_tags['release_date']
|
||||
audiofile[preset['originaldate']] = meta_tags['release_date']
|
||||
if meta_tags['genre']:
|
||||
audiofile[preset['genre']] = meta_tags['genre']
|
||||
if meta_tags['copyright']:
|
||||
audiofile[preset['copyright']] = meta_tags['copyright']
|
||||
if meta_tags['lyrics']:
|
||||
audiofile[preset['lyrics']] = meta_tags['lyrics']
|
||||
if self.music_file.endswith('.flac'):
|
||||
audiofile[preset['discnumber']] = str(meta_tags['disc_number'])
|
||||
else:
|
||||
audiofile[preset['discnumber']] = [(meta_tags['disc_number'], 0)]
|
||||
if self.music_file.endswith('.flac'):
|
||||
audiofile[preset['tracknumber']] = str(meta_tags['track_number'])
|
||||
else:
|
||||
audiofile[preset['tracknumber']] = [(meta_tags['track_number'],
|
||||
meta_tags['total_tracks'])]
|
||||
|
||||
Reference in New Issue
Block a user