media-tools/to_opus.sh
2023-07-07 22:01:04 +02:00

72 lines
2.6 KiB
Bash

#!/bin/bash
# set shopt-options used by this shell-script
# Note, 0 (true) from shopt -q is "false" in a math context.
shopt -q globstar; globstar_set=$?
((globstar_set)) && shopt -s globstar
shopt -q extglob; extglob_set=$?
((extglob_set)) && shopt -s extglob
# return default shopt-options
function finish {
((globstar_set)) && shopt -u globstar
((extglob_set)) && shopt -u extglob
}
trap finish EXIT
print_help() {
printf "Help: not implemented yet"
}
while getopts 'e:' flag; do
case "${flag}" in
e) extension+=("$OPTARG");;
h) print_help
exit 0;;
*) exit 1 ;;
esac
done
# write array into string
extension="${extension[*]}"
# remove leading space
extension="${extension##+([[:space:]])}"
# change separator
extension=${extension// /|}
for file in **/*.@($extension); do
# array over the number of channels of all streams
readarray -t channels <<<"$(ffprobe -v error -select_streams a -show_entries stream=channels -of compact=p=0:nk=1 "$file")"
# array over the bitrates of all streams
readarray -t bitrates <<<"$(ffprobe -v error -select_streams a -show_entries stream=bit_rate -of compact=p=0:nk=1 "$file")"
# number of audiostreams
audiostreams=${#channels[@]}
# set a channel dependend bitrate for every audio stream
# https://wiki.xiph.org/Opus_Recommended_Settings
# to use ffmpegs default just comment out this block
bitrate_settings=""
for ((index=0; index<audiostreams;index++)); do
if [[ ${channels[index]} -eq 1 ]]; then
if [[ $bitrates == 'N/A' || ${bitrates[index]} -gt 64000 ]]; then bitrate_settings="$bitrate_settings-b:a:$index 64k "; fi
elif [[ ${channels[index]} -eq 2 ]]; then
if [[ $bitrates == 'N/A' || ${bitrates[index]} -gt 128000 ]]; then bitrate_settings="$bitrate_settings-b:a:$index 128k "; fi
elif [[ ${channels[index]} -lt 6 ]]; then
if [[ $bitrates == 'N/A' || ${bitrates[index]} -gt 256000 ]]; then bitrate_settings="$bitrate_settings-b:a:$index 256k "; fi
elif [[ $bitrates == 'N/A' || ${bitrates[index]} -gt 450000 ]]; then bitrate_settings="$bitrate_settings-b:a:$index 450k "; fi
done
# check if it contains video streams (Thumbnails etc. will be ignored)
# use mkv for videos and for multiple audio streams
is_video=$(ffprobe -v error -select_streams V -show_entries stream=codec_type "$file")
if [[ ${#channels[@]} -gt 1 || -n "$is_video" ]]; then
command="ffmpeg -i \"$file\" -map 0 -map -0:d -map -0:t -c copy -c:a libopus $bitrate_settings -v info -hide_banner \"${file%.*}.mkv\""
else
command="ffmpeg -i \"$file\" $bitrate_settings-v info -hide_banner \"${file%.*}.opus\""
fi
eval "$command" #&& rm "$file"
done
exit 0