OverDrive is great and distributes DRM-free MP3s instead of some fragile DRM-ridden format, which is awesome. Way to go, Rakuten / OverDrive, fight the man!
Their "OverDrive Media Console" application for macOS is pretty simple... so simple, I'm like, why have an app?
So I wrote a shell script, overdrive.sh
,
which takes one or more .odm
files (which are just XML),
and downloads the audio content files locally, just like the app.
The following will install the standalone script into ~/.local/bin
and mark it executable:
mkdir -p ~/.local/bin
curl https://chbrown.github.io/overdrive/overdrive.sh -o ~/.local/bin/overdrive
chmod +x ~/.local/bin/overdrive
At this point, if calling overdrive
produces the error message -bash: overdrive: command not found
,
you'll need to add ~/.local/bin
to your PATH
. One way to do this:
printf 'export PATH=$HOME/.local/bin:$PATH\n' >> ~/.bashrc
source ~/.bashrc
N.b.: if you're using zsh
instead of bash
, run this instead:
printf 'export PATH=$HOME/.local/bin:$PATH\n' >> ~/.zshrc
source ~/.zshrc
Now you should be able to run overdrive --help
and use the commands described below...
Download an OverDrive loan file from your library or wherever.
I'll assume that yours is called Novel.odm
.
Assuming you've downloaded it to your ~/Downloads
folder, simply run the following command:
cd ~/Downloads
overdrive download Novel.odm
When you run that, the script first checks if there is already a Novel.odm.license
file alongside Novel.odm
.
If that file already exists, the script will not request a new license,
since the OverDrive server will only grant one license per .odm
loan.
If not, it will request the license from the OverDrive server and write it to a new Novel.odm.license
file,
by performing the following actions:
- Extract the
AcquisitionUrl
andMediaID
from theNovel.odm
file. - Compute a Base64-encoded SHA-1 hash from a few
|
-separated values and a suffix ofOVERDRIVE*MEDIA*CONSOLE
, but backwards. (Thanks to https://github.com/jvolkening/gloc for somehow figuring out how to construct that hash!) - Using those values and a randomly generated
ClientID
GUID, it submits a request to the OverDrive server to get the full license for this book, which is an XML file that has a<License>
element at the root. That element contains a long Base64-encoded<Signature>
, which is subsequently used to request the content files.
Now, license in hand, the script downloads the audio content files by taking the following steps:
- Extract the
Title
andAuthor
values from theCDATA
content nested inNovel.odm
. - For each of the parts of the book listed in
Novel.odm
, make a request to another OverDrive endpoint, which will validate the request and redirect to the actual MP3 file on their CDN, and save the result into a folder in the current directory, named likeAuthor - Title/Part0N.mp3
.
N.b.: These "parts" don't necessarily correspond to actual chapters in the book; there may be multiple chapters in a single part, or a single chapter spread out over multiple parts.
The OverDrive format makes "returning" a loan extremely simple.
All you have to do is request the URL specified by the <EarlyReturnURL>
element in the loan file.
The return
command does exactly that, e.g.:
overdrive return Novel.odm
If you have trouble getting the script to run successfully, add the --verbose
flag and retry, e.g.:
overdrive download Novel.odm --verbose
This will call set -x
to turn bash's xtrace
option on,
which causes a trace of all commands to be printed to standard error,
prefixed with one or more +
signs.
If that doesn't help you debug the problem, open an issue, including the full debug output (optimally as a gist), and I'll try to help you out.
- Q: I got an error message like
-bash: ~/.local/bin/overdrive: Permission denied
orzsh: permission denied: overdrive
; what's wrong?
A: You installedoverdrive
to the right place 👍, but didn't set the executable flag 😟. Try running thechmod +x
command from the Install steps again.
This script is tested (i.e., developed and used) on macOS with bash 5.0.
It depends on the following executables being available on your PATH
:
curl
uuidgen
xmllint
iconv
openssl
base64
tidy
Package manager one-liners (please create a PR to contribute a new OS!):
Command | OS |
---|---|
brew install openssl tidy-html5 |
# macOS† |
apt-get install curl uuid-runtime libxml2-utils libc-bin openssl coreutils tidy |
# Debian / Ubuntu |
apk add bash curl util-linux libxml2-utils openssl tidyhtml |
# Alpine |
pacman -S curl util-linux libxml2 openssl coreutils tidy |
# Arch |
dnf install curl glibc-common util-linux libxml2 openssl coreutils tidy |
# Fedora |
†Though this is unnecessary; AFAICT, all required commands are installed by default on macOS 10.14 (Mojave).
The ID3(v2) tagging tool I use is mutagen
,
which is used and maintained by the Quod Libet audio player project.
Alternatively, you can use ffmpeg
with the -metadata
option.
Unfortunately, it appears that iTunes always loads .mp3
s as "Music" despite the Genre
(there doesn't seem to be any way to import .mp3
s into iTunes as "Audiobooks").
You have to open iTunes, "Get Info" for the intended songs, and set the "Media Kind" to "Audiobook" manually.
Copyright © 2017–2020 Christopher Brown. MIT Licensed.