0

My goal is to make a program that lets you edit audio metadata using tkinter, but I've gotten stuck. No matter what I try, the program will not edit the metadata. I am using a browse button so that you can choose any file. Here's my code:

import tkinter
from tkinter import filedialog
from tkinter.filedialog import askopenfilename
import eyed3

root = tkinter.Tk()
canvas = tkinter.Canvas(root, width=400, height=300)
audio_file = None


def browse_files():
    global audio_file
    audio_file_path = askopenfilename(filetypes=(("Audio Files", "*.mp3"),))
    audio_file = eyed3.load(audio_file_path)
    file_chosen_label = tkinter.Label(root, text=audio_file_path)
    file_chosen_label.pack()
    return audio_file


def change_artist():
    audio_file.tag.album_artist = artist_name.get()
    audio_file.tag.save()
    return


file_choose_label = tkinter.Label(root, text="Song file")
file_choose = tkinter.Button(root, text="Browse...", command=browse_files)
artist_label = tkinter.Label(root, text="Artist")
artist_name = tkinter.StringVar()
artist_entry = tkinter.Entry(root, textvariable=artist_name)
apply_button = tkinter.Button(root, command=change_artist, text="Apply")

file_choose_label.pack()
file_choose.pack()
artist_label.pack()
artist_entry.pack()
apply_button.pack()
canvas.pack()
root.mainloop()

What am I missing? No errors or anything.

SpikyLlama
  • 5
  • 1
  • 6
  • You don't call the `change_artist` function anywhere. Either call it explicitly, or bind it to some kind of callback, like a button callback. – Paul M. Apr 30 '21 at 18:25
  • oh like a "save" or "apply" button or something? i added it like this: ```apply_button = tkinter.Button(root, command=change_artist, text="Apply")```when i did that it returned this error: ```Exception in Tkinter callback Traceback (most recent call last): File "C:\Users\SpikyLlama\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py", line 1892, in __call__ return self.func(*args) File "C:\Users\SpikyLlama\PycharmProjects\audioinjector\venv\main.py", line 19, in change_artist audio_file.tag.album_artist = artist_name NameError: name 'audio_file' is not defined``` – SpikyLlama Apr 30 '21 at 18:27
  • Yes, that's right. The error indicates that `audio_file` does not exist. This is because you've defined that variable in the scope of another function. There are different ways of solving this, but right now the easiest would be to turn `audio_file` into a global variable. In the global scope, right under `canvas = ...`, insert `audio_file = None`. Then, in your `browse_files` function, add `global audio_file` before `audio_file_path = ...` – Paul M. Apr 30 '21 at 18:42
  • that fixed that issue, but now i have an error: "AttributeError: 'NoneType' object has no attribute 'album_artist'" why is that? – SpikyLlama Apr 30 '21 at 18:51
  • It seems you haven't shown all of your code. Could you edit your post and show all of your up-to-date code? – Paul M. Apr 30 '21 at 18:57
  • edited it so you can see all the code – SpikyLlama Apr 30 '21 at 18:59
  • Thanks for editing your post. Is it possible that you are trying to run an older version of your script? Because your error message specifically references `album_artist`, but your script doesn't contain any references to `album_artist`. – Paul M. Apr 30 '21 at 19:06
  • yeah i've been changing the different variables to test the code, genre, album_artist, artist, etc all throw the same error – SpikyLlama Apr 30 '21 at 19:10
  • And you're selecting an mp3 file first with the `Browse...` button, right? Before you press `Apply` I mean. – Paul M. Apr 30 '21 at 19:12
  • yeah, that's what i've been using the browse button for and i always do it first – SpikyLlama Apr 30 '21 at 19:14

1 Answers1

0

OK, a couple of things:

Change:

def change_artist():
    audio_file.tag.genre = artist_name
    audio_file.tag.save()
    return

To

def change_artist():
    audio_file.tag.album_artist = artist_name.get()
    audio_file.tag.save()
    return

Then, change:

artist_entry = tkinter.Entry(root, textvariable="artist_name")

To:

artist_entry = tkinter.Entry(root, textvariable=artist_name)

Let me know how it goes.


EDIT, I would like to try something. Please change your change_artist function to:

def change_artist():
    try:
        audio_file.tag.album_artist = artist_name.get()
        audio_file.tag.save()
    except AttributeError as error:
        print(type(audio_file), audio_file)
        print(type(audio_file.tag))
        raise error
    

Let me know what get's printed.


EDIT, One more time, try this:

def change_artist():
    audio_file.initTag().album_artist = artist_name.get()
    audio_file.tag.save()
Paul M.
  • 10,481
  • 2
  • 9
  • 15
  • I get this error instead: TypeError: can only concatenate str (not "NoneType") to str – SpikyLlama Apr 30 '21 at 20:10
  • @SpikyLlama Which line specifically is raising that exception? – Paul M. May 01 '21 at 13:17
  • it says line 21 – SpikyLlama May 01 '21 at 17:20
  • @SpikyLlama I don't see any concatenation taking place on that line. Please edit your original code and show your most up-to-date, current code. Please also copy-and-paste the full error traceback, which includes the stacktrace, line number, etc. – Paul M. May 01 '21 at 17:39
  • `Exception in Tkinter callback Traceback (most recent call last): File "C:\Users\SpikyLlama\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py", line 1892, in __call__ return self.func(*args) File "C:\Users\SpikyLlama\PycharmProjects\audioinjector\venv\main.py", line 21, in change_artist audio_file.tag.album_artist = artist_name.get() AttributeError: 'NoneType' object has no attribute 'album_artist'` – SpikyLlama May 01 '21 at 18:06
  • @SpikyLlama Thanks for editing your code and providing the full traceback. I've tested your exact code on my machine, and I get no such error, and I'm able to edit the metadata of mp3 files. What version of `eyeD3` are you using? Confirm that you're using the most recent version (I'm using `0.9.6`). – Paul M. May 01 '21 at 18:11
  • I am also using 0.9.6 – SpikyLlama May 01 '21 at 18:21
  • okay so that concatenation error was on a test version of my code :facepalm: so ignore that – SpikyLlama May 01 '21 at 18:29
  • @SpikyLlama No worries. I'd like to try a little experiment - I've edited my post, can you replace your `change_artist` function with the one I pasted at the bottom of my post? Then run your program, and let me know what gets printed. – Paul M. May 01 '21 at 18:33
  • this, along with the previous error – SpikyLlama May 01 '21 at 18:36
  • @SpikyLlama OK, thanks. I looked at eyeD3's source code, and my hunch is that the mp3 file you are trying to edit has some kind of unsupported ID3 tag header version, and so `audio_file.tag` gets initialized to `None`. I've added another new version of `change_artist` at the very bottom of my post. Try changing it to that, and see if you program works now. – Paul M. May 01 '21 at 18:53
  • unsurprisingly, i have run into another issue. when i add two functions, like change_artist and change_title, i can't get both tags to update. i've tried tons of methods, such as combining them into one, making a list and others. i don't know what to do now. it just adds one – SpikyLlama May 01 '21 at 23:26
  • a-ha! turns out that deleting that initTag stuff and going back to audio_file.tag.album_artist fixes that! not sure why, but now it should work prefectly adding multiple tags! – SpikyLlama May 02 '21 at 00:01
  • @SpikyLlama Ah yes, that makes sense actually. Initially, your mp3 had an unsupported ID3 tag header. Adding the `initTag` stuff rewrote the header for that mp3 file with a supported ID3 tad header version, but it also has the side-effect of clearing all fields (such as artist, genre, etc.). Switching back to the original code works now, because we've already rewritten the file's header. – Paul M. May 02 '21 at 14:12