Awesome
AAXClean
Decrypts Audible's aax and aaxc files, without FFMpeg, to an m4b (lossless mp4). The input stream is not required to be seekable when decrypting. All file-level and stream-level metadata is preserved with lossless decryption. There is an option for reading/writing file-level mp4 metadata tags and adding different chapter information.
Nuget
Include the AAXClean NuGet package to your project.
Convert to Mp3
To convert audiobooks to Mp3, use AAXClean.Codecs.
Instantiation
AaxFile has two constructors:
public AaxFile(string fileName, FileAccess access = FileAccess.Read, FileShare share = FileShare.Read);
public AaxFile(Stream file);
public AaxFile(Stream file, long fileSize, bool additionalFixups = true)
The first two constructors use the third constructor. AAXClean needs to know the total file size length, so if it's instantiated with a stream that cannot seek, you must specify the file size. If the stream is a network stream, get the file size from the content-length header.
Usage:
var aaxFile = new AaxFile(File.OpenRead(@"C:\Source File.aax"));
Aaxc:
var audible_key = "0a0b0c0d0e0f1a1b1c1d1e1f2a2b2c2d";
var audible_iv = "2e2f3a3b3c3d3e3f4a4b4c4d4e4f5a5b";
aaxFile.SetDecryptionKey(audible_key, audible_iv);
Aax:
var activation_bytes = "0a1b2c3d";
aaxFile.SetDecryptionKey(activation_bytes);
Edit Metadata Tags:
aaxFile.AppleTags.Generes = "Adventure"
await aaxFile.SaveAsync();
Relocate the moov atom to the beginning of an mp4 file:
await Mp4File.RelocateMoovAsync(@"C:\audiobook.m4b");
Output:
await aaxFile.ConvertToMp4aAsync(File.OpenWrite(@"C:\Decrypted book.mb4"));
Multipart Conversion Example:
Note that the input stream needs to be seekable to call GetChapterInfo()
var chapters = await aaxFile.GetChapterInfoAsync();
//or aaxFile.GetChaptersFromMetadata();
var conversionResult = await aaxFile.ConvertToMultiMp4aAsync(chapters, NewSplit);
private static void NewSplit(NewSplitCallback newSplitCallback)
{
string dir = @"C:\book split\";
string fileName = newSplitCallback.Chapter.Title.Replace(":", "") + ".m4b";
newSplitCallback.OutputFile = File.OpenWrite(Path.Combine(dir, fileName));
}
Mp4Operation
All ConvertTo___Async()
methods return an Mp4Operation
. Mp4Operation
contains the conversion task that's created in a suspended state. The Mp4Operation
can be started by calling Start()
or by awaiting it, and it can be cancelled by calling CancelAsync()
. If you run the task by calling Start()
, you may access the running task at Mp4Operation.OperationTask
The Mp4Operation
also contains the operation's progress and has an event you may subscribe to for progress updates.
Successive Convert operations
Mp4File
is opened with a Stream
, and it reads from this input stream when converting or running GetChapterInfoAsync()
. If the Stream
is seekable, multiple conversion operations may be performed on the same Mp4File
instance. If the Stream
is not seekable, each new operation must be run on a new instance with the Stream.Position = 0
.
Concurrent Operations
Because Mp4File
only has one input stream, it does not support concurrency. However, you may run as many concurrent operation on one file as you have Stream
instances of that file. If the file source is a local filesystem file, this may be accomplished like so:
var aaxFile1 = new AaxFile(File.Open(@"C:\Source File.aax", FileMode.Open, FileAccess.Read, FileShare.Read));
var aaxFile2 = new AaxFile(File.Open(@"C:\Source File.aax", FileMode.Open, FileAccess.Read, FileShare.Read));
aaxFile1.SetDecryptionKey("0a0b0c0d0e0f1a1b1c1d1e1f2a2b2c2d", "2e2f3a3b3c3d3e3f4a4b4c4d4e4f5a5b");
aaxFile2.SetDecryptionKey("0a0b0c0d0e0f1a1b1c1d1e1f2a2b2c2d", "2e2f3a3b3c3d3e3f4a4b4c4d4e4f5a5b");
var mp3Operation = aaxFile1.ConvertToMp3Async(File.Open(@"HP_Zero.mp3", FileMode.OpenOrCreate, FileAccess.ReadWrite));
var mp4Operation = aaxFile2.ConvertToMp4aAsync(File.OpenWrite(@"HP_Zero_reencode.m4b"));
mp3Operation.ConversionProgressUpdate += ProgressReport;
mp4Operation.ConversionProgressUpdate += ProgressReport;
mp3Operation.Start();
mp4Operation.Start();
await Task.WhenAll(mp3Operation.OperationTask, mp4Operation.OperationTask);
Note that ConvertToMp3Async is only available with AAXClean.Codecs.