0

I am trying to insert the album pictutre of a music(mp3) as an image in Python GUI window. I used mutagen ID3 picture class for this purpose. It was described in the docs but I excactly dont know how to do it. So kindly I would like to request for an example to show how to do it correctly. And if possible, please specify if there is any alternative.

Thank-you!

Toru
  • 3
  • 1
  • 4
  • There is an alternative library - [stagger](https://github.com/lorentey/stagger), which is pretty much easier to use than mutagen(really; you can do stuff like `mp3.artist = 'Artist'`). If you want to use mutagen, you should use the `APIC` frame(if you want to know how to do this with stagger, please let me know). – sudormrfbin Jun 11 '17 at 07:12
  • @Gokul Thanks Gokul ! Yes, I am interested to learn more on "stagger". Can you give some simple examples? Or is there any tutorial.....Thanks! – Toru Jun 11 '17 at 08:07

2 Answers2

2

Stagger is a library for modifying id3v2 tags; it's pretty much easy to use:

In [1]: import stagger

In [2]: mp3 = stagger.read_tag('/home/gokul/Music/Linkin Park - Burning In The Skies.mp3')

In [3]: mp3.artist
Out[3]: 'Linkin Park'

In [4]: mp3.album
Out[4]: 'A Thousand Suns'

In [5]: mp3.picture  # the cover has not been set yet
Out[5]: ''

Rest of the API is similar to this. You can modify tags like this:

In [6]: mp3.album = 'Changed It'

In [7]: mp3.album
Out[7]: 'Changed It'

To set the album/cover picture, all you have to do is....

In [10]: mp3.picture = '/home/gokul/Pictures/Cover.jpg' # path to file

In [11]: mp3.picture  # the cover has been saved!
Out[11]: 'Other(0)::<2834 bytes of jpeg data>'

You have to save the tags to the file now:

In [12]: mp3.write()

That's it! Done ;)
If you want to see all the tags in the file use mp3.frames:

In [13]: mp3.frames()
Out[13]: 
[TIT2(encoding=0, text=['Burning In The Skies']),
TPE1(encoding=0, text=['Linkin Park']),
TALB(encoding=0, text=['Changed It']),
APIC(encoding=None, mime='image/jpeg', type=0, desc='', data=<2834 bytes of binary data b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00'...>)]

Cheers!

P.S. You can modify any id3v2 tag using stagger; some of them(most common) can be modified using a format like mp3.title = 'title'. See stagger's GitHub page for editing other(uncommon and complex) tags.

sudormrfbin
  • 618
  • 8
  • 16
  • Thank you Gokul! Its lot more easier than Mutagen. But there's a problem. How can I put the image in a GUI? I am getting only a code 'Other(0)::<16937 bytes of jpeg data>' instead of an image. Anyways Thanks Again!! – Toru Jun 16 '17 at 12:34
  • 1
    You're welcome :) You can do that by: `mp3[stagger.id3.APIC][0].data`. You will get the binary data. – sudormrfbin Jun 17 '17 at 15:13
  • Thanks for the reply. Now I am able to get the whole data of the image :D But when I tried to put the Image on a GUI, I faced unicode error......[UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte] I think for decoding it to bytes but is there any proper way for decoding the data of Image? Thanks Gokul for spending your precious time for me. Thank you!! – Toru Jun 18 '17 at 10:47
  • I don't think there is; I'm not at all sure :| – sudormrfbin Jun 19 '17 at 14:37
  • Its OK. Anyways Thank you so much Gokul for helping me a lot :) – Toru Jun 19 '17 at 16:21
2

I started from Gokul's answer and found out that there is a way to decode the image data that you get with stagger with the following code:

from PIL import Image
import stagger
import io

mp3 = stagger.read_tag('song.mp3')
by_data = mp3[stagger.id3.APIC][0].data
im = io.BytesIO(by_data)
imageFile = Image.open(im)

The imageFile variable holds the image in the same way as if you imported a jpg directly with

imageFile = Image.open("test_image.jpg")

So now you can use the album art from the mp3 file however you want. I think there are multiple ways to add an image to a GUI, but the method I use is to add the lines

import tkinter
from PIL import ImageTk

photo = ImageTk.PhotoImage(imageFile)
label = tkinter.Label(image=photo)
label.image = photo
label.pack()
Koen
  • 21
  • 4