# python spotify grabber # requirements: pygetwindow from pip and fmedia in $path import pygetwindow import re import time import subprocess import threading import logging import string import unicodedata import sys # configuration logging.basicConfig( level=logging.DEBUG, format='%(asctime)s %(levelname)-8s %(message)s' ) rec_path=".\\rec\\" loopback_dev="3" monitor_interval=.2 # end configuration valid_filename_chars = "-_.() %s%s" % (string.ascii_letters, string.digits) counter=0 def clean_filename(filename, whitelist=valid_filename_chars): # keep only valid ascii chars cleaned_filename = unicodedata.normalize('NFKD', filename).encode('ASCII', 'ignore').decode() # keep only whitelisted chars cleaned_filename = ''.join(c for c in cleaned_filename if c in whitelist) return cleaned_filename def start_rec(artist, title): def rec_subprocess(): filename = '{rec_path}{nn:03d}. {artist} - {title}.mp3'.format( nn=counter, rec_path=rec_path, artist=clean_filename(artist), title=clean_filename(title) ) logging.debug('recording to {filename}'.format(filename=filename)) command = 'fmedia --record --dev-loopback={device} -o "{filename}" --mpeg-quality=2 --globcmd=listen'.format(device=loopback_dev, filename=filename) logging.debug('starting recording subprocess: {command}'.format(command=command)) subprocess.run(command, shell=True, capture_output=True, check=True) logging.debug('starting subprocess') global counter counter += 1 thread = threading.Thread(target=rec_subprocess) thread.start() def stop_rec(): subprocess.run('fmedia --globcmd=stop', shell=True) logging.debug('stopped recording') def parse_win_title(win_title): metadata = win_title.split('Spotify - ')[1].split(' ยท ') title = metadata[0] artist = metadata[1] logging.debug('got metadata {title} by {artist}'.format(title=title, artist=artist)) return title, artist def watch_window(): old_title = '' logging.debug('started window watcher') while True: win_titles = pygetwindow.getAllTitles() for win_title in win_titles: if re.search('^Spotify - .+', win_title): if win_title != old_title: logging.debug('window title changed to {wintitle}'.format(wintitle=win_title)) # read metadata from window title title, artist = parse_win_title(win_title) if old_title != '': logging.debug('stop recording') stop_rec() logging.debug('start recording now') start_rec(title, artist) old_title = win_title time.sleep(.5) input('press enter to arm') try: watch_window() except KeyboardInterrupt: logging.info('got CTRL+C - trying to clean up my mess') stop_rec() logging.info('Bye Bye') sys.exit(0)