#!/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:dh' flag; do case "${flag}" in e) extension+=("$OPTARG");; d) delete="true";; 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")" # 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 for ((index=0; index<${#channels[@]};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 ffmpeg -i "$file" -map 0 -map -0:d -map -0:t -c copy -c:a libopus $bitrate_settings-v info -hide_banner "${file%.*}.mkv" && if [[ delete="true" ]]; then rm "$file"; fi else ffmpeg -i "$file" $bitrate_settings-v info -hide_banner "${file%.*}.opus" && if [[ delete="true" ]]; then rm "$file"; fi fi done exit 0