sandreas / m4b-tool

m4b-tool is a command line utility to merge, split and chapterize audiobook files such as mp3, ogg, flac, m4a or m4b
MIT License
1.15k stars 76 forks source link

Autodetect quality depending on source #233

Open Buxxter opened 1 year ago

Buxxter commented 1 year ago

It would be great if tool can detect source quality and automaticaly sets maximum available output quality for this source. There is no point to convert 32k mp3 to 128 aac. Manual seting up the output quality is ok for single book but totally unusable when I use batch converting of my library collected from different sources.

sandreas commented 1 year ago

You are absolutely correct. Unfortunately this is not as trivial as it may seem.

In the past I had to rely on ffmpeg for bitrate and this was not accurate.

With tone the bitrate detection is pretty accurate now but vbr values probably must be handled differently and this is tricky. Different formats also may have different quality on different bitrates, so a conversion from 64kbit aac to 96kbit mp3 could make sense under specific circumstances.

Moreover the comparison has to be done per FILE not per BOOK, because every source file could have different quality. So if you have a 320k book with one file of 64k the limit as a whole would be 64k or I would have to build an average quality value, where I measure every file, sum it up and divide it by the number of files. That would be possible, but still a bit inaccurate. There is also the sampling rate, etc. etc.

However, we don't wanna have a perfect solution, so what I could do is a simple value comparison like this:

if ($sourceBitrate < $destinationBitrate) {
    $destinationBitrate = $sourceBitrate;
    $destinationSamplingRate = findAccordingSamplingRate($destinationBitrate);
}

or as mentioned the average approach

$sourceAvgBitrate = buildAverageBitrate($sourceFiles);
if($destinationBitrate > $sourceAvgBitrate) {
    $destinationBitrate = $sourceAvgBitrate;
    $destinationSamplingRate = findAccordingSamplingRate($destinationBitrate);
}

when a flag (e.g. --no-upscaling) is given. We could also introduce an integer value to be more flexible (e.g. --max-upscaling=32000) where it would upscale 64k to 96k but not higher. A value of 0 would have the same effect as the flag, a negative value could also be used to limit the downscaling to a specific value.

Which one would you prefer?

Buxxter commented 1 year ago

I'm not an expert in encoding. I just want to pack my books into a handy container with cover, chapters and bookmarks. So in my cases what I do is pretty straigh forward - I get the maximum bitrate from vbr mp3's of book and convert the whole book in this bitrate according this rule: 64/mp3 to 32/aac, 128 to 64, all other to 96

--max-upscaling with 0 value will be the good compromise for me. Ability of setting the appropriate output format for the input format would be ideal, but this solution may not be perfect for everyone else.

P.S. I'm sorry for my English. I hope you'll get the point.

maxthev commented 1 year ago

Personally, I use this commande in my script to detect bitrate :

bit=$(ffprobe -hide_banner -loglevel 0 -of flat -i "$sample" -select_streams a -show_entries format=bit_rate -of default=noprint_wrappers=1:nokey=1)

where "$sample" is the first file of the audiobook.

Then i set the bitrate in the merge function :

m4b-tool merge "$folder" -n --audio-bitrate="$bit"  [...]