cmc/cleberg.net

My personal web garden & blog.

clone: git clone https://gitbay.org/cmc/cleberg.net.git

main: content/blog/2022-07-30-flac-to-opus.org · raw

  1#+date:        [2022-07-30 Sat 00:00:00]
  2#+title:       Recursive FLAC to Opus Conversion
  3#+description: A bash script to convert FLAC files to Opus recursively.
  4#+slug:        flac-to-opus
  5#+filetags:    :linux:
  6
  7* Converting FLAC to OPUS
  8
  9I am currently rebuilding my music library from scratch so that I can
 10effectively archive all the music I own in [[https://wikipedia.org/wiki/FLAC][FLAC]] (Free Lossless Audio Codec)
 11files.
 12
 13However, streaming FLAC files outside the home can be difficult due to the size
 14of the files, especially if you're using a weak connection.
 15
 16So, in order to archive the music in a lossless format and still be able to
 17stream it easily, I opted to create a copy of my FLAC files in the [[https://en.wikipedia.org/wiki/Opus_(audio_format)][Opus audio
 18codec]]. This allows me to archive a quality, lossless version of the music and
 19then point my streaming service to the smaller, stream-ready version.
 20
 21** Dependencies
 22
 23The process I follow utilizes the =opus-tools= package in Ubuntu. Before
 24proceeding, install the package:
 25
 26#+begin_src sh
 27sudo apt install opus-tools
 28#+end_src
 29
 30If you want to use a different conversion method, such as =ffmpeg= or =avconv=,
 31simply install that package instead.
 32
 33** Conversion Process
 34
 35The script I'm using is stored in my home directory, but feel free to create it
 36wherever you want. It does not need to be in the same directory as your music
 37files.
 38
 39#+begin_src sh
 40cd ~ && nano transform.sh
 41#+end_src
 42
 43Once you have your new bash script opened in an editor, go ahead and paste the
 44following logic into the script.
 45
 46You *MUST* edit the following variables in order for it to work:
 47
 48- =source=: The source directory where your FLAC files are stored.
 49- =dest=: The destination directory where you want the resulting Opus files to
 50  be stored.
 51
 52You *MAY* want to edit the following variables to suit your needs:
 53
 54- =filename=: If you are converting to a file format other than Opus, you'll
 55  need to edit this so that your resulting files have the correct filename
 56  extension.
 57- =reldir=: This variable can be edited to strip out more leading directories in
 58  the file path. As you'll see later, I ignore this for now and simply clean it
 59  up afterward.
 60- =opusenc=: This is the actual conversion process. You may want to edit the
 61  bitrate to suit your needs. I set mine at 128 but some prefer 160 or higher.
 62
 63#+begin_src sh
 64#!/bin/bash
 65## - The IFS takes care of spaces in file and dirnames
 66## - your folders may vary
 67## - what you mount to the folders does not matter
 68## - in RELDIR, the f5 most likely MUST be edited,
 69##    since its responsible, how many leading directories
 70##    will be removed from the directory structure in order
 71##    to append that exact path to the outfile
 72## - the commented echos are still in place in order to give
 73##    you the variables for testing, before running.
 74
 75IFS=$'\n'
 76
 77## the paths given here contain the directory structure that I want to keep
 78## source=/mnt/music/archives/ARTIST/ALBUM/FLACFILE.flac
 79## local=/mnt/music/library/ARTIST/ALBUM/OPUSFILE.opus
 80
 81source=/mnt/music/archives
 82dest=/mnt/music/library
 83
 84for i in $(find $source -type f -iname '*.flac' );
 85do
 86## SET VARIABLES for PATHS and FILENAMES
 87        fullfile=$i
 88        filename="${i##*/}"
 89        filename="${filename%.*}.opus"
 90        fulldir=$(dirname "${i}")
 91        reldir="$(echo $fulldir | cut -d'/' -f5-)"
 92        reldir=${reldir//flac}
 93        outdir="$dest/$reldir"
 94        outfile="$outdir/$filename"
 95
 96# is that working?
 97# outfile='$local/""$(echo $(dirname "${i}") | cut -d'/' -f5-)"//flac"/"${i##*/}"'
 98#       echo 'output file: ' "$outfile"
 99
100## SHOW ME THE CONTENTS of the VARIABLES
101#       echo 'File found:' "$i"
102#       echo 'Relative dir: ' "$reldir"
103#       echo 'directory will be created: ' "$outdir"
104#       echo 'Filename: ' "$filename"
105#       echo 'FileExt: ' "$extension"
106#       echo 'output file: ' "$outfile"
107
108echo "\n\n"
109
110## CREATE Output Folders
111        mkdir -p "$outdir"
112
113## RUN
114# ffmpeg and avconv are alternative options if opusenc isn't adequate
115opusenc --vbr --bitrate 128 --date "$DATE" \
116--title "$TITLE" --artist "$ARTIST" --album "$ALBUM" --genre "$GENRE" \
117--comment "ALBUMARTIST=$ALBUMARTIST" --comment "DISCNUMBER=$DISCNUMBER" \
118--comment "TRACKNUMBER=$TRACKNUMBER" --comment "TRACKTOTAL=$TRACKTOTAL" \
119--comment "LYRICS=$LYRICS" "$fullfile" "$outfile"
120
121
122## just for testing
123#        sleep 1
124done
125#+end_src
126
127Once you're done, simply save the file and exit your editor. Don't forget to
128enable execution of the script:
129
130#+begin_src sh
131chmod +x transform.sh
132#+end_src
133
134Finally, you may now run the script:
135
136#+begin_src sh
137./transform.sh
138#+end_src
139
140If you used =opusenc=, you'll see the conversions happen within the terminal as
141it progresses. You will also see variables printed if you uncommented any of the
142bash script's comments.
143
144** Cleanup
145
146As I noted above, I didn't customize my =reldir= variable in the script, which
147caused my output directory to be =/mnt/music/library/archives= instead of
148=/mnt/music/library=. So, I moved the output up one level and deleted the
149accidental directory.
150
151#+begin_src sh
152cd /mnt/music/library
153mv archives/** .
154rm -rf archives
155#+end_src
156
157** Check the Resulting Size
158
159If you want to see what kind of file size savings you've gained, you can always
160use the =du= command to check:
161
162#+begin_src sh
163cd /mnt/music
164du -h --max-depth=1 .
165#+end_src
166
167In my case, my small library went from 78GB to 6.3GB!
168
169#+begin_src txt
17078G    ./archives
1716.3G   ./library
172#+end_src