Libraree

toolbox of Python scripts for music/video/photo library management

26 Jul 2022

Music

Using the following libraries:

  • tinytag !python/library-tinytag
  • mutagen !python/library-mutagen

Count

count_file = 0
count_flac = 0
count_m4a = 0
count_name_updated = 0
count_to_be_deleted = 0
count_folders_with_files = 0

blacklist = [
    'recycle',
    '.fseventsd',
    '.Spotlight-V100',
    'Trashes',
    'Covers',
]

suffixes = (        #needs to be a tuple
            '.flac', 
            '.m4a',
            '.jpg',
            '.png',
            '.bmp',
            '.txt',
            '.zip',
            ) 

valid_music = (        #needs to be a tuple
            '.flac', 
            '.m4a',
            ) 

## DELETE FILES

undesired = (        #needs to be a tuple
'.m3u', 
'.nfo',
'.sfv',
'.log',
'.cue',
'.txt',
'.md5',
'.pls',
) 

for root, dirs, files in os.walk("/path/to/folder/Music"):

    # if not any(ele in root for ele in blacklist):
    if any(ele in root for ele in valid_music):

        for name in files:
            count_file += 1

print(f"{count_file=}")

Bulk rename based on tags

from mutagen.flac import FLAC
from tinytag import TinyTag

test = False
v = False # verbose, for debugging

count_folders = 0
count_file = 0
count_flac = 0
count_m4a = 0
count_name_updated = 0
count_to_be_deleted = 0
count_folders_with_files = 0
count_renamed = 0

blacklist = [
    'recycle',
    '.fseventsd',
    '.Spotlight-V100',
    'Trashes',
    'Covers',
]


suffixes = (        #needs to be a tuple
            '.flac', 
            '.m4a',
            '.jpg',
            '.png',
            '.bmp',
            '.txt',
            '.zip',
            ) 

valid_music = (        #needs to be a tuple
            '.flac', 
            '.m4a',
            ) 

print()

error_folders = []

for x in os.walk("/path/to/folder/Music/"):

    if v:
        print()
        print('>>>>>>')
        print('X:')
        pp.pprint(x)


    root = x[0]
    folders = x[1]
    files = x[2]


    if not len(files) == 0:

        if files[0].endswith('.m4a') or files[0].endswith('.flac'):
            print()
            count_folders += 1

            print('root: \t\t ', root)
            sample_file = f"{root}/{files[0]}"
            if v:
                print('sample_file: ', sample_file)

            audio = TinyTag.get(sample_file)
            if v:
                print('audio: ', type(audio), audio)
            year = audio.year

            if year != None:
                if len(year) > 4:
                    year = year[:4]
            album = audio.album
            samplerate = audio.samplerate
            bitrate = audio.bitrate

            if v:
                print('bitrate: type ', type(bitrate), bitrate)
                print('samplerate: type ', type(samplerate), samplerate)

            hd = False
            if bitrate != None:
                if bitrate > 1500:
                    hd = True

            if files[0].endswith('.m4a'):
                if hd:
                    new_folder_name = f"{os.path.dirname(root)}/{year} {album} (M4A HD)"
                else:
                    new_folder_name = f"{os.path.dirname(root)}/{year} {album} (M4A)"
            if files[0].endswith('.flac'):
                if hd:
                    new_folder_name = f"{os.path.dirname(root)}/{year} {album} (FLAC HD)"
                else:
                    new_folder_name = f"{os.path.dirname(root)}/{year} {album} (FLAC)"
            print('new_folder_name: ', new_folder_name)

            if not test and 'QB' not in root: # carving out albums bought on Qobuz
                try:
                    os.rename(root, new_folder_name)
                    count_renamed += 1
                except Exception as e:
                    print(f"ERROR {e} WITH {root}")
                    error_folders.append((root, e))

    if v:
        print('<<<<<<<')


if len(error_folders) > 0:
    print(f"\n\nERRORS:")
    count_errors = 0
    for x in error_folders:
        count_errors += 1
        print(count_errors, '\t', x[0], '\t', x[1])

if __name__ == '__main__':
    print()
    print()
    print('-------------------------------')
    print(f"{os.path.basename(__file__)}")
    print()
    print(f"count_folders = {count_folders}")
    print(f"count_file = {count_file}")
    print(f"count_renamed = {count_renamed}")
    print(f"count = {count}")
    print(f"count_folders_with_files = {count_folders_with_files}")
    print(f"count_flac = {count_flac}")
    print(f"count_m4a = {count_m4a}")
    print(f"count_name_updated = {count_name_updated}")
    print(f"count_to_be_deleted = {count_to_be_deleted}")
    print()
    print('-------------------------------')
    run_time = round((time.time() - start_time)/60, 1)
    print()
    print(f"{os.path.basename(__file__)} finished in {run_time} minutes at {datetime.now().strftime('%H:%M:%S')}.")
    print()

Buld delete unwanted files in folders

13 Sep 2022 updated with Send2Trash instead of os.remove() (safer).

####################
# Music Library

from mutagen.flac import FLAC
from tinytag import TinyTag

from send2trash import send2trash # instead of os.remove(), safer.  

#####

test = True

#####

count_file = 0
# count_flac = 0
# count_m4a = 0
# count_name_updated = 0
count_to_be_deleted = 0
# count_folders_with_files = 0

blacklist = [
    'recycle',
    '.fseventsd',
    '.Spotlight-V100',
    'Trashes',
    'Covers',
]

suffixes = (        #needs to be a tuple
            '.flac', 
            '.m4a',
            '.jpg',
            '.png',
            '.bmp',
            '.txt',
            '.zip',
            ) 

valid_music = (        #needs to be a tuple
            '.flac', 
            '.m4a',
            ) 

## DELETE FILES

undesired = (        #needs to be a tuple
'.m3u', 
'.nfo',
'.sfv',
'.log',
'.cue',
'.CUE',
'.txt',
'.md5',
'.pls',
) 

for root, dirs, files in os.walk("/Volumes/Mus1c"):

    if not any(ele in root for ele in blacklist):

        for name in files:
            count_file += 1

            if any(ele in name for ele in undesired) and 'Doors' not in root and 'Tesla' not in name:

                count_to_be_deleted += 1

                path = f"{root}/{name}"

                if not test:
                    # os.remove(path) # replaced with send2trash
                    send2trash(path)
                    print('DELETED path: ', path)
                else:
                    print('TO BE DELETED path: ', path)

if test:
    print(f"\n\n>>>> RERUN live to delete.")

links

social