Skip to content

Instantly share code, notes, and snippets.

@facastagnini
Forked from r15ch13/convert-aax-to-m4a.cmd
Last active December 1, 2017 03:11
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save facastagnini/c333e7d490e7abb88c4b36e16cdce223 to your computer and use it in GitHub Desktop.
Save facastagnini/c333e7d490e7abb88c4b36e16cdce223 to your computer and use it in GitHub Desktop.
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
#!/usr/bin/env bash -eu
# Based on https://gist.github.com/r15ch13/0c548be006431607bf1eaecefdc0591a
BOOK_AAX=$1
BOOK_COVER="${BOOK_AAX%.*}-cover.jpg"
BOOK_M4A="${BOOK_AAX%.*}.m4a"
# 1 - extract cover image
ffmpeg -y -i "${BOOK_AAX}" "${BOOK_COVER}"
# 2 - Decrypted and convert to m4a (get the activation_bytes with https://github.com/inAudible-NG/audible-activator)
ffmpeg -y -activation_bytes 9579b005 -i "${BOOK_AAX}" -vn -c:a copy "${BOOK_M4A}"
# 3 - Add cover image (install mp4v2)
mp4art --add "${BOOK_COVER}" "${BOOK_M4A}"
# 4 - cleanup
rm -f "${BOOK_COVER}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment