content/blog/2022-07-30-flac-to-opus.org

0b2895a90c7751ce06e4b26d4db41005ea2f40a9
cleberg.net/content/blog/2022-07-30-flac-to-opus.org rendered · source · history · blame · raw

175 lines · 5710 bytes

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