Как добавить фотографию c обложки mp3 в QPixmap pyqt5

Пишу MP3-Player. Мне нужно при открытии определенной песни ее картинку показывать на окне. Но я не могу картинку загрузить в QPixmap. Как это сделать?

UPD: С картинкой разобрался. Не существует в mutagen метода, который позволит вытащить из mp3-файла название и исполнителя мелодии?

введите сюда описание изображения

from PyQt5.Qt import *
import sys

DEFAULT_STYLE = """
QProgressBar{
    border: 2px solid grey;
    border-radius: 5px;
    text-align: center
}

QProgressBar::chunk {
    background-color: orange;
    width: 10px;
   
}
"""
sliderSheet = """

QSlider::handle {
    height: 10px;
    background: yellow;
    margin: 0 -4px; 
}

QSlider::add-page {
    background: black;
}

QSlider::sub-page {
    background: yellow;
}

"""

class Window(QWidget):
    def __init__(self, parent = None):
        QWidget.__init__(self, parent)

        self.setWindowIcon(QIcon("images/mp3-player.ico"))
        self.setWindowTitle("MP3-Player")
        self.setMinimumSize(700,700)

        self.first_open_pixmap = QPixmap("images/start_picture.png")
        self.background_pixmap = QPixmap("images/background.jpg")
        self.background_pixmap = self.background_pixmap.scaled(4000,4000, Qt.KeepAspectRatio, Qt.FastTransformation)

        self.background_label = QLabel(self)
        self.background_label.hide()
        self.background_label.setPixmap(self.background_pixmap)

        self.song_image_label = QLabel(self)
        self.song_image_label.hide()

        self.first_open_label = QLabel(self)
        self.first_open_label.setPixmap(self.first_open_pixmap)

        self.left_grey_label = QLabel(self)
        self.left_grey_label.setStyleSheet("background-color: rgb(147,147,147);")

        self.high_grey_label = QLabel(self)
        self.high_grey_label.setStyleSheet("background-color: rgb(147,147,147);")

        self.cross_label = QLabel(self)
        self.cross_label.setStyleSheet("background-color: rgb(94,94,94);")

        self.slider = QSlider(self)
        self.slider.hide()

        self.start_progress_bar = QProgressBar(self)
        self.start_progress_bar.setGeometry(150,400,350,10)
        self.start_progress_bar.setStyleSheet(DEFAULT_STYLE)

        self.start_button = QPushButton(self)
        self.start_button.setIcon(QIcon('images/start.png'))
        self.start_button.setIconSize(QSize(70, 70))
        self.start_button.hide()

        self.next_button = QPushButton(self)
        self.next_button.setIcon(QIcon('images/next.png'))
        self.next_button.setIconSize(QSize(90, 90))
        self.next_button.hide()

        self.previous_button = QPushButton(self)
        self.previous_button.setIcon(QIcon('images/previous.png'))
        self.previous_button.setIconSize(QSize(60, 60))
        self.previous_button.hide()

        self.package = QFileDialog(self)

        self.package_button = QPushButton(self)
        self.package_button.setIcon(QIcon('images/package.png'))
        self.package_button.setIconSize(QSize(60, 60))
        self.package_button.hide()

        self.time = 0
        self.new_view = False
        self.music_here = False
        self.first_edited = 0
        self.start_stop = 0
        self.value = 0

        self.timer_duration = QTimer(self)
        self.current_window_size_timer = QTimer(self)
        self.start_timer = QTimer(self)

        self.current_window_size_timer.start(10)


        self.start_button.clicked.connect(self.play_music)
        self.start_timer.timeout.connect(self.first_open_app)
        self.package_button.clicked.connect(self.open_package)
        self.next_button.clicked.connect(self.next_secs)
        self.previous_button.clicked.connect(self.prev_secs)
        self.timer_duration.timeout.connect(self.value_slider)
        self.current_window_size_timer.timeout.connect(self.window_size)

        self.first_open_app()

    def first_open_app(self):
        self.time+=1
        self.setStyleSheet("background-color: rgb(94, 94, 94)")
        self.first_open_label.setGeometry(250,200,200,150)

        self.start_timer.start(5)

        self.start_progress_bar.setValue(self.time)
        self.start_progress_bar.setFormat("")

        if self.time == 100:
            self.start_timer.stop()
            self.prepare_main_app()

    def prepare_main_app(self):
        self.first_open_label.hide()
        self.start_progress_bar.hide()

        self.setStyleSheet("background-color: rgb(255,255,255)")
        self.new_view = True

    def paintEvent(self, event):
        if self.new_view == True:
            self.left_grey_label.setGeometry(0,0, \
                                             60,640*self.more_than_need_height)
            self.high_grey_label.setGeometry(0,640*self.more_than_need_height, \
                                             700*self.more_than_need_width,60*self.more_than_need_height)
            self.cross_label.setGeometry(0,640*self.more_than_need_height, \
                                         60*self.more_than_need_width,60*self.more_than_need_height)

            self.start_progress_bar.setGeometry(150 * self.more_than_need_width,380 * self.more_than_need_height, \
                                                375 *self.more_than_need_width,15 * self.more_than_need_height)

            self.start_button.show()
            self.start_button.setGeometry(120*self.more_than_need_width,640 *self.more_than_need_height, \
                                          60*self.more_than_need_width,60*self.more_than_need_height)
            self.start_button.setStyleSheet("background-color: rgb(97,97,97);border: None")

            self.next_button.show()
            self.next_button.setGeometry(60*self.more_than_need_width, 640 *self.more_than_need_height, \
                                         60*self.more_than_need_width, 60*self.more_than_need_height)
            self.next_button.setStyleSheet("background-color: rgb(97,97,97);border: None")
            self.previous_button.show()
            self.previous_button.setGeometry(180*self.more_than_need_width, 640 *self.more_than_need_height, \
                                             60*self.more_than_need_width, 60*self.more_than_need_height)
            self.previous_button.setStyleSheet("background-color: rgb(97,97,97);border: None")

            self.package_button.show()
            self.package_button.setGeometry(0, 580*self.more_than_need_height, \
                                            60, 60*self.more_than_need_height)
            self.package_button.setStyleSheet("background-color: rgb(147,147,147); \
                                               border: None;")
            self.slider.show()
            self.slider.setOrientation(Qt.Horizontal)
            self.slider.setGeometry(50,635*self.more_than_need_height,\
                                    652*(self.more_than_need_width+self.inaccuracy),5*self.more_than_need_height)
            self.slider.setStyleSheet(sliderSheet)

            self.song_image_label.show()
            self.song_image_label.setGeometry(180,120,400,340)
            self.song_image_label.setStyleSheet("background-color: rgba(255,255,255,0);")
            self.background_label.show()
            self.background_label.setGeometry(60,0,\
                                              640*(self.more_than_need_width+0.15),635*self.more_than_need_height)

            self.left_grey_label.raise_()
            self.package_button.raise_()


    def play_music(self):
        if self.music_here == True:
                self.start_stop+=1

                if self.start_stop%2 == 0:
                    self.start_button.setIcon(QIcon('images/start.png'))
                    self.start_button.setIconSize(QSize(70, 70))

                    self.player.pause()
                    self.timer_duration.stop()

                if self.start_stop%2 == 1:
                    self.start_button.setIcon(QIcon('images/stop.png'))
                    self.start_button.setIconSize(QSize(70, 70))

                    self.player.play()
                    self.timer_duration.start(1000)

    def value_slider(self):
        self.slider.setRange(0, self.player.duration()//1000)
        self.current_value = self.slider.value()
        self.value+=1
        self.slider.setValue(self.value)

        if self.slider.value() >= self.player.duration()//1000:
            self.value = 0
            self.start_stop = 0
            self.slider.setValue(0)
            self.player.setPosition(0)
            self.player.stop()
            self.timer_duration.stop()


            self.start_button.setIcon(QIcon('images/start.png'))
            self.start_button.setIconSize(QSize(70, 70))



    def prev_secs(self): #Перепутал prev_secs и next_secs
        if self.slider.value() > 0:
            self.player.setPosition(self.player.position() + 10000)
            self.slider.setValue(self.slider.value() + 10)
            self.value+=10

    def next_secs(self):
        if self.slider.value() > 10:
            self.player.setPosition(self.player.position() - 10000)
            self.slider.setValue(self.slider.value() - 10)
            self.value -= 10

        if self.slider.value() <=10 and self.slider.value()> 0:
            self.player.setPosition(0)
            self.slider.setValue(0)
            self.value = 0


    def open_package(self):
        self.name = QUrl(self.package.getOpenFileUrl()[0])

        if self.name != QUrl(""):
            self.music_here = True
            self.content = QMediaContent(self.name)

            self.player = QMediaPlayer()
            self.player.setMedia(self.content)

    def window_size(self): #Я решил не разбираться в контейнерах и делать немного по-своему растяжение виджетов
        self.current_width = self.width()
        self.more_than_need_width = self.current_width/700 #Ширина окна
        self.current_height = self.height()
        self.more_than_need_height = self.current_height / 700 #Высота окна
        if self.more_than_need_width > 1.0:
            self.inaccuracy = self.more_than_need_width / 23 # 1/23 - экспериментально выявленная погрешность
        else:
            self.inaccuracy = 0


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec_())

Ответы (1 шт):

Автор решения: Sergey Tatarincev

Если я правильно понимаю, речь о изображениях, содержащихся непосредственно в mp3.

Хранятся они в тэгах ID3v2 (описение на вики)

Для их извлечения можно использовать к примеру библиотеку mutagen

Но есть небольшой нюанс. Изображений в ID3v2 может не быть вовсе, или быть несколько.

Вот пример извлечения всех изображений и загрузки в pixmap первого:

import sys
from PyQt5 import QtGui, QtCore
from PyQt5 import QtWidgets
import mutagen
# пример mp3 содержащего изображения можно взять тут
# https://www.richardfarrar.com/audio/21%20-%20ID3%20Image%20-%20All%20Images.mp3

def saveMP3pix(filename):
    mp3 = mutagen.File(filename)
    allpix =[]
    for tag in mp3.items():
        if tag[0][:4] == 'APIC':
            pic = tag[1]
            new_name = f'my_pic_{len(allpix)}.' + str(pic.mime.split('/')[1])
            file = open(new_name, "wb")
            file.write(pic.data)
            file.close()
            allpix.append(new_name)
    return allpix



class MyWidget(QtWidgets.QWidget):

    def __init__(self, parent=None):
        QtWidgets.QWidget.__init__(self, parent=parent)
        self.initUI()

    def initUI(self):
        self.resize(1000,600)
        self.setWindowTitle('test')

        self.lb = QtWidgets.QLabel(self)
        pixlist = saveMP3pix("test.mp3")
        pixmap = QtGui.QPixmap(pixlist[0])
        self.lb.setPixmap(pixmap)
        self.show()    


def main():
    app = QtWidgets.QApplication(sys.argv)
    w = MyWidget()
    app.exec_()

if __name__ == '__main__':
    main()
→ Ссылка