Images added by eyeD3 are not shown correctly by iTunes

Issue #27 invalid
Rolf Schäuble
created an issue

If I add an image (eyeD3 --add-image cover.jpg:OTHER filename.mp3; ID v2.3), then this image is not visible in iTunes (and in Finder). To be more precise, iTunes knows that there's an image (I can select it in the cover tab of the file info dialog), but it only shows as white square.

I've experimented a bit, and found out that eyeD3 creates an APIC frame with a length that it different from the one created by iTunes (and other tagging software that is compatible with iTunes).
Original file size: 143036 bytes
APIC created by eyeD3: 143053 bytes
APIC created by iTunes: 143050 bytes

Is this a known problem? If not, can I provide more information to help diagnosing this?

System info:
OSX 10.8.3
iTunes 11.0.2

Comments (14)

  1. Jason Penney

    I see the same issue. It seems to be related to the text_delim and encoding properties of the ImageFrame. I don't quite understand what _initEncoding is doing, but it seems if encoding is set to something when it's called it overrides it's value with one thing, and if it's not set yet, it overrides it with another thing. If you set encoding on the ImageFrame before the frame is rendered, the frame can be read correctly by iTunes.

  2. Travis Shirk repo owner

    I don't have iTunes or a mac/windows.. Can you send me these two files mentioned above for comparison? Running both files with 'eyeD3 -l debug` and capturing the output would be useful as well.

  3. Jason Penney

    Sure, I'll send some sample files. I did try modifying ImageFrame to set

    self.encoding = LATIN1_ENCODING

    in __init__, which worked in this case, but I didn't test beyond that. I'll attach that one as well.

  4. Travis Shirk repo owner

    This is a bug in iTunes IMO.. here's why....

    The default encoding for v2.3 tags is unicode utf16 (utf8 is not supported in v2.3). iTunes chooses latin1. The description portion of the image frame (APIC) is defined as:

    <text-per-encoding> \x00 (\x00)

    .. so, text bytes followed by a NULL byte.. but for two byte encodings like utf16 it is two null bytes. In each case the description is empty so it should be either 2 null bytes (eyeD3 utf16) or 1 null byte (iTunes latin1). But, when I encode the empty string to utf16 I get a BOM. Byte order mark, it says the endian'ness of the two bytes. With a hex editor here are the descriptions:

    eyeD3: \xff\xf3\x00\x00
    itunes: \x00
    And here is python adding a BOM:
    In [3]: u"".encode("utf16")
    Out[3]: '\xff\xfe'
    Here is python not adding a BOM because we use utf-16-be:
    In [7]: u"".encode("utf_16_be")
    Out[7]: ''

    So, as you found using latin1 makes iTunes happy, also utf16-be might as well, it is supported by ID3 v2.3:

    $ eyeD3 test.mp3 --encoding=utf16-be --to-v2.3

    or upgrade the version and use the nicely compact utf8:

    $ eyeD3 test.mp3 --encoding=utf8 --to-v2.4
  5. Rolf Schäuble reporter

    I just tested how iTunes reacts on different encodings, and thought I'd post the results here: The only encoding that makes iTunes show the cover images is latin1, utf16-be fails the same way utf-16 does.

    As I'm using eyeD3 via code, not the commandline, I'm just setting the encoding property of the image frame to latin1, and leave the encoding of all other tags alone.

    Maybe a commandline switch to do this as well would be useful (image-encoding)?

  6. Rolf Schäuble reporter

    What would you write into that section?

    The reasoning behind the command-line option is this: Using latin1 for all text fields is not desirable, as that creates internationalization problems. However, it seems that for images latin1 is required. So my idea is to make it possible to set different encodings for text tags and images.

    However, I have to admit that I haven't tested yet that this will work. That's something I'm planning on doing in the next 1-2 weeks.

  7. Jason Penney

    FYI: This is also an issue for Oppo Blu-Ray players. Setting the encoding to 'latin1' for ImageFrame (regardless of the encoding for the rest of the tag) fixes the issue.

  8. gruns

    If anyone stumbles across this issue, another workaround is to set the APIC frame's description to a non-empty string. Like

    from eyed3 import id3
    tag = id3.Tag()
    tag.version = (2, 3, 0) # ID3v2.3
    with open('front-cover.jpg') as fd:
      imageData =
    imageType = id3.frames.ImageFrame.FRONT_COVER
    frame = tag.images.set(imageType, imageData, 'image/jpeg')
    frame.description = u'whatever'

    iTunes will decode UTF-16 encoded APIC frames, but only if the description is non-empty. See

  9. Lucky Donald

    Even shorter:

    tag.images.set(imageType, imageData, 'image/jpeg', description=u" ")  # note the space

    Setting it directly, you don't need the the frame = (@gruns Also I don't know how secure that is...)

  10. Log in to comment