Audiobook chapters to .cue and .nfo files, and back

Background: I'm not actually familiar with the scripting used for Mp3Tag actions/exports/etc. I've been able to monkey-see/monkey-do a bit just based on common sense, but a lot of the scripting is beyond what I can understand just looking at the code, particularly when RegEx is thrown into the mix. I have, however, taught myself Swift back when I was working on my Mac, so I'm not entirely clueless. I just don't know this particular language.

Dilemma: I have usually been a Mac user, but lately I've needed to work on my PC while I'm organizing my audiobook library, which I hand-verify the chapters and metadata for because I'm just OCD like that.

It's a time-consuming process, particularly as my library grows.

The Goal: I want to keep .nfo and .cue files as a backup plan (or really any text equivalent, .nfo and .cue just are handily specific.)

That way, if something happens to my external drive (or I pull the same boneheaded move twice and accidentally delete the wrong directory that happens to be too big for the Recycle Bin--oops) and I have to re-download my audiobook library from the Zon and elsewhere, it will be quicker to create a convert script to import the metadata from an .nfo file, and a .cue file for the chaptering, than to do it all again.

Exporting the metadata is fairly straightforward, and I imagine importing it will be too. It's working with the chapters that is tripping me up, because I don't know how Mp3Tag reads embedded chapters (if it does at all.)

Ultimately, I need the chaptering data exported (and importable) either as a .cue or in one of the following formats, which are also commonly used (if only I could find an app that gave the option to use all three, but it's either .cue or these):

00:00:00.000 Opening Credits
00:00:16.000 Prologue
00:22:00.000 Chapter 1


CHAPTER01NAME=Opening Credits 
CHAPTER03NAME=Chapter 1 

Ultimately, the formatting is trivial. Once I have the data, I can export it in whatever format I want. It's getting the embedded chapter data out of the file that poses a challenge.

What I've Tried: @pone has some amazing scripts that ALMOST do what I want to do with regard to exporting a cue sheet, but they appear to be reliant upon an initial tracklist import from Discogs, rather that exporting the chapters from the file's metadata (either The scripting is WAY over my head, but when it generated what was supposed to be the tracklist, it didn't bear any resemblance to any tracklist I've seen. Which would make sense, because why would audiobook data be on Discogs?

The Process: I'm using Seanap's Plex Audiobook Guide--particularly the export, action, and source files for Mp3Tag--to flush out my metadata, and then I verify the results by looking it over, and make tweaks where necessary, before considering it finalized.

For my .nfo files, I'm using a highly-specified export based on the simple NFO design by @dano, attached here:
NFO.mte (2.2 KB)
As you can see at the end, I've got a listing of the chapters at the bottom, mostly just because I'm experimenting with what I need to do to generate a chaptering data file before I start trying to write that script. Supposedly, there is a %subsong% option for files with embedded chapters that would facilitate this, but it doesn't seem to be working for me. But I digress....

With "Chapters are listed as separate files" checked, I can get a list of the chapters and the duration of each chapter, which I can then export using:

$loop($num(%discnumber%,3)$num(%track%,4)%_filename_ext%)$num(%track%,2). %title%$repeat( ,$sub(57,$len(%title%)))   [$replace(%_length%,_,:)]

However, that isn't really what I need. I need the starting timestamp of each chapter, not the duration. If the starting timestamp can't be parsed (either from the chpl atom in Nero chaptering, or the sample table atoms on the chapter text track for Quicktime chaptering) it would have to be calculated by getting the sum of the durations of all the preceeding chapters.

I feel like I'm close on this, but I'm missing something and my lack of understanding about this type of scripting and what data MP3Tag has available for export is preventing me from finding the solution. I've actually written pure Swift libraries for parsing and editing metadata and chapter data in MP4 and ID3 tagged files, so I'm familiar with how metadata WORKS, I just don't have the same level of understanding of the tools I'm using now.

Okay, I suspect my initial post was too wordy. Maybe I need to break it down into smaller chunks.

Mostly my issue is with creating a cue file, so I'll focus on that.

Since Mp3Tag uses Nero chaptering, the data for track/chapter start times should be right there in the chpl atom. Admittedly, it will be in...1/100th of a nanosecond, I believe is the unit? But I can work with that.

So my first question there a way to get to this data in Mp3Tag? I know I can product chapter durations simply by reading the length tag, but for a cue, I need either the chapter start time, or a way to calculate start times from the durations.

The search words "create cue" yield e.g. this thread:

I read that thread, and the ones it linked to, and several others as well.

What they're trying to do is a different animal to what I'm trying to do. The OP of the thread you linked has a list of the start times and chapters already. They don't specify how they have the information, whether it's from an embedded cue or an external tracklist of some kind, or what, so it's not clear if they're looking to actually extract the .cue from the audio file or if they want to create a .cue from some listing of the information that is external to the audio file.

The two threads referenced in that thread deal with correcting cues, rather than exporting them. The first of the two does have a comment that says that Mp3Tag can read cues (presumably embedded cues, though for all I know, you can open a cue with MP3Tag and as long as the filename of the audio file is correct, what you will get is the same result as opening the audio file directly, just listed as tracks whereas the original might be without track markers.)

The second one...honestly I'm not even sure what they're asking, but it isn't anywhere near my wheelhouse.

All the data needed to create a .cue file is in the chpl atom (Nero chapters), which Mp3Tag both reads and creates. I know this because I took a file that that I first verified only had Quicktime chapters--which don't involve a chpl atom--and loaded it into Mp3tag, then upon saving it, I looked back over the atom structure again and there was a chpl atom where there hadn't been one before. Ergo, Mp3Tag can and does generate a chpl atom if it has the chapter data available from Quicktime chaptering, or a tracklist, or something.

If Mp3Tag can create a chpl atom, then it either already knows the starting timestamp for each track/chapter, or it calculates the timestamp from the sum of the durations of all the preceeding tracks.

I suspect it's the latter, because the atoms responsible for Quicktime chaptering store track/chapter information as durations, rather than as starting timestamps. (I know this because I've written a library to parse MP4 chapter and metadata, so I'm intimately familiar with how these atoms work.)

Without getting too technical, in a chpl atom, chapter data is stored as a "table" that can be visualized like this:

timestamp (64 bit) | byte count of title string | title string
timestamp (64 bit) | byte count of title string | title string
timestamp (64 bit) | byte count of title string | title string

By knowing that the timestamps are 64-bt and the byte-count of the title strings, you know where one entry in the table ends and the next begins.

The timestamp in the table is (iirc, it's been a couple years since I wrote my libraries) in 1/100th of a nanosecond units. Knowing this makes it possible to calculate the timestamp a cue file would need in HH:mm:ss.zzz format (and again, I know this because I've done it. I just did it in Swift, and that's not what we're working with here.)

All of that is basically a long way to say that what I'm asking--which I've not found asked elsewhere on these forums despite having searched for weeks--is whether there is some way to extract this timestamp data, which Mp3Tag clearly already has because it can and does generate chpl atoms.

Alternatively, since I'm not familiar with the scripting language used by Mp3Tag, if there is a way to calculate those timestamps from the duration of each track (which I also have available, because that I can export easily) then that would work as well, but not as precisely, because the exported durations are only in seconds.

Doing so would require some way to store the duration of track 1 (which I believe should be accessible using some combination of %counter% and %length_seconds% (again, this will not be terribly precise) which then we would use to calculate the starting time of track 2, which would then be added to the duration of track 2 to get the starting time of track 3, and so forth. This would also require being able to specify which track I want the %counter% for, even if the current track isn't the one I need the data from.

See the documentation on Scripting:

There are a number of integer mathematic functions like $DIV(), $MOD(), $MUL() and $ADD() with which you probably can do some adding up of durations.
You would have to think of a way to get the minutes and seconds and a possible overflow right, though.

What I still don't understand: if you see the files in MP3tag and you see the chapters in MP3tag - can't you generate an export of this which shows the duration of each track and then import that data to e.g. Excel where you do the rest of the calculations (because I think it may be easier there)?

Yes, there are any number of ways to accomplish this external to Mp3Tag, and some of them wouldn't even take that long. I can think of five or six apps off the top of my head that either export .cue files, or export a text file with chapter timestamps and titles, which I could then use instead of a .cue file, or format into a .cue file.

However, I'm trying to actually learn the scripting (as well as get better at using regex because that is just one concept that goes completely over my head) as a sort of learning project. I've looked over all the documentation on scripting functions, but what the documentation lacks is many examples of how to implement them for more complex functionality--like, say, calculating time-stamps from durations.

I'm at the monkey-see, monkey-do stage of trying to mimic what I see others doing in their scripts and hoping I get it right. And the samples I've downloaded from the forums (like @pone's scripts for generating a .cue from an imported Discogs tracklist) are just on a level of sophistication I simply can't make any sense of yet, especially since they involve a great deal of regex.

(also, I'm just OCD enough to want to be able to export it all--edited .m4b, .nfo, .cue, and whatever else--in a single function rather than jumping from app to app to get it done.)

There is this forum for this purpose - you cannot possibly cover all the usecases in a help (and usually, the documentation is not read at all).
As the cases covered in threads in this forum, I suspect that your case is a rather special one and I fear that there is no way around but to do it from scratch.

I agree. That is why I’m asking for input on how to get where I need to go. Because I just don’t know what Mp3Tag has going on under the hood, or what I can tease out of it as I learn. I’d like to know it’s at least possible before I invest too much time in it.