aboutsummaryrefslogtreecommitdiff
path: root/blog/2022-07-30-flac-to-opus.org
blob: df069b0f50dacbf45d202732f3ab798525ffe0b4 (plain) (blame)
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
+++
date = 2022-07-30
title = "Recursive Command-Line FLAC to Opus Conversion"
description = "A retrospective on how I recursively converting my FLAC file music library to OPUS with opusenc."
+++

## Converting FLAC to OPUS

I am currently rebuilding my music library from scratch so that I can 
effectively archive all the music I own in the [FLAC file 
format](https://en.wikipedia.org/wiki/FLAC), a lossless audio codec.

However, streaming FLAC files outside the home can be difficult due to the 
size of the files, especially if you're using a weak connection.

So, in order to archive the music in a lossless format and still be able to 
stream it easily, I opted to create a copy of my FLAC files in the [Opus audio 
codec](https://en.wikipedia.org/wiki/Opus_(audio_format)). This allows me to 
archive a quality, lossless version of the music and then point my streaming 
service to the smaller, stream-ready version.

### Dependencies

The process I follow utilizes the `opus-tools` package in Ubuntu. Before 
proceeding, install the package:

```sh
sudo apt install opus-tools
```

If you want to use a different conversion method, such as `ffmpeg` or `avconv`, 
simply install that package instead.

### Conversion Process

The script I'm using is stored in my home directory, but feel free to create it 
wherever you want. It does not need to be in the same directory as your music 
files.

```sh
cd ~ && nano transform.sh
```

Once you have your new bash script opened in an editor, go ahead and paste the 
following logic into the script.

You **MUST** edit the following variables in order for it to work:

- `source`: The source directory where your FLAC files are stored.
- `dest`: The destination directory where you want the resulting Opus files to 
be stored.

You **MAY** want to edit the following variables to suit your needs:

- `filename`: If you are converting to a file format other than Opus, you'll 
need to edit this so that your resulting files have the correct filename 
extension.
- `reldir`: This variable can be edited to strip out more leading directories in 
the file path. As you'll see later, I ignore this for now and simply clean it up 
afterward.
- `opusenc`: This is the actual conversion process. You may want to edit the 
bitrate to suit your needs. I set mine at 128 but some prefer 160 or higher.

```sh
#!/bin/bash
## - The IFS takes care of spaces in file and dirnames
## - your folders may vary
## - what you mount to the folders does not matter
## - in RELDIR, the f5 most likely MUST be edited,
##    since its responsible, how many leading directories
##    will be removed from the directory structure in order
##    to append that exact path to the outfile
## - the commented echos are still in place in order to give
##    you the variables for testing, before running.

IFS=$'\n'

## the paths given here contain the directory structure that I want to keep
## source=/mnt/music/archives/ARTIST/ALBUM/FLACFILE.flac
## local=/mnt/music/library/ARTIST/ALBUM/OPUSFILE.opus

source=/mnt/music/archives
dest=/mnt/music/library

for i in $(find $source -type f -iname '*.flac' );
do
## SET VARIABLES for PATHS and FILENAMES
        fullfile=$i
        filename="${i##*/}"
        filename="${filename%.*}.opus"
        fulldir=$(dirname "${i}")
        reldir="$(echo $fulldir | cut -d'/' -f5-)"
        reldir=${reldir//flac}
        outdir="$dest/$reldir"
        outfile="$outdir/$filename"

# is that working?
# outfile='$local/""$(echo $(dirname "${i}") | cut -d'/' -f5-)"//flac"/"${i##*/}"'
#       echo 'output file: ' "$outfile"

## SHOW ME THE CONTENTS of the VARIABLES
#       echo 'File found:' "$i"
#       echo 'Relative dir: ' "$reldir"
#       echo 'directory will be created: ' "$outdir"
#       echo 'Filename: ' "$filename"
#       echo 'FileExt: ' "$extension"
#       echo 'output file: ' "$outfile"

echo "\n\n"

## CREATE Output Folders
        mkdir -p "$outdir"

## RUN
# ffmpeg and avconv are alternative options if opusenc isn't adequate
opusenc --vbr --bitrate 128 --date "$DATE" \
--title "$TITLE" --artist "$ARTIST" --album "$ALBUM" --genre "$GENRE" \
--comment "ALBUMARTIST=$ALBUMARTIST" --comment "DISCNUMBER=$DISCNUMBER" \
--comment "TRACKNUMBER=$TRACKNUMBER" --comment "TRACKTOTAL=$TRACKTOTAL" \
--comment "LYRICS=$LYRICS" "$fullfile" "$outfile"


## just for testing
#        sleep 1
done
```

Once you're done, simply save the file and exit your editor. Don't forget to 
enable execution of the script:

```sh
chmod +x transform.sh
```

Finally, you may now run the script:

```sh
./transform.sh
```

If you used `opusenc`, you'll see the conversions happen within the terminal as 
it progresses.
You will also see variables printed if you uncommented any of the bash 
script's comments.

### Cleanup

As I noted above, I didn't customize my `reldir` variable in the script, which 
caused my output directory to be `/mnt/music/library/archives` instead of 
`/mnt/music/library`. So, I moved the output up one level and deleted the 
accidental directory.

```sh
cd /mnt/music/library
mv archives/* .
rm -rf archives
```

### Check the Resulting Size

If you want to see what kind of file size savings you've gained, you can always 
use the `du` command to check:

```sh
cd /mnt/music
du -h --max-depth=1 .
```

In my case, my small library went from 78GB to 6.3GB!

```txt
78G    ./archives
6.3G   ./library
```