3

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

我已经完全按照此答案中的说明复制了代码:

使用 Mutagen 在 MP4 文件中嵌入专辑封面

但是当我尝试运行代码时仍然收到错误消息。如果我自己运行带有“albumart”值的代码,我会收到错误:

MP4file.tags['covr'] = albumart

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

但是,如果我用括号括住专辑标签变量,如前面提到的 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]

两天来我一直在试图弄清楚我做错了什么。如果有人能帮我发现问题,我会欠你的。

谢谢!

4

1 回答 1

1

在引发异常的位置的源代码中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不能bytesAtom.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)了代码的最后一行,以保留对文件所做的更改。

于 2019-06-19T18:40:00.183 回答