Created
December 30, 2022 09:06
-
-
Save cnicodeme/e02aed7a9fe635063b389c3b52ee1c7c to your computer and use it in GitHub Desktop.
Tags MP3 files to their appropriate ID3 tag based on their path and filename.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
import argparse, glob, os | |
try: | |
from mutagen.easyid3 import EasyID3 | |
except ImportError: | |
print('"mutagen" package is required for this to work.') | |
print('Please install it using pip or any other package manager') | |
exit(0) | |
def update_file(path, **kwargs): | |
audio = EasyID3(path) | |
filename = os.path.basename(path) | |
names = [x.strip() for x in filename.replace('.mp3', '').split('-')] | |
folders = path.split('/') | |
folders.pop() # We remove the filename | |
for key in ('title', 'artist', 'album', 'composer'): | |
if kwargs.get(key): | |
if kwargs.get(key).startswith('%'): | |
try: | |
index = int(kwargs.get(key)[1:]) | |
if index < 0: | |
audio[key] = folders[index] | |
else: | |
audio[key] = names[index] | |
continue | |
except (ValueError, IndexError): | |
print('value error') | |
continue | |
audio[key] = kwargs.get(key) | |
audio.save() | |
if __name__ == '__main__': | |
parser = argparse.ArgumentParser(description="""Updates ID3 tags of one or multiple .mp3 files. | |
You can pass arguments with variables in this format: %Xs where X is a number. | |
- If X is more than 0, the filename will be split in parts with dash ("-") being the separator. | |
In this case, the number X will match the part. | |
For instance, given a filename "12 - Enjoy the silence - 2004.mp3", passing the argument | |
"--title %1s" will set the title to "Enjoy the silence" | |
- If X is less than 0, the value will match the path in reverse order. | |
For instance, a given path of "/home/user/music/Linkin Park/Remixes 81-04/", passing the argument | |
"--album %-1s" will set the album name to "Remixes 81-04" | |
What's left to do: | |
* Implement the year parameter | |
* Allow for choosing what to split with (default is dash ("-") but we could set anything else) | |
* Handle subsplit; For instance, an Album path could contain both year and name ("2004 - Remixes 81-04"). | |
Passing an argument such as "%-1;1s" could be something, but it becomes ugly... | |
Accepted paramters: | |
* -p, --path : The path to either a folder or an mp3 file (checked via the last 4 chars being equals to ".mp3") | |
* --artist: Sets the artist's name | |
* --album: Sets the album's name | |
* --title: Sets the title's name | |
* -- composer: Sets the composer's name | |
(All the parameters except -p/--path are optional) | |
""") | |
parser.add_argument('-p', '--path', type=str, required=True) | |
parser.add_argument('--artist', type=str, default=None, required=False) | |
parser.add_argument('--album', type=str, default=None, required=False) | |
parser.add_argument('--title', type=str, default=None, required=False) | |
parser.add_argument('--composer', type=str, default=None, required=False) | |
args = parser.parse_args() | |
if args.path.endswith('.mp3'): | |
# Process one file only | |
if not os.path.exists(args.path): | |
print('ERR: Given path was not found.') | |
exit(1) | |
update_file(args.path, artist=args.artist, album=args.album, title=args.title, composer=args.composer) | |
else: | |
full_path = os.path.abspath(args.path) | |
if not os.path.isdir(full_path): | |
print('ERR: Given path does not exists.') | |
# exit(1) | |
if args.title: | |
try: | |
assert args.title.startswith('%') | |
except AssertionError: | |
print('ERR: Title must be a variable based on the name') | |
exit(1) | |
files = glob.glob('{0}/**/*.mp3'.format(full_path), recursive=True) | |
for fname in files: | |
print(fname) | |
update_file(fname, artist=args.artist, album=args.album, title=args.title, composer=args.composer) | |
print('Done.') | |
exit(0) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment