alt title: I shouldn't have to this, all of this is fucking stupid.

We have two kids, like most parents we ended up buying little machines that played some music and projected some lights onto the ceiling. They're supposed to help babies sleep. Do they work? Who knows, but ~every parent out with a baby will try ~anything to help them sleep, so we tried them. Once a child is used to a part of a routine they need it. Desperately. 100% of the time. The machines all died. Quickly. Their average life span couldn't have been more than like 6 months. I ended up taking a Philips Hue bulb (for fun colours), some card-stock paper, and a cricut and MacGyvering my own star projector onto a lamp. It works great, it's been working for years.

That leaves music. We bought a Sonos speaker from Ikea and streamed music it to it from Calm. Our daughter really liked one instrumental track, so we left it playing in her room 24x7 for years. While our son liked listening to bedtime stories, also from Calm. There was Thomas the Tank Engine stories, stories about Penguins, even a story about the Semi-colon! All very soothing, they slept well. We bought a lifetime subscription to Calm.

Then someone at Calm woke up and chose violence.

Our daughter usually listens to a story, followed by her favoured music on repeat until morning. We accomplish this with a simple playlist: the story, then the music 10 times in a row. Problem Solved. Then (it seems) someone at Calm embarked on a journey to re-encode their audio library, and apply volume normalization inconsistently across tracks. To make the story loud enough to hear we'd need to set the volume on the speaker to "24", for the music we wanted "8", so if we didn't change the volume promptly IT GOT VERY LOUD. Where we could previously just start our daughter's playlist and leave, now we needed to set ourselves reminders to adjust the volume once the story ended and the music began. It was a pain.

I filed support tickets with Calm and Sonos. The Sonos folks fully understood the issue, worked with me to eliminate any other variables, and then (reasonably) told me there was nothing they could do. The music bits come in, they play them like they're supposed to. Calm gave me a canned response and told me they'd pass my feedback on.

Time to fix this crap so my kids can sleep.

Step 1. Download the music from Calm

Calm has an app, integrations with music services... and also a website. I found a browser plugin that would let me download the music that was streaming from the website. Calm uses a mix of .mp3 and .oga files.

Step 2. Convert all the music to .mp3

After googling "swiss army knife for video files" to remember what FFMpeg was called I converted all the music files I'd downloaded to mp3s. Using some terrible bash scripts, and a shell command this went pretty quickly. Have I mentioned I hate bash scripting? I hate bash scripting.

#!/bin/bash

filename=$(basename -- "$1")
extension="${filename##*.}"
filename="${filename%.*}"

#ffmpeg -i "./$1" -f mp3 ./mp3/"$filename".mp3
echo $filename
echo $extension

if [ $extension == "mp3" ]
then
	mv ./"$1" ./mp3/"$1"
else
	ffmpeg -i ./"$1" -f mp3 ./mp3/"$filename".mp3
	rm "$1"
fi

Step 3. Figure out how loud the music is now

There's some cool python program that's supposed to make this easier, but I couldn't get it to work. Instead I mostly copy pasted things from a Stack Overflow post, then crammed it into a shell script so I didn't need to remember everything. I still hate bash scripts, but it's better than trying to remember how to use ffmpeg.

#!/bin/bash

ffmpeg -i ./"$1" -af "volumedetect" -vn -sn -dn -f null /dev/null

It pumps out a bunch of output, but mostly I'm interested in these lines:

[Parsed_volumedetect_0 @ 0x118e06590] mean_volume: -30.6 dB
[Parsed_volumedetect_0 @ 0x118e06590] max_volume: -10.1 dB

Step 4. Normalize the audio

I've decided to normalize at 0.db, so I take the "max volume" value from step 3, and ask FFMpeg to use it to change the audio of the track. Not directly of course, first I have to write a bash script wrong 4-5 times, then end up with this.

#!/bin/bash
filename="${1%%.*}"
extension="${1##*.}"
ffmpeg -i ./"$1" -af "volume=$2dB" ./normalized/"$filename"-n.mp3

Step 5. Edit the MP3 Metadata

I'm old enough to remember the MP3 file naming convention wars, and using various software utilities to try and enforce my will on my sprawling MP3 collection. My kids don't need to understand what space-dash-space means, so I'll grabbed MP3Tag to add decent metadata to tracks manually, and add the cover art.

Step 6. Put it on the network

I initially thought I needed an iTunes server to make Sonos happy, but it turns out you just need a shared network drive. We've got a Synology NAS, which is both overkill for some relaxing stories, and already set up on the network. I created a new folder shared with SMB, and added a user that had access to that folder.

I found it a bit tricky to get the exact syntax the Sonos app wanted for the network share working. I found it helpful to experiment at the command line. I also briefly fought (and loss) Synology which wasn't happy with weak a password I was generating for an account that had read only access to 50 files.

open "smb://sonos:sleepymusic@192.168.1.113/music"

Step 7. Add it to Sonos

Sonos hides your local network stuff under Settings -> System -> Media Servers (rather than Settings -> Services & Voice, which is where the rest of your music comes from). The connection string above turns into

//192.168.1.113/music 

with the username and password entered into their own respective boxes. This sounds obvious, but I lost my patience 8 steps ago and it took a while.

Step 8. Sleep Success

Now my daughter can listen to stories, and music, all without changing the volume on her speaker.

Conclusion

This was an absolutely ridiculous process to go through. I hated every step of it, this is dumb, I shouldn't need to do this. But more than that, I value my daughter having a good bed time routine, so here we are. As a small bonus I know remember in glorious detail why I hate bash scripting, and our daughter still gets music and stories even if the Internet is down.

Cover Photo by Anthony 🙂: https://www.pexels.com/photo/closed-up-photography-of-brown-wooden-framed-sony-speaker-157534/