Last active
May 24, 2023 09:14
-
-
Save Cygon/eb7b3646b4cdb93c484ce1a4b5544c7d to your computer and use it in GitHub Desktop.
Shell script that downmixes and transcodes audio into high-quality AAC tracks
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
# Converts audio from BluRay or lossless source into high quality | |
# AAC files with custom stereo downmix parameters | |
# | |
# Use like this: | |
# ./transcode-audio my_movie.mkv ger51 eng51 skip jpn20 | |
# | |
# Each parameter after the movie name tells the script which kind | |
# of audio channel to handle. | |
# | |
# Dependencies: | |
# * ffmpeg | |
# * qaac (working = w/apple's core audio toolkit) | |
# * wine (to run qaac) | |
# | |
# File from which the audio is taken | |
inputFile="$1" | |
# Quality, 127 is best, 95 is about equivalent to 320 kbit mp3 | |
# | |
# Channels | Quality | Expected bitrate | |
# -----------|---------|------------------- | |
# 2 | 95 | 160 kbps | |
# 2 | 127 | 260 kbps | |
# 5.1 | 95 | 480 kbps | |
# 5.1 | 127 | 720 kbps | |
# | |
qaacStereoQuality=127 | |
qaac5dot1Quality=127 | |
#qaac5dot1Quality=95 | |
# Whether to even encode the 5.1 tracks | |
# | |
# If this is false, all 5.1 audio is downmixed to stereo audio. | |
# And the 5.1 audio tracks are not provided at all | |
# | |
want5dot1=true | |
# Whether to delete the *.flac files | |
# | |
# These are created via ffmpeg and contain the processed audio | |
# tracks before they're transcoded to AAC (using qaac instead of | |
# ffmpeg's own transcoder due to qaac supposedly being higher quality) | |
# | |
# If you want to do some checking and/or processing (i.e. normalize | |
# volume levels) in Audacity, set this to false. | |
# | |
deleteFlacs=false | |
# Standard downmix formula (also used by ffmpeg with -ac 2), | |
# this is sourced from ATSC 7.8, but lacking mastering data, | |
# fixes 'clev' and 'slev' to 0.707. Makes dialogue too quiet: | |
# -af "pan=stereo|FL<1.0*FL+0.707*FC+0.707*BL|FR<1.0*FR+0.707*FC+0.707*BR" | |
# | |
# Nightmode dialogue formula from Doom9. This results in voices at | |
# levels more typical of traditional stereo recordings, but it's | |
# mostly just guesswork and some listening tests: | |
# -af "pan=stereo|FL=FC+0.30*FL+0.30*BL|FR=FC+0.30*FR+0.30*BR" | |
# | |
# The middleground between ATSC and decent dialogue volume. | |
# I don't perceive the dialogue as much quieter than nightmode's, | |
# but this should yield much better stereo separation: | |
# -af "pan=stereo|FL=0.85*FC+0.65*FL+0.5*BL|FR=0.85*FC+0.65*FR+0.5*BR" | |
# | |
volume350="pan=stereo|FL=2.98*FC+2.28*FL+1.75*BL|FR=2.98*FC+2.28*FR+1.75*BR" | |
volume325="pan=stereo|FL=2.76*FC+2.11*FL+1.63*BL|FR=2.76*FC+2.11*FR+1.63*BR" | |
volume300="pan=stereo|FL=2.55*FC+1.95*FL+1.5*BL|FR=2.55*FC+1.95*FR+1.5*BR" | |
volume250="pan=stereo|FL=2.13*FC+1.63*FL+1.25*BL|FR=2.13*FC+1.63*FR+1.25*BR" | |
volume200="pan=stereo|FL=1.7*FC+1.3*FL+1.0*BL|FR=1.7*FC+1.3*FR+1.0*BR" | |
volume100="pan=stereo|FL=0.85*FC+0.65*FL+0.5*BL|FR=0.85*FC+0.65*FR+0.5*BR" | |
volume90="pan=stereo|FL=0.77*FC+0.59*FL+0.45*BL|FR=0.77*FC+0.59*FR+0.45*BR" | |
volume80="pan=stereo|FL=0.68*FC+0.52*FL+0.4*BL|FR=0.68*FC+0.52*FR+0.4*BR" | |
germanStereoDownmixFormula=$volume100 | |
stereoDownmixFormula=$volume100 | |
# ------------------------------------------------------------------- | |
# Figure out where we will get the 2.0 audio files from | |
# ------------------------------------------------------------------- | |
# Shift the arguments one down, pushing the input filename away | |
shift | |
audioTrackIndex=0 | |
# Figure out if we need to downmix the 2.0 channels ourselves or | |
# if these are provided by the source video/audio container. | |
# | |
# If you want the improved downmix formula from this script, just | |
# say "skip" instead of "xxx20" for the 2.0 channels and they will | |
# be downmixed from the 5.1 audio tracks | |
# | |
if [[ "$@" == *"eng20"* ]] | |
then | |
englishStereoNeeded=false | |
else | |
englishStereoNeeded=true | |
fi | |
if [[ "$@" == *"ger20"* ]] | |
then | |
germanStereoNeeded=false | |
else | |
germanStereoNeeded=true | |
fi | |
if [[ "$@" == *"jpn20"* ]] | |
then | |
japaneseStereoNeeded=false | |
else | |
japaneseStereoNeeded=true | |
fi | |
# ------------------------------------------------------------------- | |
# Do the actual transcoding | |
# ------------------------------------------------------------------- | |
# For each argument passed on the command line | |
while test $# -gt 0 | |
do | |
case "$1" in | |
skip) | |
;; | |
eng51) | |
if $englishStereoNeeded ; then | |
ffmpeg \ | |
-hide_banner \ | |
-i "$inputFile" \ | |
-vn \ | |
-map a:$audioTrackIndex \ | |
-strict \ | |
-2 \ | |
-af "$stereoDownmixFormula" \ | |
-y \ | |
english-stereo.flac | |
wine /opt/qaac-2.72/qaac.exe \ | |
--tvbr $qaacStereoQuality \ | |
--quality 2 \ | |
--no-smart-padding \ | |
--no-dither \ | |
english-stereo.flac | |
if $deleteFlacs ; then | |
rm english-stereo.flac | |
fi | |
fi | |
if $want5dot1 ; then | |
ffmpeg \ | |
-hide_banner \ | |
-i "$inputFile" \ | |
-vn \ | |
-map a:$audioTrackIndex \ | |
-y \ | |
english-5dot1.flac | |
wine /opt/qaac-2.72/qaac.exe \ | |
--tvbr $qaac5dot1Quality \ | |
--quality 2 \ | |
--no-smart-padding \ | |
--no-dither \ | |
english-5dot1.flac | |
if $deleteFlacs ; then | |
rm english-5dot1.flac | |
fi | |
fi | |
;; | |
eng20) | |
ffmpeg \ | |
-hide_banner \ | |
-i "$inputFile" \ | |
-vn \ | |
-map a:$audioTrackIndex \ | |
-y \ | |
english-stereo.flac | |
wine /opt/qaac-2.72/qaac.exe \ | |
--tvbr $qaacStereoQuality \ | |
--quality 2 \ | |
--no-smart-padding \ | |
--no-dither \ | |
english-stereo.flac | |
if $deleteFlacs ; then | |
rm english-stereo.flac | |
fi | |
;; | |
ger51) | |
if $germanStereoNeeded ; then | |
ffmpeg \ | |
-hide_banner \ | |
-i "$inputFile" \ | |
-vn \ | |
-map a:$audioTrackIndex \ | |
-strict \ | |
-2 \ | |
-af "$germanStereoDownmixFormula" \ | |
-y \ | |
german-stereo.flac | |
wine /opt/qaac-2.72/qaac.exe \ | |
--tvbr $qaacStereoQuality \ | |
--quality 2 \ | |
--no-smart-padding \ | |
--no-dither \ | |
german-stereo.flac | |
if $deleteFlacs ; then | |
rm german-stereo.flac | |
fi | |
fi | |
if $want5dot1 ; then | |
ffmpeg \ | |
-hide_banner \ | |
-i "$inputFile" \ | |
-vn \ | |
-map a:$audioTrackIndex \ | |
-y \ | |
german-5dot1.flac | |
wine /opt/qaac-2.72/qaac.exe \ | |
--tvbr $qaac5dot1Quality \ | |
--quality 2 \ | |
--no-smart-padding \ | |
--no-dither \ | |
german-5dot1.flac | |
if $deleteFlacs ; then | |
rm german-5dot1.flac | |
fi | |
fi | |
;; | |
ger20) | |
ffmpeg \ | |
-hide_banner \ | |
-i "$inputFile" \ | |
-vn \ | |
-map a:$audioTrackIndex \ | |
-y \ | |
german-stereo.flac | |
wine /opt/qaac-2.72/qaac.exe \ | |
--tvbr $qaacStereoQuality \ | |
--quality 2 \ | |
--no-smart-padding \ | |
--no-dither \ | |
german-stereo.flac | |
if $deleteFlacs ; then | |
rm german-stereo.flac | |
fi | |
;; | |
jpn51) | |
if $japaneseStereoNeeded ; then | |
ffmpeg \ | |
-hide_banner \ | |
-i "$inputFile" \ | |
-vn \ | |
-map a:$audioTrackIndex \ | |
-strict \ | |
-2 \ | |
-af "$stereoDownmixFormula" \ | |
-y \ | |
japanese-stereo.flac | |
wine /opt/qaac-2.72/qaac.exe \ | |
--tvbr $qaacStereoQuality \ | |
--quality 2 \ | |
--no-smart-padding \ | |
--no-dither \ | |
japanese-stereo.flac | |
if $deleteFlacs ; then | |
rm japanese-stereo.flac | |
fi | |
fi | |
if $want5dot1 ; then | |
ffmpeg \ | |
-hide_banner \ | |
-i "$inputFile" \ | |
-vn \ | |
-map a:$audioTrackIndex \ | |
-y \ | |
japanese-5dot1.flac | |
wine /opt/qaac-2.72/qaac.exe \ | |
--tvbr $qaac5dot1Quality \ | |
--quality 2 \ | |
--no-smart-padding \ | |
--no-dither \ | |
japanese-5dot1.flac | |
if $deleteFlacs ; then | |
rm japanese-5dot1.flac | |
fi | |
fi | |
;; | |
jpn20) | |
ffmpeg \ | |
-hide_banner \ | |
-i "$inputFile" \ | |
-vn \ | |
-map a:$audioTrackIndex \ | |
-y \ | |
japanese-stereo.flac | |
wine /opt/qaac-2.72/qaac.exe \ | |
--tvbr $qaacStereoQuality \ | |
--quality 2 \ | |
--no-smart-padding \ | |
--no-dither \ | |
japanese-stereo.flac | |
if $deleteFlacs ; then | |
rm japanese-stereo.flac | |
fi | |
;; | |
esac | |
shift | |
let "audioTrackIndex = $audioTrackIndex + 1" | |
done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment