我在编写脚本以使用诱变剂标记我的音乐库时遇到问题。 以下代码在处理 mp3 文件时工作正常,但会损坏 m4a 文件。
def set_video_tags(video, filepath):
try:
tags = ID3(filepath, v2_version=3)
except ID3NoHeaderError:
tags = ID3()
tags.add(TXXX(3, desc='desc:custom_tag',text= video.custom_text))
tags.save(filepath, v2_version=3)
处理 m4a 文件后,标签可以使用 mutagen 读回,但不会被任何其他播放器检测到,音频也不会播放。
我尝试在调用此函数之前从文件中删除 MP4 标签,但没有帮助。
我做错了什么?
请您参考如下方法:
正如我在评论中所说,MP4 和 MP3 是不同的容器,它们使用完全不同的结构来存储元数据。虽然从技术上讲,您可以在 MP4 元数据中编码 ID3 字段,但这种方法的使用在很大程度上取决于您的标记器/播放器,因为有很多方法可以做到这一点,每个人都认为他们有最好的方法,因此可以插入他们自己的结构。
什么是 MP3 容器的 ID3,XMP适用于 MP4/M4A 容器(以及许多其他容器,如 JPEG、PDF 甚至 MP3,如果你愿意的话)——除了 XMP 是一个实际标准而 ID3 是事后才想到的(它实际上只是在MP3 文件的末尾),每个人都喜欢它,它的功能主要由当时非常流行的播放器决定,如 WinAmp、foobar2000 等。相比之下,XMP 本质上是一种类似原子馈送的结构(这就是为什么您会听到 mp4 标签被称为“原子”,即使它们指的不是同一事物),它连同其元数据还包含有关什么的信息元数据的呈现使得即使是第一次遇到它的玩家在理论上也可以从不相关的元数据中辨别出相关的元数据。
当然,在实践中,这也变成了播放器/标记器 war ,因此他们中的许多人使用自己的自定义“扩展”进行标记 - 目前 iTunes 在应该使用哪些字段以及如何使用以及其他方面拥有巨大的影响力玩家喜欢打球 - 诱变剂 也是。 iTunes 不是单一的 XMP 结构,而是在 MP4 结构本身中将标签作为非视频/音频帧(实际的“原子”)传播,并且一些“标签”必须被奇怪地命名(二进制名称等),所以它们不会“不会干扰格式本身。虽然这种方法有一些优势(通过流式传输更改元数据,对现场事件非常有用),但它使标记变得不必要地复杂,并且再次成为非标准的。
无论如何,您的问题发生是因为您试图将 ID3 结构写入 MP4 容器 - 当写入 ID3 标签时 mutagen 不会解析整个文件以辨别底层文件是否支持 ID3以及在哪里/如何写它,相反,它假设它被提供了一个普通的 MP3 文件,并在错误的地方以错误的格式写下,充其量只是在文件末尾添加一些垃圾(早期的,不可流式传输的) ID3 版本),或者最坏的情况是破坏您的 M4A 容器。当您读回文件时也是如此 - 它可以在可预测的位置读取它之前写入的 ID3 结构,它不关心其余数据是什么。
所以,正如我所说的,并且如文档中所示,使用 mutagen.mp4.MP4(或者更确切地说是底层 mutagen.mp4.MP4Tags)在处理 MP4/M4A 容器时,因为它们是为与 MP4 容器一起工作而创建的。例如,要在您尝试更改 desc 标签时:
from mutagen.mp4 import MP4
def get_description(filename):
return MP4(filename).tags.get("desc", [None])[-1]
def set_description(filename, description):
tags = MP4(filename).tags
tags["desc"] = description
tags.save(filename)
注意:我只使用 get_description() 函数中的最后一个 desc 条目,因为每个“标签”支持多个条目,因此现有标签作为列表返回。您显然不会在生产环境中使用上述内容。
你可以用它来测试:
print("Current description: {}".format(get_description("test.m4a")))
# Current description: None
set_description("test.m4a", "Test description") # let's add some description
print("Current description: {}".format(get_description("test.m4a")))
# Current description: Test description
# You can also modify the description once set:
set_description("test.m4a", get_description("test.m4a") + " update")
print("Current description: {}".format(get_description("test.m4a")))
# Current description: Test description update
# etc.
对于全套“受支持”(或者更确切地说,iTunes,嗯,鼓励) key ,您可以查看 mutagen.mp4.MP4Tag文档。当然,您可以使用自由形式的结构(即 ----:foo:bar)发明自己的 key ,但不要指望任何其他玩家都能识别它们。
