-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFlacToMp3V3.sh
More file actions
189 lines (156 loc) · 6.06 KB
/
Copy pathFlacToMp3V3.sh
File metadata and controls
189 lines (156 loc) · 6.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
#!/bin/bash
############################################################################################
#
# A FFMPEG SCRIPT TO CONVERT FLAC FILES INTO MP3@320 USING MULTIPLE CORES
#
# The script uses fd instead of find (since it's much more powerful and executes
# in parallalel) to find the flac files inside the specified source directory.
# When it finds a file it then creates a directory with the same name and parent
# folders in the output directory and after that uses ffmpeg to convert the file into
# an mp3 at 320 kb/s.
#
# Once it has converted the flac files it copies the mp3 files that already existed
# in the source directory into the output directory
#
############################################################################################
# FFMPEG HAS A BUG WHITH THE IMAGE METADATA WHERE IT WILL SOMETIMES MAKE THE FILE 2X BIGGER THAN IT SHOULD
# I SOLVED IT BY REMOVING THE IMAGE ENTIRELY WHEN CONVERTING SO THAT WAY IT NEVER HAPPENS, BUT BECAUSE
# I WANT TO HAVE THE METADATA IMAGES ON THE FILES I HAVE THEN TO REAATACH THE IMAGE AGAIN WITH A PYTHON SCRIPT
##################
# INITIALIZATION #
##################
# Check if fd is installed
if [[ ! $(which fd) ]]; then
echo "[E] Couldn't find fd. Make sure fd is installed."
fi
# Check if the mutagen python library is installed (to reattach the metadata images)
if [[ $(python -c "import mutagen") ]]; then
echo "[E] Couldn't find python library mutagen. Make sure mutagen is installed."
fi
# Initialize errors as 0 and we will set it to 1 if an error occurs
errors=0
# Get the script directory
script_dir="$(dirname $0)"
# Add an empty line for readability
echo ""
########################
# ARGUMENTS PROCESSING #
########################
help_msg(){
echo "Usage:"
echo " FlacToMp3V3.sh [options]"
echo
echo "Options:"
echo " -s [source] The source directory. Defaults to working directory"
echo " -d [destination] The output directory. Defaults to working directory"
echo " -c [number_of_cores] The number of cores to use. Defaults to MAX"
}
while getopts 's:d:c:h' option; do
case "${option}" in
# Source directory
s)
if [[ -d ${OPTARG}/ ]]; then
src_dir=${OPTARG}
else
echo "[E] Source ${OPTARG} Not a valid directory"
errors=1
fi
;;
# Destination directory
d)
if [[ -d ${OPTARG}/ ]]; then
out_dir=${OPTARG}
else
echo "[E] Destination ${OPTARG} Not a valid directory"
errors=1
fi
;;
# Number of cores
c)
if (( ${OPTARG} <= $(nproc) )); then
cores=${OPTARG}
else
echo "[E] Specified Number of cores (${OPTARG}) greater than Number of cores available ($(nproc))"
errors=1
fi
;;
# Help
h)
help_msg
exit 0
;;
# Unspecified argument
*)
help_msg
exit 1
;;
esac
done
# If any errors have been found exit the program
# Do this here instead of when the error is found to process all the arguments so you can know if there are several
# errors so you don't have to run, find an error, fix it, find a different error, fix it... This way you can fix all
# in one run
if (( $errors != 0 )); then
echo "Errors where found. Exiting"
echo ""
exit 1
fi
# If a source directory hasn't been specified use the working directory
if [[ -z $src_dir ]]; then
src_dir=$(pwd)
fi
# If an output directory hasn't been specified use the wroking directory
if [[ -z $out_dir ]]; then
out_dir=$(pwd)
fi
# If cores hasn't been specified use maximum number available
if [[ -z $cores ]]; then
cores=$(nproc)
fi
########
# MAIN #
########
# Using fd spans multi-threaded processes while find doesn't
# Use fd in the source directory (--search-path) to find all files (-t)
# with flac extension (-e), for each result execute (-x) a bash.
# The bash call is needed to be able to do string substitutions over
# the finded paths (since fd uses {} to call the paths inside the -x
# using ${} gives substitution errors) so we call bash and pass it the
# arguments we want that we can then call with $n.
# Inside the bash we create the output directories,
# then ffmpeg the flac to mp3 @ 320kb/s (-b),without cover image (-map)
# (because sometimes it gives encoding errors and makes the files 2x
# bigger) only if its a newer file (-n),
# then if only if the ffmpeg succeeded, we find the cover image for
# that song using the song path minus the filename and removing the possible
# '/Disc*' folder (if present) and only searching in that very folder
# (-maxdepth 1) and pipe the output to my AutoImageCover.py that
# sets the metadata image via xargs with % as the selected char to replace
# the argument (-I) and specifying that the variable must be used as a literal
# string (-0) (which also makes it have a \n at the end, so that must be
# removed in the python script).
fd -j $cores -t f -e flac --search-path "$src_dir" -x bash -c 'mkdir -p -m 777 "${1/#$3/$4}";
ffmpeg -n -i "$0" -map 0:a -b:a 320k "${2/#$3/$4}.mp3" && {
find "${1%\/Disc*}" -maxdepth 1 -type f \( -name "*.jpg" -o -name "*.png" \) |
xargs -0 -I % python "$5/AutoImageCover.py" "${2/#$3/$4}.mp3" %
}' {} {//} {.} "$src_dir" "$out_dir" "$script_dir"
# Use fd to find the files (-t) with mp3 extension (-e) and bash each result
# (same reason as before)
# Do one first path string substitution for the directory prefix with an
# echo so ge can then use the result in the next command and output it to
# /dev/null so it doesn't print to terminal, and then another string substitution
# to remove the ' [mp3]',
# finally create the directory and its parents (-p) with mode 777 (-m),
# then copy the song to that directory only if its newer (-u) with verbosity (-v)
fd -t f -e mp3 --search-path "$src_dir" -x bash -c 'echo "${1/#$2/$3}" > /dev/null;
mkdir -p -m 777 "${_/ \[mp3]/}";
cp -uv "$0" "$_"' {} {//} "$src_dir" "$out_dir"
# Add empty line for readability
echo ""
# $SECONDS is a builtin variable that stores the seconds the script has
# been running
# Use that to print the real time the script took
# times prints the user and sys time
# exit call
ELAPSED="Real: $(($SECONDS / 3600))hrs $((($SECONDS / 60) % 60))min $(($SECONDS % 60))sec"
ret=$?; echo "$ELAPSED"; times; echo ""; exit "$ret"