1

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' codec can't decode byte 0xc6 in position 0: invalid continuation byte

4

1 に答える 1

7

ID3v1 には、非 ASCII 文字を確実に含めることはできません。cp1251 でエンコードされたバイトを ID3v1 タグに書き込むことはできますが、ロシア語ロケールの OS インストールでのみキリル文字としてレンダリングされ、すべてのアプリケーションでレンダリングされるわけではありません。

EyeD3 は内部で Unicode 文字列を処理し、任意latin1に ID3v1 タグのエンコーディングとして (別名 ISO-8859-1) を使用することを選択します。これは、Windows ボックスのデフォルトのロケール固有のエンコーディングではないため、おそらく適切な選択でlatin1はありません (西ヨーロッパの場合、実際cp1252には似ていますが同じではありません)。

ただし、このエンコーディングの選択のプロパティは、その中の各バイトが同じコード ポイント番号を持つ Unicode 文字にマップされることです。latin1としてエンコードされた場合、 以外のエンコーディングで選択された文字列のバイトエンコーディングになる文字を含む Unicode 文字列を作成することで、これを利用できますlatin1

album_name = u'Жить в твоей голове'
mangled_name = album_name.encode('cp1251').decode('latin1')
tag.setAlbum(mangled_name) # will encode as latin1, resulting in cp1251 bytes

これは恐ろしいハックであり、利益が疑わしく、ID3v1 を避けるべき理由の 1 つです。

于 2014-04-28T16:35:31.440 に答える