使用Python和Mutagen设置MP4文件封面遇到问题,该怎么办?

3

根据其他StackOverflow问题和mutagen文档的多个建议,我能够编写代码获取和设置MP3和MP4文件中的每个ID3标签。但是,我在为M4B文件设置封面时遇到了问题。

我已经按照以下答案中所述的方式精确复制了代码:

Embedding album cover in MP4 file using Mutagen

但是,当我尝试运行代码时仍然收到错误。如果我只使用“albumart”值运行代码,则会收到以下错误:

MP4file.tags['covr'] = albumart

异常已发生:TypeError 无法将 int 连接到字节中

然而,如果我像上述 StackOverflow 问题中所示的那样在 albumart 变量周围加上括号,我会得到以下输出:

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个回答

2
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中。

为了避免编辑或修补mutagen库源代码,技巧是将“MP4Cover”对象转换为bytes,并将结果包装在一个集合中,如下所示。

最初的回答:

封面标签的名称为key,从图片中读取的数据被封装成MP4Cover对象的形式保存在value中。当你遍历MP4Cover对象时,它会产生一字节的图像数据,每次迭代都会返回一个int类型的数据。

此外,在Python 3+版本中,struct.pack返回的是一个bytes类型的对象。我认为cover参数旨在收集从封面图像中获取的字节数据。

在您提供的代码中,封面图像的字节数据被包装在一个MP4Cover对象中,这个对象无法像Atom.render方法的第二个参数那样添加到bytes中。

要避免编辑或修补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)以保存对文件所做的更改,使其持久化。"Original Answer"翻译成"最初的回答"。

1
这是正确的。对于那些难以理解的人来说,通过在 bytes(albumart) 周围添加方括号,现在你可以将一个列表保存到 MP4file.tags['covr'] 中,这也意味着你可以在其中有多个图像。 - J-a-n-u-s
1
这个解决方案对我不起作用。我从中得到的错误是“无法将'bytes'对象解释为整数”。 - Hello
@hello 你本地的mutagen库副本版本是否与上面提到的问题中讨论的版本相同?你的Python解释器版本呢?如果你的使用情况与答案中的情况相同,那么Python或mutagen库中的某些内容可能已经发生了变化。这个答案已经快一年了,可能涉及过时的软件版本。 - Giova
1
这对我有效,尽管我相信解决方法导致cover_format无法被正确识别并写入文件。我也认为分配cover_format的行不应该有单引号,但我认为这不是问题所在。 - Aaron left Stack Overflow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接