Проблемы с настройкой обложки для файлов MP4 с использованием Python и Mutagen - PullRequest
0 голосов
/ 01 января 2019

Следуя многочисленным предложениям из других вопросов StackOverflow и документации по мутагенам, я смог придумать код для получения и установки каждого тега ID3 в файлах MP3 и MP4.У меня проблема с настройкой обложки для файлов M4B.

Я воспроизвел код в точности так, как он изложен в этом ответе:

Вставка обложки альбома в файл MP4используя Mutagen

Но я все еще получаю ошибки, когда пытаюсь запустить код.Если я сам запускаю код со значением 'albumart', я получаю сообщение об ошибке:

MP4file.tags['covr'] = albumart

Исключение: TypeError не может преобразовать int в байты

Однако, если я окружу переменную albumart скобками, как показано в вышеупомянутом вопросе StackOverflow, я получу следующий вывод:

MP4file.tags['covr'] = [albumart]

Произошло исключение: обязательный аргумент struct.error не является целым числом

Вот функция целиком.Секция MP3 работает без проблем.

from mutagen.mp3 import MP3
from mutagen.mp4 import MP4, MP4Cover


def set_cover(filename, cover):
    r = requests.get(cover)
    with open('C:/temp/cover.jpg', 'wb') as q:
        q.write(r.content)
    if(filename.endswith(".mp3")):
        MP3file = MP3(filename, ID3=ID3)
        if cover.endswith('.jpg') or cover.endswith('.jpeg'):
            mime = 'image/jpg'
        else:
            mime = 'image/png'
        with open('C:/temp/cover.jpg', 'rb') as albumart: 
            MP3file.tags.add(APIC(encoding=3, mime=mime, type=3, desc=u'Cover', data=albumart.read()))
        MP3file.save(filename)
    else:
        MP4file = MP4(filename)
        if cover.endswith('.jpg') or cover.endswith('.jpeg'):
            cover_format = 'MP4Cover.FORMAT_JPEG'
        else:
            cover_format = 'MP4Cover.FORMAT_PNG'
        with open('C:/temp/cover.jpg', 'rb') as f:
            albumart = MP4Cover(f.read(), imageformat=cover_format)
        MP4file.tags['covr'] = [albumart]

Я пытаюсь понять, что я делаю не так уже два дня.Если кто-нибудь может помочь мне определить проблему, я буду у вас в долгу.

Спасибо!

1 Ответ

0 голосов
/ 19 июня 2019

В исходном коде mutagen в том месте, где возникает исключение, я нашел следующие строки:

 def __render_cover(self, key, value):
        ...
        for cover in value:
            try:
                imageformat = cover.imageformat
            except AttributeError:
                imageformat = MP4Cover.FORMAT_JPEG
            ...
            Atom.render(b"data", struct.pack(">2I", imageformat, 0) + cover))
        ...

Там key - это имя тега обложки и value - это данные, считанные с изображения, обернутые в объект MP4Cover.Что ж, получается, что если вы итерируете объект MP4Cover, как в приведенном выше коде, итерация выдает один байт изображения за итерацию как int.

Более того, в Python версии 3+ struct.pack возвращает объект типа bytes.Я думаю, что аргумент cover был задуман как набор байтов, взятых с обложки.

В приведенном выше коде байты изображения обложки заключены в объект типа MP4Cover, который нельзя добавить к bytes, как это делается во втором аргументе Atom.render.

Чтобы избежать необходимости редактировать или исправлять исходный код библиотеки mutagen, уловка заключается в преобразовании объекта 'MP4Cover' в bytes и заключении результата в коллекцию, как показано ниже.

import requests
from mutagen.mp3 import MP3
from mutagen.mp4 import MP4, MP4Cover


def set_cover(filename, cover):
    r = requests.get(cover)
    with open('C:/temp/cover.jpg', 'wb') as q:
        q.write(r.content)
    if(filename.endswith(".mp3")):
        MP3file = MP3(filename, ID3=ID3)
        if cover.endswith('.jpg') or cover.endswith('.jpeg'):
            mime = 'image/jpg'
        else:
            mime = 'image/png'
        with open('C:/temp/cover.jpg', 'rb') as albumart: 
            MP3file.tags.add(APIC(encoding=3, mime=mime, type=3, desc=u'Cover', data=albumart.read()))
        MP3file.save(filename)
    else:
        MP4file = MP4(filename)
        if cover.endswith('.jpg') or cover.endswith('.jpeg'):
            cover_format = 'MP4Cover.FORMAT_JPEG'
        else:
            cover_format = 'MP4Cover.FORMAT_PNG'
        with open('C:/temp/cover.jpg', 'rb') as f:
            albumart = MP4Cover(f.read(), imageformat=cover_format)
        MP4file.tags['covr'] = [bytes(albumart)]
        MP4file.save(filename)

Я также добавил MP4file.save(filename) в качестве последней строки кода, чтобы сохранить изменения, внесенные в файл.

...