Skip to content

Instantly share code, notes, and snippets.

@cnicodeme
Created December 30, 2022 09:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cnicodeme/e02aed7a9fe635063b389c3b52ee1c7c to your computer and use it in GitHub Desktop.
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.
# -*- 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