Opus is a relatively new lossy audio codec from Xiph Foundation, successor to Vorbis and Speex codecs. It provides very good quality for low bandwidth (<32kbps) streams with speech, but also provides high quality for broader bandwidth (>64kbps) and more demanding data like music etc. So it can be one-off solution for any digital audio encoding. According to some tests presented on it’s site, it’s comparable with HE AAC for higher bandwidth, higher quality data, while it additionally provides better results for lower bandwidth, speech data this is something xHE ACC is addressing too, however I have not seen available codec yet.). And what is most appealing on Opus is that it’s free, without patents and it’s open source. (While majority of common audio codecs e.g MP3, AAC are restricted by patents and are subject to paying loyalties , I think Fraunhofer holds basic patents, but situations is quite complex and differs per country).
Based on positives reviews, I though that Opus could be ideal codec for audio books, where it can provide good quality at low bit rates. At least for me, I really do not need top quality for audio books (say mp3 128kbps), while the book takes gigabytes of space, but on the other hand, I do appreciate good quality and for low quality audios I have problems to understand and I cannot really enjoy the book.
So how can Opus help and is it ready for everyday use?
On Linux I can encode audio to Opus inside Ogg container with FFmpeg ( not every distro has ffmpeg compiled with libopus, however you can easily use static builds). I’ve created this script to be able to convert whole directories (even recursively):
#!/bin/bash BITRATE=24 CUTOFF=12000 APPLICATION=audio FORMAT=ogg QUALITY=10 trap "exit 2" SIGINT for i in "$@" do case $i in -b=*|--bitrate=*) # bitrate in kilobits eg. 24, 32. 64 ... BITRATE="${i#*=}" shift ;; -c=*|--cutoff=*) # cutoff - for low pass filter - 4000, 6000, 8000, 12000, or 20000 CUTOFF="${i#*=}" shift ;; -a=*|--app=*) # application type - voip, audio or lowdelay APPLICATION="${i#*=}" shift ;; -f=*|--format=*) # container format ogg, mkv, webm ... FORMAT="${i#*=}" shift ;; -q=*|--quality=*) # compression quality - 0 fast, low quality - 10 - low high quality QUALITY="${i#*=}" shift ;; -d|--delete) # delete input file after conversion DELETE=YES shift ;; -r|--recursive) # resurse into sub directories RECURSIVE=YES shift # past argument with no value ;; *) # unknown option ;; esac done if [[ -n "$1" && -d "$1" ]]; then cd "$1" for FILE in *.mp3; do if [[ "$FILE" != "*.mp3" ]]; then echo "Processing $FILE" ffmpeg -nostdin -v error -stats -i "$FILE" -y -map_metadata 0 -acodec libopus -b:a ${BITRATE}k -vbr on -compression_level $QUALITY -application $APPLICATION -cutoff $CUTOFF "${FILE%.*}.$FORMAT" if [[ $? -ne 0 ]]; then echo "Encoding error on $FILE" >&2 fi if [[ -n $DELETE ]]; then rm "$FILE" fi fi done if [[ -n $RECURSIVE ]]; then find . -maxdepth 1 -mindepth 1 -type d -exec $0 -b=$BITRATE -c=$CUTOFF -a=$APPLICATION -f=$FORMAT -q=$QUALITY ${DELETE+-d} ${RECURSIVE+-r} {} \; fi exit 0 else echo "Please specify directory!" >&2 exit 1 fi
I converted several audio books (mp3 96kbps or 128kbps, stereo) with opus parameters defaulted in the above script – resulting Opus 24kbps stereo. I also compared (listening on headphones (relatively good ones, Jabra) and external speakers (also fairly good, Yamaha) ) opus version to mp3 version and cannot tell any significant difference in quality, (128kbps mp3 sounds very slightly better in headphones, for 96kbps I was not able to tell any difference). The difference in size is however remarkable – opus is 4-5 times smaller.
Support for Opus in Linux (Ubuntu 14.04) is good – I can play it basically in any player (including default audio player Rhythmbox), however I hit some issues with Android (which is now device I use mostly for listening music and audio books). On Android Opus in ogg container was supported only by VLC player (I believe couple more can play it, but I have only VLC installed). Natively Android does support Opus, but only in matroska (.mkv) container (from 5.0+ as stated here). Solution could be to use always matroska, but I still prefer ogg, because it’s more common container for Opus. Since I use Subsonic (see also my previous article) to steam audio books to my mobile I can use transcoding.
Transcoding can be pretty basic, since both containers support Opus, so it’s just about copying audio stream from one container to other, which can be very fast. However there is still a small issue: if conversion is piped to output, resulting mkv container does not contain duration and stream size in header, so resulting file is not seekable on Android. Target of transcoding has to be fully searchable (e,g, file) so that ffmpeg can write, duration and size after conversion. Solution was to create small transcoding script, which uses a temporary file:
#!/bin/bash if [[ -f "$1" && "$1" == *.ogg ]]; then TMPFILE=`mktemp` ffmpeg -y -v error -i "$1" -map 0:0 -c:a copy -f matroska $TMPFILE cat $TMPFILE rm $TMPFILE else echo "Need ogg file as param" >&2 fi
To improve performance and decrease disk usage we can use tmpfs for temporary files (if we have enough memory):
# put this into /etc.fstab tmpfs /tmp tmpfs nodev,nosuid 0 0
Final note – I also tried webm container, which should be generally equivalent to mkv (with some limitations), but for webm seeking in file was not working.