112 lines
4.4 KiB
Python
112 lines
4.4 KiB
Python
'''Adds metadata to the chapterized mp3s'''
|
|
|
|
import os
|
|
import shutil
|
|
import json
|
|
import re
|
|
from mutagen.id3 import ID3, APIC, TIT2, TPE1, TCOM, TCON, TRCK, TALB
|
|
from config import circulation,bookshelf
|
|
|
|
def process_directories(directory):
|
|
'''Iterate through all subfolders & create cleaned_metadata.json'''
|
|
for root, dirs, files in os.walk(directory):
|
|
for dir in dirs:
|
|
subfolder_path = os.path.join(root, dir)
|
|
metadata_file = os.path.join(subfolder_path, "cleaned_metadata.json")
|
|
if os.path.exists(metadata_file):
|
|
metadata = read_metadata(metadata_file)
|
|
if metadata is None:
|
|
print("Skipping due to json error")
|
|
continue
|
|
add_metadata_to_files(subfolder_path, metadata)
|
|
|
|
def read_metadata(metadata_file):
|
|
'''Read and return json data from the given metadata file'''
|
|
try:
|
|
with open(metadata_file, "r") as f:
|
|
return json.load(f)
|
|
except (FileNotFoundError, json.JSONDecodeError) as e:
|
|
print(f"Error reading metadata file {metadata_file}: {e}")
|
|
return None
|
|
|
|
def get_album_title(metadata):
|
|
'''Extract the Book Title from metadata and clean it'''
|
|
album_title = metadata.get("Title", "")
|
|
return re.sub(r"-s\b", "'s", album_title)
|
|
|
|
def get_artist(metadata):
|
|
'''Extract the Author from metadata'''
|
|
return metadata.get("Author", "")
|
|
|
|
def get_composer(metadata):
|
|
'''Extract the Narrator from metadata'''
|
|
return metadata.get("Narrator", "")
|
|
|
|
def get_genre(metadata):
|
|
'''Extract the Subjects from metadata'''
|
|
return metadata.get("Subjects", "")
|
|
|
|
def add_metadata_to_files(directory, metadata):
|
|
'''Add metadata to all chapterized mp3s in the directory'''
|
|
if not metadata:
|
|
print(f"No metadata available for directory {directory}. Skipping.")
|
|
return
|
|
album_title = get_album_title(metadata)
|
|
artist = get_artist(metadata)
|
|
composer = get_composer(metadata)
|
|
genre = get_genre(metadata)
|
|
|
|
'''Get a list of all mp3 files in the current directory'''
|
|
mp3_files = [f for f in os.listdir(directory) if f.endswith(".mp3")]
|
|
|
|
'''Sort the list of mp3 files alphabetically'''
|
|
mp3_files.sort()
|
|
|
|
'''Iterate through the list of mp3 files'''
|
|
for i, mp3_file in enumerate(mp3_files, 1):
|
|
mp3_file_path = os.path.join(directory, mp3_file)
|
|
|
|
'''Extract the title of the mp3 file'''
|
|
file_name, _ = os.path.splitext(mp3_file)
|
|
title = re.sub(r"^\d+_", "", file_name) # Correctly extracts the title from the filename
|
|
|
|
'''Add the track number & other metadata to the file using ID3'''
|
|
try:
|
|
# Add the track number & other metadata to the file using ID3
|
|
audio = ID3(mp3_file_path)
|
|
audio.add(TRCK(encoding=3, text=str(i)))
|
|
audio.add(TIT2(encoding=3, text=title))
|
|
audio.add(TPE1(encoding=3, text=artist))
|
|
audio.add(TCOM(encoding=3, text=composer))
|
|
audio.add(TCON(encoding=3, text=genre))
|
|
audio.add(TALB(encoding=3, text=album_title))
|
|
'''Check if folder.jpg exists in the current directory'''
|
|
if os.path.exists(os.path.join(directory, "folder.jpg")):
|
|
'''Add the album art to the file using ID3'''
|
|
with open(os.path.join(directory, "folder.jpg"), "rb") as albumart:
|
|
audio = ID3(mp3_file_path)
|
|
audio.add(APIC(encoding=3, mime='image/jpeg', type=3, desc='Cover', data=albumart.read()))
|
|
audio.save()
|
|
except Exception as e:
|
|
print(f"Failed to add metadata to {mp3_file_path}: {e}")
|
|
|
|
def meta_to_mp3(directory):
|
|
for root, dirs, files in os.walk(directory):
|
|
'''Traverse the directory and apply the metadata to the mp3 files'''
|
|
for dir in dirs:
|
|
subfolder_path = os.path.join(root, dir)
|
|
parent_folder = os.path.dirname(subfolder_path)
|
|
if parent_folder == directory:
|
|
try:
|
|
shutil.move(subfolder_path, bookshelf)
|
|
except OSError as e:
|
|
print(f"Error moving directory {subfolder_path} to {bookshelf}: {e}")
|
|
|
|
def traverse_directory(directory):
|
|
process_directories(directory)
|
|
meta_to_mp3(directory)
|
|
|
|
'''Point the script at your Circulation folder'''
|
|
directory = circulation
|
|
|
|
traverse_directory(directory) |