Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chapters not recognized by iTunes #444

Open
dskrad opened this issue May 31, 2020 · 6 comments
Open

Chapters not recognized by iTunes #444

dskrad opened this issue May 31, 2020 · 6 comments

Comments

@dskrad
Copy link

dskrad commented May 31, 2020

I am adding chapters to mp3 files. These chapters are visible on Android apps, but for some unknown reason the chapters are not seen in iTunes or Apple Podcasts app.

@SimplexPL
Copy link

SimplexPL commented Aug 31, 2020

Sorry for hijacking this issue, but I am trying to learn how to add chapters to mp3 files using eyeD3 CLI and I cannot find information about it in documentation. For example:

0 hits on "chapter" or "section" in the help text (also there is a typo "pupularity" :) )

eyeD3 --help
usage: eyeD3 [-h] [--version] [-l LEVEL[:LOGGER]] [--profile] [--pdb] [-r] [--exclude PATTERN] [--fs-encoding ENCODING] [-L] [-P NAME] [-C FILE] [--backup] [-Q] [--no-color] [--no-config] [-a STRING] [-A STRING] [-b STRING] [-t STRING]
             [-n NUM] [-N NUM] [--track-offset N] [--composer STRING] [--orig-artist STRING] [-d NUM] [-D NUM] [-G GENRE] [--non-std-genres] [-Y YEAR] [-c STRING] [--artist-city STRING] [--artist-state STRING] [--artist-country STRING]
             [--rename PATTERN] [-1] [-2] [--to-v1.1] [--to-v2.3] [--to-v2.4] [--release-date DATE] [--orig-release-date DATE] [--recording-date DATE] [--encoding-date DATE] [--tagging-date DATE] [--publisher STRING]
             [--play-count <+>N] [--bpm N] [--unique-file-id OWNER_ID:ID] [--add-comment COMMENT[:DESCRIPTION[:LANG]]] [--remove-comment DESCRIPTION[:LANG]] [--remove-all-comments] [--add-lyrics LYRICS_FILE[:DESCRIPTION[:LANG]]]
             [--remove-lyrics DESCRIPTION[:LANG]] [--remove-all-lyrics] [--text-frame FID:TEXT] [--user-text-frame DESC:TEXT] [--url-frame FID:URL] [--user-url-frame DESCRIPTION:URL] [--add-image IMG_PATH:TYPE[:DESCRIPTION]]
             [--remove-image DESCRIPTION] [--remove-all-images] [--write-images DIR] [--add-object OBJ_PATH:MIME-TYPE[:DESCRIPTION[:FILENAME]]] [--remove-object DESCRIPTION] [--write-objects DIR] [--remove-all-objects]
             [--add-popularity EMAIL:RATING[:PLAY_COUNT]] [--remove-popularity EMAIL] [--remove-v1] [--remove-v2] [--remove-all] [--remove-frame FID] [--max-padding NUM_BYTES] [--no-max-padding] [--encoding latin1|utf8|utf16|utf16-be]
             [--force-update] [-v] [--preserve-file-times]
             [PATH [PATH ...]]

positional arguments:
  PATH                  Files or directory paths

optional arguments:
  -h, --help            show this help message and exit
  --version             Display version information and exit
  -r, --recursive       Recurse into subdirectories.
  --exclude PATTERN     A regular expression for path exclusion. May be specified multiple times.
  --fs-encoding ENCODING
                        Use the specified file system encoding for filenames. Default as it was detected is 'utf-8' but this option is still useful when reading from mounted file systems.
  -L, --plugins         List all available plugins
  -P NAME, --plugin NAME
                        Specify which plugin to use. The default is 'classic'
  -C FILE, --config FILE
                        Supply a configuration file. The default is '${HOME}/.config/eyeD3/config.ini', although even that is optional.
  --backup              Plugins should honor this option such that a backup is made of any file modified. The backup is made in same directory with a '.orig' extension added.
  -Q, --quiet           A hint to plugins to output less.
  --no-color            Suppress color codes in console output. This will happen automatically if the output is not a TTY (e.g. when redirecting to a file)
  --no-config           Do not load the default user config '${HOME}/.config/eyeD3/config.ini'. The -c/--config options are still honored if present.

Debugging:
  -l LEVEL[:LOGGER], --log-level LEVEL[:LOGGER]
                        Set a log level. This option may be specified multiple times. If a logger name is specified than the level applies only to that logger, otherwise the level is set on the top-level logger. Acceptable levels are
                        'debug', 'verbose', 'info', 'warning', 'error', 'critical'.
  --profile             Run using python profiler.
  --pdb                 Drop into 'pdb' when errors occur.

Plugin options:
  Classic eyeD3 interface for viewing and editing tags.

  All PATH arguments are parsed and displayed. Directory paths are searched
  recursively. Any editing options (--artist, --title) are applied to each file
  read.

  All date options (-Y, --release-year excepted) follow ISO 8601 format. This is
  ``yyyy-mm-ddThh:mm:ss``. The year is required, and each component thereafter is
  optional. For example, 2012-03 is valid, 2012--12 is not.

  -a STRING, --artist STRING
                        Set the artist name.
  -A STRING, --album STRING
                        Set the album name.
  -b STRING, --album-artist STRING
                        Set the album artist name. 'Various Artists', for example. Another example is collaborations when the track artist might be 'Eminem featuring Proof' the album artist would be 'Eminem'.
  -t STRING, --title STRING
                        Set the track title.
  -n NUM, --track NUM   Set the track number. Use 0 to clear.
  -N NUM, --track-total NUM
                        Set total number of tracks. Use 0 to clear.
  --track-offset N      Increment/decrement the track number by [-]N. This option is applied after --track=N is set.
  --composer STRING     Set the composer's name.
  --orig-artist STRING  Set the orignal artist's name. For example, a cover song can include the orignal author of the track.
  -d NUM, --disc-num NUM
                        Set the disc number. Use 0 to clear.
  -D NUM, --disc-total NUM
                        Set total number of discs in set. Use 0 to clear.
  -G GENRE, --genre GENRE
                        Set the genre. If the argument is a standard ID3 genre name or number both will be set. Otherwise, any string can be used. Run 'eyeD3 --plugin=genres' for a list of standard ID3 genre names/ids.
  --non-std-genres      Disables certain ID3 genre standards, such as the mapping of numeric value to genre names. For example, genre=1 is taken literally, not mapped to 'Classic Rock'.
  -Y YEAR, --release-year YEAR
                        Set the year the track was released. Use the date options for more precise values or dates other than release.
  -c STRING, --comment STRING
                        Set a comment. In ID3 tags this is the comment with an empty description. See --add-comment to add multiple comment frames.
  --artist-city STRING  The artist's city of origin. Stored as a user text frame `eyeD3#artist_origin`
  --artist-state STRING
                        The artist's state of origin. Stored as a user text frame `eyeD3#artist_origin`
  --artist-country STRING
                        The artist's country of origin. Stored as a user text frame `eyeD3#artist_origin`
  --rename PATTERN      Rename file (the extension is not affected) based on data in the tag using substitution variables: $album, $album_artist, $artist, $best_date, $best_date:prefer_recording, $best_date:prefer_recording:year,
                        $best_date:prefer_release, $best_date:prefer_release:year, $best_date:year, $disc:num, $disc:total, $file, $file:ext, $original_release_date, $original_release_date:year, $recording_date, $recording_date:year,
                        $release_date, $release_date:year, $title, $track:num, $track:total

ID3 options:
  -1, --v1              Only read and write ID3 v1.x tags. By default, v1.x tags are only read or written if there is not a v2 tag in the file.
  -2, --v2              Only read/write ID3 v2.x tags. This is the default unless the file only contains a v1 tag.
  --to-v1.1             Convert the file's tag to ID3 v1.1 (Or 1.0 if there is no track number)
  --to-v2.3             Convert the file's tag to ID3 v2.3
  --to-v2.4             Convert the file's tag to ID3 v2.4
  --release-date DATE   Set the date the track/album was released
  --orig-release-date DATE
                        Set the original date the track/album was released
  --recording-date DATE
                        Set the date the track/album was recorded
  --encoding-date DATE  Set the date the file was encoded
  --tagging-date DATE   Set the date the file was tagged
  --publisher STRING    Set the publisher/label name
  --play-count <+>N     Set the number of times played counter. If the argument value begins with '+' the tag's play count is incremented by N, otherwise the value is set to exactly N.
  --bpm N               Set the beats per minute value.
  --unique-file-id OWNER_ID:ID
                        Add a unique file ID frame. If the ID arg is empty the frame is removed. An OWNER_ID is required. The ID may be no more than 64 bytes.
  --add-comment COMMENT[:DESCRIPTION[:LANG]]
                        Add or replace a comment. There may be more than one comment in a tag, as long as the DESCRIPTION and LANG values are unique. The default DESCRIPTION is '' and the default language code is 'eng'.
  --remove-comment DESCRIPTION[:LANG]
                        Remove comment matching DESCRIPTION and LANG. The default language code is 'eng'.
  --remove-all-comments
                        Remove all comments from the tag.
  --add-lyrics LYRICS_FILE[:DESCRIPTION[:LANG]]
                        Add or replace a lyrics. There may be more than one set of lyrics in a tag, as long as the DESCRIPTION and LANG values are unique. The default DESCRIPTION is '' and the default language code is 'eng'.
  --remove-lyrics DESCRIPTION[:LANG]
                        Remove lyrics matching DESCRIPTION and LANG. The default language code is 'eng'.
  --remove-all-lyrics   Remove all lyrics from the tag.
  --text-frame FID:TEXT
                        Set the value of a text frame. To remove the frame, specify an empty value. For example, --text-frame='TDRC:'
  --user-text-frame DESC:TEXT
                        Set the value of a user text frame (i.e., TXXX). To remove the frame, specify an empty value. e.g., --user-text-frame='SomeDesc:'
  --url-frame FID:URL   Set the value of a URL frame. To remove the frame, specify an empty value. e.g., --url-frame='WCOM:'
  --user-url-frame DESCRIPTION:URL
                        Set the value of a user URL frame (i.e., WXXX). To remove the frame, specify an empty value. e.g., --user-url-frame='SomeDesc:'
  --add-image IMG_PATH:TYPE[:DESCRIPTION]
                        Add or replace an image. There may be more than one image in a tag, as long as the DESCRIPTION values are unique. The default DESCRIPTION is ''. If PATH begins with 'http[s]://' then it is interpreted as a URL
                        instead of a file containing image data. The TYPE must be one of the following: OTHER, ICON, OTHER_ICON, FRONT_COVER, BACK_COVER, LEAFLET, MEDIA, LEAD_ARTIST, ARTIST, CONDUCTOR, BAND, COMPOSER, LYRICIST,
                        RECORDING_LOCATION, DURING_RECORDING, DURING_PERFORMANCE, VIDEO, BRIGHT_COLORED_FISH, ILLUSTRATION, BAND_LOGO, PUBLISHER_LOGO.
  --remove-image DESCRIPTION
                        Remove image matching DESCRIPTION.
  --remove-all-images   Remove all images from the tag
  --write-images DIR    Causes all attached images (APIC frames) to be written to the specified directory.
  --add-object OBJ_PATH:MIME-TYPE[:DESCRIPTION[:FILENAME]]
                        Add or replace an object. There may be more than one object in a tag, as long as the DESCRIPTION values are unique. The default DESCRIPTION is ''.
  --remove-object DESCRIPTION
                        Remove object matching DESCRIPTION.
  --write-objects DIR   Causes all attached objects (GEOB frames) to be written to the specified directory.
  --remove-all-objects  Remove all objects from the tag
  --add-popularity EMAIL:RATING[:PLAY_COUNT]
                        Adds a pupularity metric. There may be multiples popularity values, but each must have a unique email address component. The rating is a number between 0 (worst) and 255 (best). The play count is optional, and
                        defaults to 0, since there is already a dedicated play count frame.
  --remove-popularity EMAIL
                        Removes the popularity frame with the specified email key.
  --remove-v1           Remove ID3 v1.x tag.
  --remove-v2           Remove ID3 v2.x tag.
  --remove-all          Remove ID3 v1.x and v2.x tags.
  --remove-frame FID    Remove all frames with the given ID. This option may be specified multiple times.
  --max-padding NUM_BYTES
                        Shrink file if tag padding (unused space) exceeds the given number of bytes. (Useful e.g. after removal of large cover art.) Default is 64 KiB, file will be rewritten with default padding (1 KiB) or max padding,
                        whichever is smaller.
  --no-max-padding      Disable --max-padding altogether.
  --encoding latin1|utf8|utf16|utf16-be
                        Set the encoding that is used for all text frames. This option is only applied if the tag is updated as the result of an edit option (e.g. --artist, --title, etc.) or --force-update is specified.

Misc options:
  --force-update        Rewrite the tag despite there being no edit options.
  -v, --verbose         Show all available tag data
  --preserve-file-times
                        When writing, do not update file modification times.

https://eyed3.readthedocs.io/
1 hit on Chapter, but I do not how to use it in the command line:
https://eyed3.readthedocs.io/en/latest/eyed3.id3.html?highlight=chapter#eyed3.id3.frames.ChapterFrame

@odie5533
Copy link

odie5533 commented Feb 11, 2021

Sorry for hijacking this issue, but I am trying to learn how to add chapters to mp3 files using eyeD3 CLI and I cannot find information about it in documentation.

You can't add them with the CLI. There's issue #7 to add the feature.

You can add them using Python:

import eyed3

t = eyed3.load("mypodcast.mp3").tag
# b"ch1" must be unique for each chapter
# Create a chapter starting on 10 seconds ending on 50 seconds
ch1 = t.chapters.set(b"ch1", (10000, 50000))
ch1.title = "Chapter 1"
t.save()

@odie5533
Copy link

odie5533 commented Mar 1, 2021

@dskrad I'm using eyeD3 to add ID3 chapters to mp3 files with podcast episodes, and we got a very similar problem with Apple Podcasts on MacOS and iOS - for some episodes chapters will show normally, and for others won't show at all.

After scratching my head for a little while, I found that if you are using ID3v2.4 tag format, Apple Podcasts will break on chapters with titles (TIT2 sub-frames) containing more than 51 utf-8 symbols in them.

You could try switching the chapter title TextFrame encoding:

from eyed3.id3 import UTF_16_ENCODING

added_chapter = t.chapters.set(b"ch1", (10000, 50000))
added_chapter.encoding = UTF_16_ENCODING
added_chapter.title = "Chapter 1"

@q210
Copy link

q210 commented Mar 1, 2021

Hm, strange, my previous comment (the one that @odie5533 answered to) disappeared somewhere. Recreating it here for posterity:

@dskrad I'm using eyeD3 to add ID3 chapters to mp3 files with podcast episodes, and we got a very similar problem with Apple Podcasts on MacOS and iOS - for some episodes chapters will show normally, and for others won't show at all.

After scratching my head for a little while, I found that if you are using ID3v2.4 tag format, Apple Podcasts will break on chapters with titles (TIT2 sub-frames) containing more than 51 utf-8 symbols in them.

I was able to circumvent the problem by switching to older ID3v2.3 tag format - after using it Podcasts app on MacOS and iOS started showing the same chapters without any problems.

P.S. @nicfit thank you very very much for your work on this library! It saved me a lot of time and nerves in tasks involving ID3 tags.

@q210
Copy link

q210 commented Mar 1, 2021

@odie5533 thanks for the advice! Tried to test using ID3v2.4 chapter tags with UTF_16_ENCODING today, but sadly Apple Podcasts still will not show them if any one of them had more than 51 symbol. Luckily switching to ID3v2.3 format works for me, so no big deal.

Just to be thorough, here's how I tested things:

  1. Download to my local Mac any podcast episode from the cloud using Apple Podcasts app.
  2. Close Podcasts app
  3. Copy podcast file from ~/Library/Group Containers/243LU875E5.groups.com.apple.podcasts/Library/Cache/<episode mp3 file> ( will have UUID instead of a proper episode name, so you will have to find what you downloaded by file creation date) to the working directory
  4. Set ID3 TOC and chapter tags to the file
  5. Copy file back to ~/Library/Group Containers/243LU875E5.groups.com.apple.podcasts/Library/Cache/<episode mp3 file>
  6. Open Podcasts app to check if it reads chapters on the downloaded episode

@nicfit nicfit removed the help wanted label Mar 2, 2021
@nicfit
Copy link
Owner

nicfit commented Mar 5, 2021

Chapter enhancements here: #531

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants