ID3_V1 仅支持 latin1 编码。为了用俄语字符编写 V1 标签,使用了 cp1251 编码。我想将数据从 V2 标签 (unicode) 复制到 V1 标签。我使用 eyeD3 使用以下代码获得 V2 标签:
tag.link(mp3path, v=eyeD3.ID3_V2)
mp3album_v2 = tag.getAlbum()
...
tag.link(mp3path, v=eyeD3.ID3_V1)
tag.setTextEncoding(eyeD3.LATIN1_ENCODING)
tag.setAlbum(mp3album_v2.encode('cp1251')) # ???
tag.update()
返回以下内容:
>>> print mp3album_v2
Жить в твоей голове
>>> print type(mp3album_v2)
<type 'unicode'>
>>> print repr(mp3album_v2)
u'\u0416\u0438\u0442\u044c \u0432 \u0442\u0432\u043e\u0435\u0439 \u0433\u043e\u043b\u043e\u0432\u0435'
看起来 setAlbum 需要 utf-8 字符串 (?):
def setAlbum(self, a):
self.setTextFrame(ALBUM_FID, self.strToUnicode(a));
def strToUnicode(self, s):
t = type(s);
if t != unicode and t == str:
s = unicode(s, eyeD3.LOCAL_ENCODING);
elif t != unicode and t != str:
raise TagException("Wrong type passed to strToUnicode: %s" % str(t));
return s;
但是如果我尝试执行 tag.setAlbum(mp3album_v2.encode('cp1251').encode('utf-8')),那么我会得到一个错误 UnicodeDecodeError: “utf8”编解码器无法解码位置 0 中的字节 0xc6:无效的连续字节
请您参考如下方法:
ID3v1 不能可靠地包含任何非 ASCII 字符。您可以将 cp1251 编码的字节写入 ID3v1 标签,但它们只会在安装俄语语言环境操作系统时呈现为西里尔文,甚至不会在所有应用程序中呈现。
EyeD3 在内部处理 Unicode 字符串并任意选择使用 latin1(又名 ISO-8859-1)作为 ID3v1 标签的编码。这可能不是一个好的选择,因为 latin1 从来不是 Windows 机器上默认的特定于区域设置的编码(对于西欧,它实际上是 cp1252 ,它相似但不相同).
然而,这种编码选择的一个属性是其中的每个字节都映射到具有相同代码点编号的 Unicode 字符。您可以通过制作一个包含字符的 Unicode 字符串来利用这一点,当这些字符被编码为 latin1 时,最终将成为所选字符串的字节编码,而不是 latin1.
album_name = u'Жить в твоей голове'
mangled_name = album_name.encode('cp1251').decode('latin1')
tag.setAlbum(mangled_name) # will encode as latin1, resulting in cp1251 bytes
这是一个可怕的 hack,其好处值得怀疑,也是您应该避免使用 ID3v1 的原因之一。
