r15ch13
7/1/2016 - 12:49 AM

Convert aax to m4a

Convert aax to m4a

Convert aax to m4a

Converts Audible aax audiobooks to m4a while keeping chapters and the cover image intact. The cover is added as a looped image so it is shown while playing on Plex Media Server

Usage

> convert-aax-to-m4a.cmd <filename> <device> <debug>

  • <filename>: is your aax file. duh!
  • <device>: is the number of the registry entry in HKLM\SOFTWARE\WOW6432Node\Audible\SWGIDMAP.
  • <debug>: add debug as 3rd parameter to get more ffmpeg output

Example:

> convert-aax-to-m4a.cmd AgenttotheStars_ep6_A1SZN9UBXNTEA2.aax

Using Device 0 (Activation Bytes: 74FF0506)

Reading audiobook information ...
John Scalzi - Agent to the Stars (Unabridged) [2010] (Duration: 8h44m)

Converting to m4a ...
size=  246321kB time=08:49:45.00 bitrate=  63.5kbits/s speed=7.09e+003x

Adding looped cover image audiobook
frame=31844 fps=645 q=17.0 Lsize=  256060kB time=08:49:45.00 bitrate=  66.0kbits/s speed= 644x

Done!

Requirements

  • Installed Audible Download Manager
  • ffmpeg for converting
  • jq for extracting information

How it works

  • Extract cover image:
    • ffmpeg -y -i audiobook.aax cover.png
  • Decrypted and convert to m4a:
    • ffmpeg -y -activation_bytes 1CEB00DA -i audiobook.aax -c:a copy -vn audiobook-tmp.m4a
  • Add looped cover image:
    • ffmpeg -y -r 1 -loop 1 -i cover.png -i audiobook-tmp.m4a -c:a copy -shortest audiobook.m4a

License

The MIT License (MIT)

@echo off
setlocal enableextensions
chcp 65001
set input=%1
set device=%2
set loglevel=quiet
for %%i in ("%~f1") do set dirname=%%~dpi
for %%i in ("%~f1") do set extension=%%~xi

set tempfile=%dirname%%RANDOM%-temp.m4a
set tempimage=%dirname%%RANDOM%-temp.png

if /i "%1" EQU "" (echo Usage: %0 ^<filename^> ^<device^> & goto :eof)
if /i "%extension%" NEQ ".aax" (echo Not an AAX file! & goto :eof)
if /i "%2" EQU "" set device=0
if /i "%3" EQU "debug" set loglevel=info
where /q ffmpeg || (echo Please install ffmpeg! & goto :eof)
where /q jq || (echo Please install jq! & goto :eof)

echo.
rem http://stackoverflow.com/a/12730022/2710739
for /f "tokens=2*" %%a in ('reg.exe query "HKLM\SOFTWARE\WOW6432Node\Audible\SWGIDMAP" /v "%device%"') do set bytes=%%b
set activation_bytes=%bytes:~6,2%%bytes:~4,2%%bytes:~2,2%%bytes:~0,2%
if /i "%bytes%" EQU "" echo Device %device% does not exist! & goto :eof
if /i "%activation_bytes%" EQU "FFFFFFFF" echo Device %device% is not activated! & goto :eof
echo Using Device %device% (Activation Bytes: %activation_bytes%)

echo.
echo Reading audiobook information ...
for /f "tokens=*" %%i in ('ffprobe "%input%" -v %loglevel% -print_format json -show_format ^| jq -r ".format.tags.artist"') do set artist=%%i
for /f "tokens=*" %%i in ('ffprobe "%input%" -v %loglevel% -print_format json -show_format ^| jq -r ".format.tags.title"') do set title=%%i
for /f "tokens=*" %%i in ('ffprobe "%input%" -v %loglevel% -print_format json -show_format ^| jq -r ".format.tags.date"') do set year=%%i
for /f "tokens=*" %%i in ('ffprobe "%input%" -v %loglevel% -print_format json -show_format ^| jq -r """\(.format.duration|(tonumber/60/60)|floor)h\(.format.duration|(tonumber%%60))m"""') do set duration=%%i
set filename=%artist% - %title% [%year%].m4a
set filename=%filename:\=%
set filename=%filename:/=%
set filename=%filename::=%
set filename=%filename:?=%
set filename=%filename:"=%
set filename=%filename:<=%
set filename=%filename:>=%
set filename=%filename:|=%
rem crashes the cmd if variables contain umlauts ...
rem echo %artist% - %title% [%year%] (Duration: %duration%)

echo.
echo Converting to m4a ...
ffmpeg -y -v quiet -i "%input%" "%tempimage%"
ffmpeg -y -v %loglevel% -stats -activation_bytes %activation_bytes% -i "%input%" -c:a copy -vn "%tempfile%" || (echo Audiobook can't be unlocked with this Activation Bytes: %activation_bytes% & goto :cleanup)

echo.
echo Adding looped cover image audiobook
ffmpeg -y -v %loglevel% -stats -r 1 -loop 1 -i "%tempimage%" -i "%tempfile%" -c:a copy -shortest "%dirname%%filename%"
echo.
echo Done!
goto :cleanup

:cleanup
del /q "%tempfile%" >nul 2>&1
del /q "%tempimage%" >nul 2>&1
goto :eof