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

时间:2019-01-01 19:37:15

标签: python mp3 mp4 mutagen

根据其他StackOverflow问题和诱变剂文档的多项建议,我能够拿出代码来获取和设置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 个答案:

答案 0 :(得分: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是Cover标签的名称,value是从图像读取的数据,包装在MP4Cover对象中。好吧,事实证明,如果您像上面的代码那样遍历MP4Cover对象,则每次迭代将为int生成一个图像字节。

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

在您上面给出的代码中,封面图像的字节被包装在MP4Cover类型的对象内,该对象无法像{{1}的第二个参数那样添加到bytes }。

为避免不得不编辑或修补Atom.render库源代码,诀窍是将“ MP4Cover”对象转换为mutagen并将结果包装在集合中,如下所示。

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) 作为代码的最后一行,以保留对文件所做的更改。