atldotnet: [Proposal] Add missing tags from audible aax files

The problem

When opening a .aax file, many fields wont be filled out. Instead, track.AdditionalFields has alot of unmapped properties. Lurking throught the decompiled sources of Audible/AAXSDKRT and some guesswork, i found out what most of the tags mean.

The resulting model of the sample aax file:

{
    "LONG_DESCRIPTION": "It\u0027s the perfect listen for your morning commute! In the time it takes you to get to work, you\u0027ll hear a digest of the day\u0027s top stories, prepared by the editorial staff of The New York Times. Each edition includes articles from the front page, as well as the paper\u0027s international, national, business, sports, and editorial sections.",
    "SHORT_TITLE": "NYT 07-10-2015 Audio Digest",
    "ASIN": "B00VM3HQAQ",
    "TYPE": "ADBL",
    "VERSION": "158766",
    "GUID": "A2U1HTLPI1WVTV",
    "AACR": "CR!CD9G72PRJD0454R03MXPF6R38HCC",
    "ProductId": "NB_NYTS_150710",
    "Publisher": "The New York Times",
    "Narrator": "The New York Times",
    "ReleaseDate": "10-JUL-2015",
    "PARENT_PRODUCT_ID": "NB_NYTS_000001",
    "PARENT_TITLE": "The New York Times Audio Digest",
    "Parent_ASIN": "B002V9ZD4G"

    "AUTHOR": "",
    "CATEGORY": "",
    "COPYRIGHT": "",
    "COVER_ART": "",
    "PRODUCT_ID": "",
    "PROVIDER": "",
    "PUBLISH_DATE": "",
    "SHORT_DESCRIPTION": "",
    "SUBCATEGORY": "",
    "TITLE": "",
    "USER_ALIAS": "",
    "PARENT_SHORT_TITLE": "",
    "TRACK_NUMBER": "",
    "SynchronizedImage": "",
    "Png": "",
}

Environment

  • ATL version (or git revision) that exhibits the issue: Main as of today

Code To Reproduce Issue

Sample file: https://github.com/inAudible-NG/audible-samples/blob/master/Audible_AAX_sample_62689101.aax My (very raw) approach: https://gist.github.com/JKamsker/d3333c78789b0e878ba4bea9e3d457ea This is only meant as inspiration for you to implement in this project. I’m not doing this myself, because i dont know your code style enought.

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 18 (17 by maintainers)

Commits related to this issue

Most upvoted comments

First things first, don’t forget these fields can already be written by the library, using Track.AdditionalFields

I know, ATL is very flexible. I’m promoting your library everywhere I can (e.g. Hackernews), because I think it is an awesome piece of software.

If your app is aimed at handling multiple tagging formats (e.g. ID3v2, native M4A tags, Vorbis tags…), adding these fields generically to IMetaDataIO will simplify your work app-side, allowing you to write less code to handle these formats properly.

I already extended Track class with properties to read and write my suggestions directly mapping them to AdditionalFields. Although there is a huge list of improvements in my mind, I did not understand your code well enough to really improve ATL with PRs - that might come later 😉

Secondly, I’m sensitive to your needs as an editor of audiobook software. Related fields that have equivalents in multiple tagging systems will be implemented generically. However, don’t ask me to implement every known metadata, using these huge mapping lists as specification. I really prefer to invest my time in something users actually need.

Since I am the author of m4b-tool, I absolutely understand and support this approach. Currently I’m trying to port m4b-tool to a C# app called tone heavily utilizing atldotnet. So tried to collect the 12 properties I really would need, that in my opinion could be added in a generic way in the list above.

However, the big mapping lists are not really helpful, because if a field is not 100% mappable, the mapping approaches differ depending on which library or software is used (Mp3tag, kid3, ffmpeg, VLC, ExifTool, MP4Box, mp4v2, etc.). I would love to have an RFC here, but although there are many best practises, there is no specification.

I thought over creating a JSON file with a searchable HTML-Document to look up the POSSIBLE mappings with notes about how specific implementations look like - so it would be possible to auto generate mapping code (no reason to write code that can be generated), or make it even configurable to be more flexible with an overridable method for MapAdditionalField:

public class MyTrack : Track
{
    // this is new
    public override string? MapAdditionalField(Format format, string key) => format.ID switch
    {
        // Format is not really appropriate, because it should be the TaggingFormat (id3v2, etc.), not the audio file format
        AudioDataIOFactory.CID_MP3 => MapMp3(key),
        AudioDataIOFactory.CID_MP4 => MapMp4(key),
        _ => null
    };
    
    private static string? MapMp3(string key) => key switch
    {
        nameof(AlbumSort)    => "TSOA",
        nameof(Group)    => "TIT1",
        _ => null,
    };
    
    private static string? MapMp4(string key) => key switch
    {
        nameof(AlbumSort)    => "soal",
        nameof(Group)    => "©grp",
        _ => null,
    };
}

But I tell you something… Instead of hacking my Ideas into comments of issues, I’ll think over this carefully and submit PRs after understanding your code better. If something is not to your liking, we discuss it in the PRs. Until then I would really appreciate the following 8 Properties in Track:

  • string SortAlbum
  • string SortAlbumArtist
  • string SortArtist
  • string SortTitle
  • string Group
  • string MovementName (or SeriesTitle)
  • string MovementIndex (or SeriesPart - string because of part 2.1, etc.)
  • string LongDescription

Already supported by ATL

  • TITLE
  • AUTHOR (= artist)
  • COPYRIGHT
  • COVER_ART
  • CATEGORY (= genre)
  • TRACK_NUMBER

Missing mappings; added for next release

  • LONG_DESCRIPTION
  • Publisher
  • ReleaseDate (= Publishing date)

New fields available through IMetaDataIO (for next release)

  • ProductId

No support (left in track.AdditionalFields as MP4/AAX is the only standard where that field actually exists)

  • Narrator
  • SHORT_TITLE
  • ASIN
  • TYPE
  • VERSION
  • GUID
  • AACR
  • PARENT_PRODUCT_ID
  • PARENT_TITLE
  • Parent_ASIN
  • PROVIDER
  • SHORT_DESCRIPTION
  • SUBCATEGORY
  • USER_ALIAS
  • PARENT_SHORT_TITLE
  • SynchronizedImage
  • Png

Available in today’s v4.12

I chose for the MP4 writer to ignore non-integer values while logging a warning.

I’m fine with that.

As you may expect, I don’t intend to create non-standard fallback fields.

Yeah and this is a good decision 😃

Anyway, you’ll soon have 8 new standard fields to play with smile

Cool, thank you very much. I have to check how this works together with my own implementation of 19 new fields by just mapping AdditionalFields in a dirty hack attempt… (see here)

I think there is some serious work to do updating atldotnet to benefit from these changes, but I love the fact that now I have 8 new native fields that are internally mapped and have official support.

Great work, as always, thank you very much.

Thanks for the quick reply. I chose for the MP4 writer to ignore non-integer values while logging a warning.

As you may expect, I don’t intend to create non-standard fallback fields.

Anyway, you’ll soon have 8 new standard fields to play with 😄