From f2d475a9b05fd77287d31228ae80bfe548f8f3a9 Mon Sep 17 00:00:00 2001 From: Mbucari Date: Mon, 3 Jul 2023 13:25:47 -0600 Subject: [PATCH] Add audiobookshelf tags for m4b and mp3 Fix the following tag fields so they are correctly parsed and displayed in audiobookshelf: Language Publisher Series name and number ASIN --- Source/AaxDecrypter/AaxDecrypter.csproj | 2 +- .../AaxDecrypter/AaxcDownloadConvertBase.cs | 28 +++++++++++++++++++ Source/AaxDecrypter/IDownloadOptions.cs | 9 +++++- Source/AaxDecrypter/MpegUtil.cs | 17 +++++++++++ Source/FileLiberator/DownloadOptions.cs | 7 +++++ 5 files changed, 61 insertions(+), 2 deletions(-) diff --git a/Source/AaxDecrypter/AaxDecrypter.csproj b/Source/AaxDecrypter/AaxDecrypter.csproj index 5e65d72d..c065bf6d 100644 --- a/Source/AaxDecrypter/AaxDecrypter.csproj +++ b/Source/AaxDecrypter/AaxDecrypter.csproj @@ -13,7 +13,7 @@ - + diff --git a/Source/AaxDecrypter/AaxcDownloadConvertBase.cs b/Source/AaxDecrypter/AaxcDownloadConvertBase.cs index 3c10db4c..e8e0423f 100644 --- a/Source/AaxDecrypter/AaxcDownloadConvertBase.cs +++ b/Source/AaxDecrypter/AaxcDownloadConvertBase.cs @@ -51,6 +51,34 @@ namespace AaxDecrypter if (!string.IsNullOrWhiteSpace(AaxFile.AppleTags.Copyright)) AaxFile.AppleTags.Copyright = AaxFile.AppleTags.Copyright.Replace("(P)", "℗").Replace("©", "©"); + + //Add audiobook shelf tags + //https://github.com/advplyr/audiobookshelf/issues/1794#issuecomment-1565050213 + const string tagDomain = "com.pilabor.tone"; + + AaxFile.AppleTags.Title = DownloadOptions.Title; + + if (DownloadOptions.Subtitle is string subtitle) + AaxFile.AppleTags.AppleListBox.EditOrAddFreeformTag(tagDomain, "SUBTITLE", subtitle); + + if (DownloadOptions.Publisher is string publisher) + AaxFile.AppleTags.AppleListBox.EditOrAddFreeformTag(tagDomain, "PUBLISHER", publisher); + + if (DownloadOptions.Language is string language) + AaxFile.AppleTags.AppleListBox.EditOrAddFreeformTag(tagDomain, "LANGUAGE", language); + + if (DownloadOptions.AudibleProductId is string asin) + { + AaxFile.AppleTags.Asin = asin; + AaxFile.AppleTags.AppleListBox.EditOrAddTag("asin", asin); + AaxFile.AppleTags.AppleListBox.EditOrAddFreeformTag(tagDomain, "AUDIBLE_ASIN", asin); + } + + if (DownloadOptions.SeriesName is string series) + AaxFile.AppleTags.AppleListBox.EditOrAddFreeformTag(tagDomain, "SERIES", series); + + if (DownloadOptions.SeriesNumber is float part) + AaxFile.AppleTags.AppleListBox.EditOrAddFreeformTag(tagDomain, "PART", part.ToString()); } //Finishing configuring lame encoder. diff --git a/Source/AaxDecrypter/IDownloadOptions.cs b/Source/AaxDecrypter/IDownloadOptions.cs index ccbb3808..6edca962 100644 --- a/Source/AaxDecrypter/IDownloadOptions.cs +++ b/Source/AaxDecrypter/IDownloadOptions.cs @@ -21,7 +21,14 @@ namespace AaxDecrypter long DownloadSpeedBps { get; } ChapterInfo ChapterInfo { get; } bool FixupFile { get; } - NAudio.Lame.LameConfig LameConfig { get; } + string AudibleProductId { get; } + string Title { get; } + string Subtitle { get; } + string Publisher { get; } + string Language { get; } + string SeriesName { get; } + float? SeriesNumber { get; } + NAudio.Lame.LameConfig LameConfig { get; } bool Downsample { get; } bool MatchSourceBitrate { get; } bool MoveMoovToBeginning { get; } diff --git a/Source/AaxDecrypter/MpegUtil.cs b/Source/AaxDecrypter/MpegUtil.cs index d7ab9c37..f863e963 100644 --- a/Source/AaxDecrypter/MpegUtil.cs +++ b/Source/AaxDecrypter/MpegUtil.cs @@ -1,4 +1,5 @@ using AAXClean; +using AAXClean.Codecs; using NAudio.Lame; using System; @@ -6,6 +7,7 @@ namespace AaxDecrypter { public static class MpegUtil { + private const string TagDomain = "com.pilabor.tone"; public static void ConfigureLameOptions(Mp4File mp4File, LameConfig lameConfig, bool downsample, bool matchSourceBitrate) { double bitrateMultiple = 1; @@ -36,6 +38,21 @@ namespace AaxDecrypter else if (lameConfig.VBR == VBRMode.ABR) lameConfig.ABRRateKbps = kbps; } + + //Setup metadata tags + lameConfig.ID3 = mp4File.AppleTags.ToIDTags(); + + if (mp4File.AppleTags.AppleListBox.GetFreeformTagString(TagDomain, "SUBTITLE") is string subtitle) + lameConfig.ID3.Subtitle = subtitle; + + if (mp4File.AppleTags.AppleListBox.GetFreeformTagString(TagDomain, "LANGUAGE") is string lang) + lameConfig.ID3.UserDefinedText.Add("LANGUAGE", lang); + + if (mp4File.AppleTags.AppleListBox.GetFreeformTagString(TagDomain, "SERIES") is string series) + lameConfig.ID3.UserDefinedText.Add("SERIES", series); + + if (mp4File.AppleTags.AppleListBox.GetFreeformTagString(TagDomain, "PART") is string part) + lameConfig.ID3.UserDefinedText.Add("PART", part); } } } diff --git a/Source/FileLiberator/DownloadOptions.cs b/Source/FileLiberator/DownloadOptions.cs index 7b46170d..76b80967 100644 --- a/Source/FileLiberator/DownloadOptions.cs +++ b/Source/FileLiberator/DownloadOptions.cs @@ -21,6 +21,13 @@ namespace FileLiberator public TimeSpan RuntimeLength { get; init; } public OutputFormat OutputFormat { get; init; } public ChapterInfo ChapterInfo { get; init; } + public string Title => LibraryBook.Book.Title; + public string Subtitle => LibraryBook.Book.Subtitle; + public string Publisher => LibraryBook.Book.Publisher; + public string Language => LibraryBook.Book.Language; + public string AudibleProductId => LibraryBookDto.AudibleProductId; + public string SeriesName => LibraryBookDto.SeriesName; + public float? SeriesNumber => LibraryBookDto.SeriesNumber; public NAudio.Lame.LameConfig LameConfig { get; init; } public string UserAgent => AudibleApi.Resources.Download_User_Agent; public bool TrimOutputToChapterLength => config.AllowLibationFixup && config.StripAudibleBrandAudio;