😁 About me 📜 Articles 📚️ Bookshelf 📧 Contact 🎮 Games 🥞 Recipes 📙 Things I use 🔗 Links
🇺🇸 🇵🇱

How do I orginize my music library?

#personal #linux #tutorial #software

2024-02-09

Firstly speaking I don't use spotify, youtube music or other online music player. I store my music locally on my laptop and my phone.

I sometimes use those services to discover new tracks, but mostly it happened by fate and not by my choice - youtube compilations.

With that I want to have a simple and reliable system, which would tag my music automatically.

Solution

I have a simple program written in rust, which tags my ogg files basing on their names.

Naming scheme:

<Title>.ogg
<Artist>-<Title>.ogg
<Artist>-<Album>-<Title>.ogg
<Artist>-<Album>-<Nr>-<Title>.ogg
<Artist>-<Album>-<Nr>-<Max Nr>-<Title>.ogg

It also add a cover image, if it was found in .cover folder. For more specifics read the code.

There is a problem, from where do I get those ogg files.

Downloading

I my opinion the best tool for getting music is yt-dlp. You can use it on youtune, soundloud or even more.

I personally love to download those ... Full Album videos from youtube and split them with my simple shell script.

#!/bin/sh

# Check if you gave enough args
[ -z "$4" ] && echo "ogg-split <ARTIST> <ALBUM> <OGG FILE> <DESC FILE>" && exit 1

artist="$1"
album="$2"
ogg_file="$3"
desc_file="$4"

# Check if files exists
[ ! -e "$ogg_file" ] && echo "Such ogg file don't exist" && exit 1
[ ! -e "$desc_file" ] && echo "Such ogg file don't exist" && exit 1

begin=""
end=""

title=""

i=0
# TODO Secure for empty line at the end of a file
max="$(cat "$desc_file" | wc -l)"

while IFS= read -r line ; do
  # Get time in seconds
  end="$(printf "${line%% *}" | awk -F\: '{ for(k=NF;k>0;k--) sum+=($k*(60^(NF-k))); print sum }')"

  # Check if not first iteration
  if [ -n "$begin" ]; then
    echo "$begin-$end $title"
    ffmpeg -i "$ogg_file" -acodec copy -ss "$begin" -to "$end" "$artist-$album-$i-$max-$title.ogg" >/dev/null 2>&1 </dev/null || exit 1
  fi

  begin="$end"
  title="${line#* }"
  i=$(( i + 1 ))
done < "$desc_file"

# -sexagesimal
end="$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$ogg_file")"
echo "$begin-$end $title"
ffmpeg -i "$ogg_file" -acodec copy -ss "$begin" -to "$end" "$artist-$album-$i-$max-$title.ogg" >/dev/null 2>&1 </dev/null

I know that it isn't perfect, but it works most of the times.

It will split a ogg files into a smaller ones, basing on a file with timestamps and titles.