From ae29ff8f8710e22e58f5611d18ae4742ec3a2006 Mon Sep 17 00:00:00 2001 From: Ritiek Date: Sat, 24 Jun 2017 21:49:19 +0530 Subject: [PATCH] Split conversion code --- core/convert.py | 75 ++++++++++++++++++++++++++++++++++++++++ core/misc.py | 8 +++++ spotdl.py | 91 ++++++++----------------------------------------- 3 files changed, 97 insertions(+), 77 deletions(-) create mode 100644 core/convert.py diff --git a/core/convert.py b/core/convert.py new file mode 100644 index 0000000..d8fc717 --- /dev/null +++ b/core/convert.py @@ -0,0 +1,75 @@ +import subprocess +import os + +def song(input_song, output_song, avconv, verbose): + if not input_song == output_song: + input_song = input_song.encode('utf-8') + output_song = output_song.encode('utf-8') + print('Converting ' + input_song + ' to ' + output_song.split('.')[-1]) + if avconv: + convert_with_avconv(input_song, output_song, verbose) + else: + convert_with_FFmpeg(input_song, output_song, verbose) + os.remove('Music/' + input_song) + +def convert_with_avconv(input_song, output_song, verbose): + # different path for windows + if os.name == 'nt': + avconv_path = 'Scripts\\avconv.exe' + else: + avconv_path = 'avconv' + + if verbose: + level = 'debug' + else: + level = '0' + + command = [avconv_path, + '-loglevel', level, + '-i', 'Music/' + input_song, + '-ab', '192k', + 'Music/' + output_song] + + subprocess.call(command) + + +def convert_with_FFmpeg(input_song, output_song, verbose): + # What are the differences and similarities between ffmpeg, libav, and avconv? + # https://stackoverflow.com/questions/9477115 + # ffmeg encoders high to lower quality + # libopus > libvorbis >= libfdk_aac > aac > libmp3lame + # libfdk_aac due to copyrights needs to be compiled by end user + # on MacOS brew install ffmpeg --with-fdk-aac will do just that. Other OS? + # https://trac.ffmpeg.org/wiki/Encode/AAC + + if os.name == "nt": + ffmpeg_pre = 'Scripts\\ffmpeg.exe ' + else: + ffmpeg_pre = 'ffmpeg ' + + ffmpeg_pre += '-y ' + if not verbose: + ffmpeg_pre += '-hide_banner -nostats -v panic ' + + input_ext = input_song.split('.')[-1] + output_ext = output_song.split('.')[-1] + + if input_ext == 'm4a': + if output_ext == 'mp3': + ffmpeg_params = '-codec:v copy -codec:a libmp3lame -q:a 2 ' + elif output_ext == 'webm': + ffmpeg_params = '-c:a libopus -vbr on -b:a 192k -vn ' + + elif input_ext == 'webm': + if output_ext == 'mp3': + ffmpeg_params = ' -ab 192k -ar 44100 -vn ' + elif output_ext == 'm4a': + ffmpeg_params = '-cutoff 20000 -c:a libfdk_aac -b:a 192k -vn ' + + command = (ffmpeg_pre + + '-i Music/' + input_song + ' ' + + ffmpeg_params + + 'Music/' + output_song + '').split(' ') + + subprocess.call(command) + diff --git a/core/misc.py b/core/misc.py index e9b5e86..bc84beb 100755 --- a/core/misc.py +++ b/core/misc.py @@ -117,6 +117,14 @@ def fix_decoding(query): query = query.decode('utf-8') return query +def filter_path(path): + os.chdir(sys.path[0]) + if not os.path.exists(path): + os.makedirs(path) + for temp in os.listdir(path): + if temp.endswith('.temp'): + os.remove(path + '/' + temp) + def grace_quit(): print('') print('') diff --git a/spotdl.py b/spotdl.py index 2b1727c..44fc5d2 100755 --- a/spotdl.py +++ b/spotdl.py @@ -3,6 +3,7 @@ # -*- coding: UTF-8 -*- from core import metadata +from core import convert from core import misc from bs4 import BeautifulSoup from titlecase import titlecase @@ -11,7 +12,6 @@ import spotipy import pafy import sys import os -import subprocess # urllib2 is urllib.request in python3 try: @@ -33,8 +33,10 @@ def generate_metadata(raw_song): meta_tags = spotify.track(raw_song) else: # otherwise search on spotify and fetch information from first result - meta_tags = spotify.search(raw_song, limit=1)['tracks']['items'][0] - + try: + meta_tags = spotify.search(raw_song, limit=1)['tracks']['items'][0] + except: + return None artist = spotify.artist(meta_tags['artists'][0]['id']) album = spotify.album(meta_tags['album']['id']) @@ -157,75 +159,6 @@ def download_song(content): link.download(filepath='Music/' + music_file + args.input_ext) return True -# convert song from input_ext to output_ext -def convert_song(music_file): - # skip conversion if input_ext == output_ext - if not args.input_ext == args.output_ext: - music_file = music_file.encode('utf-8') - print('Converting ' + music_file + args.input_ext + ' to ' + args.output_ext[1:]) - if args.avconv: - convert_with_avconv(music_file) - else: - convert_with_FFmpeg(music_file) - os.remove('Music/' + music_file + args.input_ext) - -def convert_with_avconv(music_file): - # different path for windows - if os.name == 'nt': - avconv_path = 'Scripts\\avconv.exe' - else: - avconv_path = 'avconv' - - if args.verbose: - level = 'debug' - else: - level = '0' - - command = [avconv_path, - '-loglevel', level, - '-i', 'Music/' + music_file + args.input_ext, - '-ab', '192k', - 'Music/' + music_file + args.output_ext] - - subprocess.call(command) - - -def convert_with_FFmpeg(music_file): - # What are the differences and similarities between ffmpeg, libav, and avconv? - # https://stackoverflow.com/questions/9477115 - # ffmeg encoders high to lower quality - # libopus > libvorbis >= libfdk_aac > aac > libmp3lame - # libfdk_aac due to copyrights needs to be compiled by end user - # on MacOS brew install ffmpeg --with-fdk-aac will do just that. Other OS? - # https://trac.ffmpeg.org/wiki/Encode/AAC - - if os.name == "nt": - ffmpeg_pre = 'Scripts\\ffmpeg.exe ' - else: - ffmpeg_pre = 'ffmpeg ' - - ffmpeg_pre += '-y ' - if not args.verbose: - ffmpeg_pre += '-hide_banner -nostats -v panic ' - - if args.input_ext == '.m4a': - if args.output_ext == '.mp3': - ffmpeg_params = '-codec:v copy -codec:a libmp3lame -q:a 2 ' - elif output_ext == '.webm': - ffmpeg_params = '-c:a libopus -vbr on -b:a 192k -vn ' - elif args.input_ext == '.webm': - if args.output_ext == '.mp3': - ffmpeg_params = ' -ab 192k -ar 44100 -vn ' - elif args.output_ext == '.m4a': - ffmpeg_params = '-cutoff 20000 -c:a libfdk_aac -b:a 192k -vn ' - - command = (ffmpeg_pre + - '-i Music/' + music_file + args.input_ext + ' ' + - ffmpeg_params + - 'Music/' + music_file + args.output_ext + '').split(' ') - - subprocess.call(command) - # check if input song already exists in Music folder def check_exists(music_file, raw_song, islist): files = os.listdir("Music") @@ -314,19 +247,23 @@ def grab_single(raw_song, number=None): if not check_exists(music_file, raw_song, islist=islist): if download_song(content): print('') - convert_song(music_file) + input_song = music_file + args.input_ext + output_song = music_file + args.output_ext + convert.song(input_song, + output_song, + avconv=args.avconv, + verbose=args.verbose) meta_tags = generate_metadata(raw_song) if not args.no_metadata: - output = music_file + args.output_ext - metadata.embed(output, meta_tags) + metadata.embed(output_song, meta_tags) else: print('No audio streams available') if __name__ == '__main__': os.chdir(sys.path[0]) - if not os.path.exists("Music"): - os.makedirs("Music") + + misc.filter_path('Music') # token is mandatory when using Spotify's API # https://developer.spotify.com/news-stories/2017/01/27/removing-unauthenticated-calls-to-the-web-api/