Quantcast
Channel: Ivanovo
Viewing all articles
Browse latest Browse all 85

Opus Audio Codec for Audio Books And More

$
0
0

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.


Viewing all articles
Browse latest Browse all 85

Trending Articles