chore(unitproc/bkt-replace_contractions):Add licence info
[BK-2020-03.git] / user / mp3s_to_opus.sh
... / ...
CommitLineData
1#!/bin/bash
2# Desc: Converts a directory of mp3s into a single opus file
3# Usage: mp3s_to_opus.sh [DIR in] [DIR out] [BITRATE]
4# Example: mp3s_to_opus.sh ./dir_source ./dir_output 48k
5# Depends: GNU Coretils 8.32 (date)
6# Version: 0.0.4
7
8# plumbing
9opus_bitrate="$3"; # e.g. "48k"
10script_rundate="$(date +%s)";
11dir_tmp="/dev/shm";
12dir_in="$(readlink -f "$1")";
13dir_out="$(readlink -f "$2")";
14file_flist="$dir_tmp"/"$script_rundate"..flist.txt;
15file_out_opus="$dir_out"/output.opus;
16file_albumart="$dir_out"/albumart.png;
17
18yell() { echo "$0: $*" >&2; } # print script path and all args to stderr
19die() { yell "$*"; exit 111; } # same as yell() but non-zero exit status
20must() { "$@" || die "cannot $*"; } # runs args as command, reports args if command fails
21show_usage() {
22 # Desc: Display script usage information
23 # Usage: showUsage
24 # Version 0.0.2
25 # Input: none
26 # Output: stdout
27 # Depends: GNU-coreutils 8.30 (cat)
28 cat <<'EOF'
29 USAGE:
30 mp3s_to_opus.sh [DIR in] [DIR out] [BITRATE]
31
32 EXAMPLE:
33 mp3s_to_opus.sh ./source_dir ./out_dir 48k
34EOF
35} # Display information on how to use this script.
36check_depends() {
37 if ! command -v ffmpeg; then show_usage; die "FATAL:Missing ffmpeg."; fi;
38}; # check dependencies
39check_plumbing() {
40 if [[ $# -ne 3 ]]; then show_usage; die "FATAL:Invalid arg count:$#"; fi;
41 if [[ ! -d "$dir_in" ]]; then show_usage; die "FATAL:Not a dir:$dir_in"; fi;
42 if [[ ! -d "$dir_out" ]]; then mkdir -p "$2"; fi;
43}; # check arguments
44build_filelist() {
45 # Depends: var dir_tmp temporary directory
46 # var dir_in input dir
47 # var file_flist path file list
48 # Output: file: $file_flist list of mp3 files for ffmpeg
49
50 # Change directory to input dir
51 pushd "$dir_in" || die "FATAL:Directory error:$(pwd)";
52
53 while read -r line; do
54 yell "$(printf "file '%s'\n" "${line#./}")";
55 printf "file '%s'\n" "${line#./}" >> "$file_flist";
56 done < <(find "$dir_in" -type f -iname "*.mp3" | sort);
57
58 # Return to original dir
59 popd || die "FATAL:Directory error:$(pwd)";
60
61}; # build file list for ffmpeg
62ffmpeg_convert() {
63 # Depends: var dir_tmp
64 # dir_in
65 # dir_out
66 # Input: file $file_flist list of mp3 files for ffmpeg
67
68 # Change directory to input dir
69 pushd "$dir_in" || die "FATAL:Directory error:$(pwd)";
70
71 # Concatenate mp3 files into a single WAV file
72 # # Convert WAV to 48 kbps opus file
73 ffmpeg -nostdin -f concat -safe 0 -i "$file_flist" -c:a pcm_s24le -rf64 auto -f wav - | \
74 ffmpeg -i - -c:a libopus -b:a "$opus_bitrate" "$file_out_opus";
75
76 # Return to original dir
77 popd || die "FATAL:Directory error:$(pwd)";
78}; # convert mp3s to opus via ffmpeg
79save_albumart() {
80 local file
81 file="$(find "$dir_in" -type f -iname "*.mp3" | sort | head -n1)";
82 file="$(readlink -f "$file")";
83 ffmpeg -nostdin -i "$file" -an -vcodec copy "$file_albumart";
84}; # save album art from an mp3 to output dir
85main() {
86 check_depends && yell "DEBUG:check_depends OK";
87 check_plumbing "$@" && yell "DEBUG:check_plumbing OK";
88 build_filelist "$@" && yell "DEBUG:build_filelist OK";
89 ffmpeg_convert "$@" && yell "DEBUG:ffmpeg_convert OK";
90 save_albumart "$@" && yell "DEBUG:save_albumart OK";
91}; # main program
92
93main "$@";
94