11

I'm running ffmpeg v2.8.1 from Homebrew, and trying to convert Audible files but there's some trick I"m missing.

This command produces this error output.

ffmpeg -activation_bytes 1CEB00DA -i Volume1.aax -vn -c:a copy output.mp4

[mov,mp4,m4a,3gp,3g2,mj2 @ 0x7fc9a4010600] [aax] file checksum == d72f1f04e3c73d0bc68e742db1bc69b58dc3a500
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x7fc9a4010600] [aax] mismatch in checksums!
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x7fc9a4010600] error reading header
Volume1.aax: Invalid data found when processing input

I know the file is ok, because it plays in iTunes. I does have the file image/cover art embedded in it as well,

From the ffmpeg docs, I read Audible AAX files are encrypted M4B files, and they can be decrypted by specifying a 4 byte activation secret.

I'm presuming - probably incorrectly - that the one given is ok. If not, how does one find that secret.

25

First run these commands:

brew install chromedriver ffmpeg
sudo easy_install pip
pip install selenium requests
git clone https://github.com/inAudible-NG/audible-activator
cd audible-activator
sed -i '' 's,chromedriver_path = "./chromedriver",chromedriver_path = "/usr/local/bin/chromedriver",' audible-activator.py
./audible-activator.py

Then enter your Audible username and password and wait for a while for the eight character activation key to be printed.

If you do not run the sed command that changes the value of the chromedriver_path variable, ./audible-activator.py results in an error like 'chromedriver' executable needs to be in PATH even if chromedriver is on the path or in the audible-activator directory. If your sed is GNU sed, replace sed -i '' with sed -i.

After that run a command like this:

ffmpeg -activation_bytes youractivationkey -i input.aax -c copy output.m4b

(I edited the command above based on the comments by LiWang and marcus erronius to replace output.m4a;mv output.m4{a,b} with output.m4b and to replace -vn -c:v copy with -c copy.)

If you try to use the ffmpeg command above with an aa file instead of an aax file, it results in an error like Option activation_bytes not found. To download a book from Audible as aax instead of aa, choose "Enhanced" from the "Audio Quality" dropdown in the view for downloading a book.

aax files are encrypted mp4 / m4a / m4b files so the ffmpeg command above does not re-encode audio and it preserves metadata such as chapters. mp4, m4a, and m4b are alternative filename extensions for the MPEG-4 Part 14 container format. The m4a and m4b extensions were originally introduced by Apple. One difference between the m4a and m4b extensions is that the option to remember the previous playback position in iTunes is enabled by default for files with an m4b extension but not for files with an m4a extension. iTunes also displays files with an m4b extension under audiobooks by default.

Old versions of iTunes did not have the checkbox to enable remembering the previous playback position, but remembering the previous playback position was always enabled for files with an m4b extension, so even Wikipedia still incorrectly states that "an .m4a audio file cannot "bookmark" (remember the last listening spot), whereas .m4b extension files can." (Even though I don't know if there are still other media players which behave like old versions of iTunes in that respect.)

The UTI for the m4b extension is com.apple.protected-mpeg-4-audio and Finder shows the kind of all m4b files as "protected MPEG-4 audio" even though all files with an m4b extension do not have copy protection.

  • I'm using .aax files and getting the error: Unrecognized option 'activation_bytes'.. Any ideas? Has Audible changed their format in the last year? – lollercoaster Jun 25 '17 at 19:57
  • 2
    Any reason to convert to *.m4a and then rename as *.m4b? Why not just do: ffmpeg -activation_bytes youractivationkey -i input.aax -vn -c:a copy output.m4b? – Li Wang Apr 29 '18 at 19:15
  • 1
    @LiWang It resulted in an error with older versions of ffmpeg, but that no longer seems to be the case. – nisetama May 9 '18 at 13:21
  • @user4669748 I see. Thanks for the confirmation! – Li Wang May 9 '18 at 18:07
  • I had to use this command to get python working, but after this went perfect! ln -sf /usr/bin/python2.7 /usr/local/bin/python2 – Sethmr Nov 10 '18 at 1:33
7

This will get you your activation secret:

https://github.com/inAudible-NG/audible-activator

  • 1
    I used this script to do the actual conversion. It's also worth noting that you have to install selenium and requests via pip or easy_install and also download and extract chromedriver into the audible-activator directory for it to work. This info is provided in audible-activator's README but it is useful to know up front :) – intuited Dec 9 '16 at 0:50
  • Thanks, @intuited; that script is gold. Needed light tweaking to use GNU grep (the ggrep installed with brew install grep) on macos, but did a great job after that. – ecmanaut Oct 8 '17 at 23:53
6

I tried user4669748's answer, and ran into a few things worth noting, and discovered a fix that got things to work for me:

  1. audible-activator.py requires Python 2.7; it fails with Python 3.
  2. After starting it, the Chrome window pops-up on the screen and you start to see GUI activity, and a successful login to Audible.
  3. Soon after login, browser activity seems to hang, with Waiting for px.owneriq.net constantly displayed in the bottom status bar.
  4. After 5 minutes, I had a TimeoutException:

    [*] Player ID is 2jmj7l5rSw0yVb/vlWAYkK/YBwk=
    Traceback (most recent call last):
      File "./audible-activator.py", line 151, in <module>
        fetch_activation_bytes(username, password, options)
      File "./audible-activator.py", line 74, in fetch_activation_bytes
        search_box.submit()
      File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/selenium/webdriver/remote/webelement.py", line 88, in submit
        self._execute(Command.SUBMIT_ELEMENT)
      File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/selenium/webdriver/remote/webelement.py", line 494, in _execute
        return self._parent.execute(command, params)
      File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/selenium/webdriver/remote/webdriver.py", line 236, in execute
        self.error_handler.check_response(response)
      File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/selenium/webdriver/remote/errorhandler.py", line 192, in check_response
        raise exception_class(message, screen, stacktrace)
    selenium.common.exceptions.TimeoutException: Message: timeout: cannot determine loading status
    from timeout: Timed out receiving message from renderer: -0.222
      (Session info: chrome=54.0.2840.98)
      (Driver info: chromedriver=2.25.426935 (820a95b0b81d33e42712f9198c215f703412e1a1),platform=Mac OS X 10.12.0 x86_64)
    

At this, I was stuck. However, thinking that px.owneriq.net is some kind of ad or tracking site, I tried to "temporarily disable" it by adding to /etc/hosts with an invalid IP address, e.g.

0.0.0.0 px.owneriq.net

(This was a tactic suggested by a friend to stop ads in browser.)

After this addition to /etc/hosts, re-run the program. It ran to completion in 30 seconds.

A 4-byte activation key was printed to the screen, and worked perfectly with ffmpeg as described in user4669748's answer.

I then restored /etc/hosts to its original content.

You must log in to answer this question.

protected by bmike Feb 28 '17 at 22:55

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged .