运行 遇到使用 Python 和 Mutagen 为 MP4 文件设置封面的问题

Running into problems setting cover art for MP4 files using Python and Mutagen

根据其他 Whosebug 问题和 mutagen 文档的多项建议,我能够想出代码来获取和设置 MP3 和 MP4 文件中的每个 ID3 标签。我遇到的问题是为 M4B 文件设置封面。

我已经按照这个答案中的布局完全复制了代码:

但是当我尝试 运行 代码时,我仍然收到错误消息。如果我 运行 具有 'albumart' 值的代码本身我收到错误:

MP4file.tags['covr'] = albumart

Exception has occurred: TypeError can't concat int to bytes

但是,如果我像上述 Whosebug 问题中所示用方括号括起 albumart 变量,我会得到以下输出:

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

Exception has occurred: struct.error required argument is not an integer

这是完整的功能。 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]

这两天我一直在想我做错了什么。如果有人能帮助我发现问题,我会感激你的。

谢谢!

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 returns 类型为 bytes 的对象。我认为 cover 参数是从封面图像中提取的字节集合。

在你上面给出的代码中,封面图像的字节被包裹在一个类型为 MP4Cover 的对象中,不能像 [= 的第二个参数那样添加到 bytes 23=]。

为了避免必须编辑或修补 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) 作为代码的最后一行,以保留对文件所做的更改。