install dependencies

brew install yt-dlp
brew install ffmpeg
brew install nvm # or whatver you use to install node
nvm install --lts

using the dependencies

url=https://www.youtube.com/watch?v=xxx
yt-dlp --list-formats $url
yt-dlp -f m4a <url-with-playlist>
ffmpeg -i "<filename>" -to 00:02:35 foo.mp3

script for splitting a multi-track into

building the code snippets

ffmpeg \
-i "'Something To Remind You' vs. 'Dream A Liitle Dream of Me' | Cross Battles #2 | The Voice | VTM [CCsBWWdnFq0].m4a" \
-to 00:01:41 \
"09 - Something To Remind You - Cross Battles #2 - The Voice van Vlaanderen - CCsBWWdnFq0.m4a"

ffmpeg \
-ss 00:01:50 \
-i "'Something To Remind You' vs. 'Dream A Liitle Dream of Me' | Cross Battles #2 | The Voice | VTM [CCsBWWdnFq0].m4a" \
-to 00:01:55 \
"10 - Dream A Liitle Dream of Me - Cross Battles #2 - The Voice van Vlaanderen - CCsBWWdnFq0.m4a"
function toSeconds(s){let seconds = 0; const parts = s.split(":").reverse(); for(let i = 0; i < parts.length; i++){seconds += Math.pow(60, i) * +parts[i]} return seconds;}
function leftpad0(s) {return s.toString().length<2 ? "0" + s : ""+s}

function fromSeconds(s) { const hours = Math.floor(s/3600), minutes = Math.floor((s/60)%60), seconds = s%60; return `${leftpad0(hours)}:${leftpad0(minutes)}:${leftpad0(seconds)}`}
let lines = (await import("fs")).readFileSync('scratch_25.txt').toString()
lines.split('\n').filter(line => line).map(line => line.split(/ +/, 2)).map(l =>[toSeconds(l[0]), l[1]])

lines.split('\n').filter(line => line).map(line => line.split(/ +/, 2)).map(l =>[l[0], toSeconds(l[1]) - toSeconds(l[0])])

lines.split('\n').filter(line => line).map(line => line.split(/ +/, 2)).map(l =>[l[0], fromSeconds(toSeconds(l[1]) - toSeconds(l[0]))]).map(l => `${l[0]}   ${l[1]}`)

lines.split('\n').filter(line => line).map(line => line.split(/ +/, 2)).map(l =>[l[0], fromSeconds(toSeconds(l[1]) - toSeconds(l[0]))]).map((l, i) => `ffmpeg -ss ${l[0]} -i "" -to ${l[1]} "${leftpad0(i + 1)} - "`)
lines.replaceAll('[[', '\n').split('\n').filter(line => line)


let times = lines.replaceAll('[[', '\n[[').split('\n').filter(line => line).map(l=>l.match(/\[\[(.*)]\(.*\)] (.*)/))[0]

let times = lines.replaceAll('[[', '\n[[').split('\n').filter(line => line).map(l=>l.match(/\[\[(.*)]\(.*\)] (.*)/)).map(matches => ({start:matches[1].trim(), title:matches[2].trim()}))[0]
function toSeconds(s){let seconds = 0; const parts = s.split(":").reverse(); for(let i = 0; i < parts.length; i++){seconds += Math.pow(60, i) * +parts[i]} return seconds;}

function leftpad0(s) {return s.toString().length<2 ? "0" + s : ""+s}

function fromSeconds(s) { const hours = Math.floor(s/3600), minutes = Math.floor((s/60)%60), seconds = s%60; return `${leftpad0(hours)}:${leftpad0(minutes)}:${leftpad0(seconds)}`}

let lines = (await import("fs")).readFileSync('scratch_25.txt').toString()
let times = lines.replaceAll('[[', '\n[[').split('\n').filter(line => line).map(l=>l.match(/\[\[(.*)]\(.*\)] (.*)/)).map(matches => ({start:matches[1].trim(), title:matches[2].trim()}))[0]

download youtube cover image

assuming all folders end in the youtube id song name [yt-id]

find . -type d -maxdepth 1 | sed 's/.*\[\([0-9a-zA-Z_-]*\)\] *$/\1/' | xargs -I {} curl -o '{}.jpg' 'https://img.youtube.com/vi/{}/0.jpg'

final script version

https://github.com/TjenWellens/ffmpeg-split-multiple

using it all

mkdir foo
cd foo

url="https://www.youtube.com/watch?v=xxxx" # replace xxxx
yt-dlp -f m4a $url

vi timestamps.txt

source_file="$(ls)" # assumes a single file in the dir
node split-music.js *xxxx*.m4a timestamps.txt | pbcopy

# the script is now in your clipboard (assuming mac)
# paste it and press enter!


# get the cover image
find . -type d -maxdepth 1 | sed 's/.*\[\([0-9a-zA-Z_-]*\)\] *$/\1/' | xargs -I {} curl -o '{}.jpg' 'https://img.youtube.com/vi/{}/0.jpg'