Skip to content

Instantly share code, notes, and snippets.

@jscholes
Created January 4, 2024 18:23
Show Gist options
  • Save jscholes/1f5449d69de12c15fb3e53bb5b63848b to your computer and use it in GitHub Desktop.
Save jscholes/1f5449d69de12c15fb3e53bb5b63848b to your computer and use it in GitHub Desktop.

A small percentage of Audible AAX files – usually radio dramatizations / plays – are encoded at a sample rate of 44.1kHz. These files do not seem to play natively on Android, but are accepted by tools and players on Linux, e.g. mplayer, ffmpeg, etc. Trying to use them with Booksonic causes playback to fail if transcoding is not enabled for m4a / m4b files. Similarly, playing through Plex results in a forced server-side transcode. A bug was filed against Booksonic partly about this:

popeen/Booksonic-App#67

After much investigation, it seems the only difference between files that play and those that don’t, apart from the sample rate, bit rate, etc., is a single bit set in the Audio Object Type Specific Config in the ESDS atom in an M4A file. This bit is described as dependsOnCoreCoder in most sources:

https://wiki.multimedia.cx/index.php/Understanding_AAC https://wiki.multimedia.cx/index.php/MPEG-4_Audio https://stackoverflow.com/questions/3987850/mp4-atom-how-to-discriminate-the-audio-codec-is-it-aac-or-mp3

Trying to extract the AAC audio to an ADTS file with ffmpeg yields the error Scalable configurations are not allowed in ADTS, which would suggest this bit is something to do with Scalable Sampling Rate AAC.

https://github.com/FFmpeg/FFmpeg/blob/f0c0ad4455e5f72edf175e81a06e52562cdd1ab2/libavformat/adtsenc.c#L77

Various code fragments found online suggest that this bit should be followed by several bits of extra data, but this does not appear to be the case in the problematic AAC files – it is possible they are therefore considered malformed:

https://android.googlesource.com/platform/frameworks/av/+/jb-release/media/libstagefright/codecs/aacdec/get_ga_specific_config.cpp#341 https://github.com/MediaArea/MediaInfoLib/blob/5cf78d3af8a2847589f22ac7d7acb6735ec9c200/Source/MediaInfo/Audio/File_Aac_GeneralAudio.cpp#L77 https://github.com/FFmpeg/FFmpeg/blob/fd3ee7a92e9227ee44e2a0d837ba9879959b15d7/libavcodec/aacdec_template.c#L831

It turns out that flipping the bit in question is enough to fix these AAC files and make them playable. This can be done with the tools provided at https://www.bento4.com/. For example:

f="$1"
t=`mktemp`
mp4extract moov/trak/mdia/minf/stbl/stsd/mp4a/esds \
	"$f" /dev/stdout | xxd -p | tr -d '\n' >$t
magic=$(sed -re 's/^.*0580808002(....).*$/\1/' $t)
if [ "$magic" != "1212" ]; then
	echo "no need to fix"
	rm "$t"
	exit 0
fi
t2=`mktemp`
new=$(sed -re 's/05808080021212/05808080021210/' $t | xxd -r -p >$t2)
rm $t
old="${f}.pre-fix"
mv -v "$f" "$old"
mp4edit --replace \
	moov/trak/mdia/minf/stbl/stsd/mp4a/esds:"$t2" \
	"$old" \
	"$f"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment