본문 바로가기
장난감/mp3tagger

mp3tagger 3 - GUI with tkinter (filedialog)

by Mr. Green 2022. 8. 8.

 안녕하세요. 이번엔 GUI를 완성해보겠습니다. 물론 tkinter 입니다.

차례

0. filedialog.askopenfilename()

0-1. 파일 열기 버튼

1. 파일 태그 띄우기

1-1. 태그 기본값

1-2. 태그 저장

2. 커버 이미지 버튼

3. 프로젝트 3

0. filedialog.askopenfilename()

 tkinter에서 파일을 선택할 수 있는 창을 띄울 수 있습니다. 이 명령어로는 파일 하나만 열 수 있는데, 필요하다면 끝에 s를 붙여(askopenfilenames()) 여러 파일을 선택하게 할 수 있습니다.

aud_path = filedialog.askopenfilename(filetypes=[('mp3', '.mp3'), ('wma', '.wma'), ('all audio', '*.*')], initialdir='./input/')
aud = eyed3.load(aud_path)
  • filetypes : 확장자를 골라 보기 편하게 해줍니다.
    • 예) *.mp3 : mp3 형식의 모든 파일
    • *.* : 모든 파일 명+모든 확장자
  • initialdir : 선택창 뜨자마자 바로 보여줄 디렉토리
  • eyed3.load : 선택된 파일을 바로 받는다.

initialdir에서 mp3 파일만 보여주고 있는 선택창

0-1. 파일 열기 버튼

 위 파일 선택창을 그대로 함수에 복사해 버튼에 넣어줍니다. 방법

def aud_opener():
	path = filedialog.askopenfilename(filetypes=[('mp3', '.mp3'), ('wma', '.wma'), ('all audio', '*.*')], initialdir='./input/')
	aud = eyed3.load(path)

	aud_title.configure(text=aud.tag.title)
	aud_artist.configure(text=aud.tag.artist)
	aud_genre.configure(text=aud.tag.genre)
	aud_album.configure(text=aud.tag.album)
	aud_date.configure(text=aud.tag.original_release_date)
	aud_albumartist.configure(text=aud.tag.album_artist)
	aud_composer.configure(text=aud.tag.composer)
	aud_tracknumber.configure(text=aud.tag.track_num[0])
    
    
	title_input.delete(0, len(str(title_input.get())))
	artist_input.delete(0, len(str(artist_input.get())))
	genre_input.delete(0, len(str(genre_input.get())))
	...
	title_input.insert(0, aud.tag.title)
	artist_input.insert(0, aud.tag.artist)
	genre_input.insert(0, aud.tag.genre)
	...
    
opener = Button(text='Open Files', command=aud_opener)
opener.grid(row=9, column=0)

 파일을 선택하면 configure(text)로 밑의 Label에 내용을 바꿔줍니다.

1. 파일 태그 띄우기

 태그는 eyed3를 이용할 겁니다.

aud_title = Label(window, text=aud.tag.title, width=20)
aud_title.grid(row=1, column=2, columnspan=2)

 위 방식으로 title, artist, genre, album, original_release_date, album_artist, composer, track_num[0]을 넣어줍니다.

1-1. 태그 기본값

 태그를 저장할 때 빈 칸을 그대로 두면 태그를 비워버리기 때문에 기존에 갖고 있는 태그를 Entry에 띄워줘 저장을 누를 때 바꾸지 않을 태그는 유지시켜 줄 수 있도록 합니다.

title_input = Entry(window, width=15)
title_input.insert(0, aud.tag.title)
title_input.grid(row=1, column=1)
artist_input = Entry(window, width=15)
artist_input.insert(0, aud.tag.artist)
artist_input.grid(row=2, column=1)
genre_input = Entry(window, width=15)
genre_input.insert(0, aud.tag.genre)
genre_input.grid(row=3, column=1)
...

 insert(0, 내용) : Entry에 0번째 문자열에 내용을 넣습니다.

def opener():
	...
    
	title_input.delete(0, len(str(title_input.get())))
	artist_input.delete(0, len(str(artist_input.get())))
	genre_input.delete(0, len(str(genre_input.get())))
	...
	title_input.insert(0, aud.tag.title)
	artist_input.insert(0, aud.tag.artist)
	genre_input.insert(0, aud.tag.genre)
	...

 open file 버튼으로 파일을 불러올 때 역시 바뀐 파일의 태그를 Entry에 넣어줘야 합니다. 하지만 insert만 넣으면 문자열을 옆으로 밀고 넣기 때문에 delete를 써서 Entry의 내용을 비우고 다시 채워야 합니다.

1-2. 태그 저장

 태그를 Entry에 쓰고 그 내용을 저장합니다. 주의할 점은 빈 칸으로 두고 저장 눌러버리면 원래 있던 태그를 빈 칸으로 덮어버립니다.

def saver():
	aud.initTag()
	aud.tag.title = title_input.get()
	aud.tag.artist = artist_input.get()
	aud.tag.genre = genre_input.get()
	...
    
	aud.tag.save()

	if aud.tag.title:
		aud_title.configure(text=aud.tag.title)
	if aud.tag.artist:
		aud_artist.configure(text=aud.tag.artist)
	if aud.tag.genre:
		aud_genre.configure(text=aud.tag.genre)
	...

	tag_comp_lbl.configure(text='tag : done!')

2. 커버 이미지 버튼

 버튼을 눌러 파일 선택창을 엽니다. jpg, png 등 이미지 파일을 불러올 수 있게 확장자를 바꿔줍니다. 마무리로 선택된 파일 형식에 따라 APIC에서 파일 형식을 다르게 받아 줄 수 있게 만듭니다.

def cover_img():
    cov_path = filedialog.askopenfilename(filetypes=[('jpg', '.jpg'), ('png', '.png'), ('all images', '*.*')], initialdir='./input/')
    cov_path = cov_path.replace('\\', '/')

    if cov_path.endswith('png'):
        mime = 'image/png'
    if cov_path.endswith('webp'):
        mime = 'image/webp'
    if cov_path.endswith('jpg'):
        mime = 'image/jpg'
    if cov_path.endswith('jpeg'):
        mime = 'image/jpeg'

    aud = MP3(aud_path, ID3=ID3)
    aud.tags.add(
            APIC(
                encoding=0,
                mime=mime,
                type=3,
                data=open(cov_path, 'rb').read()
            )
        )
    aud.save()

    cov_comp_lbl.configure(text='cover : done!')
    
cover = Button(text='Cover Image', command=cover_img, width=10)
cover.grid(row=9, column=2)

 다만 여기서 중요한 점은 eyed3에선 파일 디렉토리를 바로 받아서 쓸 수 있었지만 mutagen에서는 \를 /로 바꿔줘야 인식합니다. 또 \는 특수문자를 다룰 때 쓰는 문자이기 때문에 \\로 써줘야 \로 인식됩니다.

 endswith(keyword)는 keyword로 끝날 때 참을 반환합니다.

3. 프로젝트 3

 이 코드로 완성입니다!

from tkinter import Tk, filedialog
from tkinter import Label, Entry, Button

from mutagen.mp3 import MP3
from mutagen.id3 import ID3, APIC

import eyed3


def aud_opener():
    path = filedialog.askopenfilename(filetypes=[('mp3', '.mp3'), ('wma', '.wma'), ('all audio', '*.*')], initialdir='./input/')
    aud = eyed3.load(path)

    aud_title.configure(text=aud.tag.title)
    aud_artist.configure(text=aud.tag.artist)
    aud_genre.configure(text=aud.tag.genre)
    aud_album.configure(text=aud.tag.album)
    aud_date.configure(text=aud.tag.original_release_date)
    aud_albumartist.configure(text=aud.tag.album_artist)
    aud_composer.configure(text=aud.tag.composer)
    aud_tracknumber.configure(text=aud.tag.track_num[0])
    
    title_input.delete(0, len(str(title_input.get())))
    artist_input.delete(0, len(str(artist_input.get())))
    genre_input.delete(0, len(str(genre_input.get())))
    album_input.delete(0, len(str(album_input.get())))
    date_input.delete(0, len(str(date_input.get())))
    albumartist_input.delete(0, len(str(albumartist_input.get())))
    composer_input.delete(0, len(str(composer_input.get())))
    tracknumber_input.delete(0, len(str(tracknumber_input.get())))

    title_input.insert(0, aud.tag.title)
    artist_input.insert(0, aud.tag.artist)
    genre_input.insert(0, aud.tag.genre)
    album_input.insert(0, aud.tag.album)
    date_input.insert(0, str(aud.tag.original_release_date))
    albumartist_input.insert(0, aud.tag.album_artist)
    composer_input.insert(0, aud.tag.composer)
    tracknumber_input.insert(0, aud.tag.track_num[0])
    
    tag_comp_lbl.configure(text='tag : yet!')
    cov_comp_lbl.configure(text='cover : yet!')

def cover_img():
    cov_path = filedialog.askopenfilename(filetypes=[('jpg', '.jpg'), ('png', '.png'), ('all images', '*.*')], initialdir='./input/')
    cov_path = cov_path.replace('\\', '/')

    if cov_path.endswith('png'):
        mime = 'image/png'
    if cov_path.endswith('webp'):
        mime = 'image/webp'
    if cov_path.endswith('jpg'):
        mime = 'image/jpg'
    if cov_path.endswith('jpeg'):
        mime = 'image/jpeg'

    aud = MP3(aud_path, ID3=ID3)
    aud.tags.add(
            APIC(
                encoding=0,
                mime=mime,
                type=3,
                data=open(cov_path, 'rb').read()
            )
        )
    aud.save()

    cov_comp_lbl.configure(text='cover : done!')

def saver():
    aud.initTag()
    aud.tag.title = title_input.get()
    aud.tag.artist = artist_input.get()
    aud.tag.genre = genre_input.get()
    aud.tag.album = album_input.get()
    aud.tag.original_release_date = date_input.get()
    aud.tag.album_artist = albumartist_input.get()
    aud.tag.composer = composer_input.get()
    aud.tag.track_num = tracknumber_input.get()
    aud.tag.save()

    if aud.tag.title:
        aud_title.configure(text=aud.tag.title)
    if aud.tag.artist:
        aud_artist.configure(text=aud.tag.artist)
    if aud.tag.genre:
        aud_genre.configure(text=aud.tag.genre)
    if aud.tag.album:
        aud_album.configure(text=aud.tag.album)
    if aud.tag.original_release_date:
        aud_date.configure(text=aud.tag.original_release_date)
    if aud.tag.album_artist:
        aud_albumartist.configure(text=aud.tag.album_artist)
    if aud.tag.composer:
        aud_composer.configure(text=aud.tag.composer)
    if aud.tag.track_num:
        aud_tracknumber.configure(text=aud.tag.track_num[0])

    tag_comp_lbl.configure(text='tag : done!')



window = Tk()

window.title('mp3tagger 1.0.0')
window.geometry('400x250+400+200')
window.resizable(False, False)
window.iconbitmap('./icon.ico')

aud_path = filedialog.askopenfilename(filetypes=[('mp3', '.mp3'), ('wma', '.wma'), ('all audio', '*.*')], initialdir='./input/')
aud = eyed3.load(aud_path)

aud_title = Label(window, text=aud.tag.title, width=20)
aud_title.grid(row=1, column=2, columnspan=2)
aud_artist = Label(window, text=aud.tag.artist, width=20)
aud_artist.grid(row=2, column=2, columnspan=2)
aud_genre = Label(window, text=aud.tag.genre, width=20)
aud_genre.grid(row=3, column=2, columnspan=2)
aud_album = Label(window, text=aud.tag.album, width=20)
aud_album.grid(row=4, column=2, columnspan=2)
aud_date = Label(window, text=aud.tag.original_release_date, width=20)
aud_date.grid(row=5, column=2, columnspan=2)
aud_albumartist = Label(window, text=aud.tag.album_artist, width=20)
aud_albumartist.grid(row=6, column=2, columnspan=2)
aud_composer = Label(window, text=aud.tag.composer, width=20)
aud_composer.grid(row=7, column=2, columnspan=2)
aud_tracknumber = Label(window, text=aud.tag.track_num[0], width=20)
aud_tracknumber.grid(row=8, column=2, columnspan=2)

title = Label(window, text='Title : ')
title.grid(row=1, column=0)
artist = Label(window, text='Artist : ')
artist.grid(row=2, column=0)
genre = Label(window, text='Genre : ')
genre.grid(row=3, column=0)
album = Label(window, text='Album : ')
album.grid(row=4, column=0)
date = Label(window, text='Year : ')
date.grid(row=5, column=0)
albumartist = Label(window, text='Album Artists : ')
albumartist.grid(row=6, column=0)
composer = Label(window, text='Composer : ')
composer.grid(row=7, column=0)
tracknumber = Label(window, text='Track Number : ')
tracknumber.grid(row=8, column=0)

title_input = Entry(window, width=15)
title_input.insert(0, aud.tag.title)
title_input.grid(row=1, column=1)
artist_input = Entry(window, width=15)
artist_input.insert(0, aud.tag.artist)
artist_input.grid(row=2, column=1)
genre_input = Entry(window, width=15)
genre_input.insert(0, aud.tag.genre)
genre_input.grid(row=3, column=1)
album_input = Entry(window, width=15)
album_input.insert(0, aud.tag.album)
album_input.grid(row=4, column=1)
date_input = Entry(window, width=15)
date_input.insert(0, str(aud.tag.original_release_date))
date_input.grid(row=5, column=1)
albumartist_input = Entry(window, width=15)
albumartist_input.insert(0, aud.tag.album_artist)
albumartist_input.grid(row=6, column=1)
composer_input = Entry(window, width=15)
composer_input.insert(0, aud.tag.composer)
composer_input.grid(row=7, column=1)
tracknumber_input = Entry(window, width=15)
tracknumber_input.insert(0, aud.tag.track_num[0])
tracknumber_input.grid(row=8, column=1)

opener = Button(text='Open Files', command=aud_opener)
opener.grid(row=9, column=0)
cover = Button(text='Cover Image', command=cover_img, width=10)
cover.grid(row=9, column=2)
saver_btn = Button(text='여!', command=saver, width=10)
saver_btn.grid(row=9, column=3)

cov_comp_lbl = Label(text='cover : yet')
tag_comp_lbl = Label(text='tag : yet')
cov_comp_lbl.grid(row=10, column=2)
tag_comp_lbl.grid(row=10, column=3)

window.mainloop()

'장난감 > mp3tagger' 카테고리의 다른 글

mp3tagger 2 - mutagen  (0) 2022.08.07
mp3tagger 1 - eyed3  (0) 2022.08.07
mp3tagger - mp3에 태그를 넣자  (0) 2022.08.05