taudiobooker.nix (3275B)
1 { pkgs, ... }: 2 3 { 4 environment.systemPackages = [ 5 (pkgs.writeShellScriptBin "taudiobooker" '' 6 set -euo pipefail 7 8 # variables 9 codec="libopus" 10 bitrate="48k" 11 compression="10" 12 output="" 13 14 # functions 15 strip_chars() { awk '{gsub(/^[ \t-]+|[ \t-]+$/,""); print $0}'; } 16 17 process_opus_file() { 18 local file="$1" 19 output="$file" 20 21 echo "Tagging OPUS file: $file" 22 23 ${pkgs.opustags}/bin/opustags -i -D "$output" 24 ${pkgs.opustags}/bin/opustags -i -s "GENRE=Audiobook" "$output" 25 26 artist=$(printf "%s" "$output" | 27 awk -F"-" '{print $1}' | 28 strip_chars) 29 30 ${pkgs.opustags}/bin/opustags -i -s "ARTIST=$artist" "$output" 31 32 if [[ "$output" == *"#"* ]]; then 33 # Series format 34 album=$(printf "%s" "$output" | 35 awk -F"-" '{print $2}' | 36 awk -F"#" '{print $1}' | 37 strip_chars) 38 39 track=$(printf "%s" "$output" | 40 awk -F"-" '{print $2}' | 41 awk -F"#" '{print $2}' | 42 awk '{gsub("^0*",""); print}' | 43 strip_chars) 44 45 title=$(printf "%s" "$output" | 46 awk -F"-" '{gsub(".opus",""); print $3}' | 47 strip_chars) 48 49 ${pkgs.opustags}/bin/opustags -i -s "ALBUM=$album" "$output" 50 ${pkgs.opustags}/bin/opustags -i -s "TRACKNUMBER=$track" "$output" 51 ${pkgs.opustags}/bin/opustags -i -s "TITLE=$title" "$output" 52 53 else 54 # Single file 55 title=$(printf "%s" "$output" | 56 awk -F"-" '{gsub(".opus",""); print $2}' | 57 strip_chars) 58 59 ${pkgs.opustags}/bin/opustags -i -s "TITLE=$title" "$output" 60 fi 61 } 62 63 process_other_file() { 64 local file="$1" 65 local base="''${file%.*}" 66 output="''${base}.opus" 67 68 echo "Encoding file to OPUS: $file → $output" 69 70 ${pkgs.ffmpeg}/bin/ffmpeg -hide_banner -loglevel error -nostats \ 71 -i "$file" \ 72 -acodec "$codec" \ 73 -ac 1 \ 74 -b:a "$bitrate" \ 75 -vbr on \ 76 -compression_level "$compression" \ 77 "$output" 78 79 echo "Done: $output" 80 } 81 82 analyze_directory() { 83 local dir="$1" 84 echo "Analyzing and concatenating directory: $dir" 85 86 # Find most common extension 87 local extension 88 extension=$(find "$dir" -type f -printf '%f\n' \ 89 | sed -E 's/.*\.([^.]+)$/\1/' \ 90 | sort | uniq -c | sort -nr | awk 'NR==1{print $2}') 91 92 if [[ -z "''${extension}" ]]; then 93 echo "No files found in directory." 94 exit 1 95 fi 96 97 echo "Most common filetype: .$extension" 98 99 # Output filename based on directory name 100 local name 101 name=$(basename "$dir") 102 output="''${name}.opus" 103 104 echo "Concatenating all .$extension files → $output" 105 106 ${pkgs.ffmpeg}/bin/ffmpeg -f concat -safe 0 \ 107 -i <(for f in "$dir"/*."$extension"; do 108 echo "file '$PWD/$f'" 109 done) \ 110 -acodec "$codec" \ 111 -ac 1 \ 112 -b:a "$bitrate" \ 113 -vbr on \ 114 -compression_level "$compression" \ 115 "$output" 116 117 echo "Created: $output" 118 } 119 120 # main logic 121 122 if [[ $# -ne 1 ]]; then 123 echo "Usage: $0 <file-or-directory>" 124 exit 1 125 fi 126 127 input="$1" 128 129 if [[ -d "$input" ]]; then 130 analyze_directory "$input" 131 elif [[ -f "$input" ]]; then 132 ext="''${input##*.}" 133 shopt -s nocasematch 134 if [[ "$ext" == "opus" ]]; then 135 process_opus_file "$input" 136 else 137 process_other_file "$input" 138 fi 139 shopt -u nocasematch 140 else 141 echo "Error: '$input' is not a valid file or directory" 142 exit 1 143 fi 144 '') 145 ]; 146 }