Bash scripting fun
Tuesday, 8 January 2019 20:01Music CDs are fragile and annoying things, sometimes. Especially if they play perfectly fine, but cannot be read for conversion on the computer. I've run into quite a few CDs like that while working on digitalising my entire music collection. Sometimes, I've managed to find the same albums for download, so that I could add them to my collection anyway. The main difference here is that downloads are mostly in MP3 format, while I convert to FLAC when I do it from the CD.
Maybe this sounds silly, but I don't really notice that difference much, as long as the MP3 is not obviously of very low quality.
Anyway, googling for downloads of flawed CDs is time-consuming and often difficult, so I've learnt to check Youtube first of all. There are lots of full albums there, and they're even neatly sorted in playlists, which means you can get just one link for the entire album. With youtube-dl installed, it's possible to download these playlists, and with the right arguments set, you can save everything as MP3 instead of video files.
So, youtube-dl does what I want... only, it needs a bunch of arguments for that, and I don't really remember which ones are needed, so I used to look that up every time I wanted to download something. Now that I've become more aware of just how much material is available straight from Youtube, I figured I needed a script to simplify the downloading... and so I decided to try to make one.
You know I can't code, right? The most I've done before is make a few scripts that run a few commands in a row, and I've also done a few versions of the obligatory "Hello world" learning script, but that's all. For the youtube downloading script, I wanted to be able to use the same one both for playlists and single songs, so this is already a bit more than I've done before. I had a basic idea of what the code would need to do to accomplish what I wanted, though, so I figured it would be a fun challenge to see if I could make the script.
So, what does it do? It asks for a Youtube URL, which is then stored in a variable. Then it asks whether the URL is a playlist. (Yes/No or Y/N are acceptable answers, everything else returns "Invalid input"). Depending on your answer, it executes either the download code for playlists or individual songs. Oh, and files are saved to a specific "YT" folder under your "Music" folder.
Now, getting it to store the URL was easy enough. Then the first challenge was how to make sure the playlist question is answered properly. When I first tested this out, I simply created a variable for whatever answer the user supplied on that question, but of course that would be a bug if the user inputted some garbage instead of Y/N. Also, how to make it accept either full words, or just single letters, and make it case-insensitive? Okay, after a bit of googling I figured I could do it with a case statement.
So, the next bit proved the most difficult. Execute one bit of download code if the URL is a playlist, and another if it isn't. Understanding that I had to use an if/else statement for this was not the hard part... but I kept getting errors no matter what I did to my commands inside those statements. I didn't understand this, as the same commands work fine when used directly in the terminal window - I was simply copy/pasting the same set of command and arguments I always use.
Now, at first I was simply typing my code up in a regular text editor, but then I downloaded one that has both a built in terminal for testing, AND code highlighting (and probably a ton of other coding functionality that I have no chance of understanding yet). Okay, now it got much easier to see which code belongs together, and whether there is a missing closing " or ' or ) somewhere, because if something is not closed, the whole rest of the code gets the wrong colouring. So, the first flaws I noticed were a couple of extra spaces. Then, after some more fidgeting around, I finally figured out that I needed quotation marks around the path to the YT folder in the downloading command/arguments.
And, yes - I have a working script to download music from Youtube, now!!
Also, yes - I realise that it still needs a few tweaks. Like, right now everything is saved to the same folder, so if you download more than one album/song, you need to go in there manually and put things in the right folders if you don't want that folder to get messy. It should be possible to add a question to name a subfolder that will be used instead of the main YT folder.
Also, I haven't checked yet, but I believe there must be a bug that makes the script break if you input an invalid Youtube URL. Surely, there should be some way to check that the URL is valid - or at least that it follows URL structure, and isn't just "yajldjfldaj" or some other garbage.
This is for tomorrow or some other day soon, though. But right now, I'm quite proud of making my first "real" script that actually does something useful.
Maybe this sounds silly, but I don't really notice that difference much, as long as the MP3 is not obviously of very low quality.
Anyway, googling for downloads of flawed CDs is time-consuming and often difficult, so I've learnt to check Youtube first of all. There are lots of full albums there, and they're even neatly sorted in playlists, which means you can get just one link for the entire album. With youtube-dl installed, it's possible to download these playlists, and with the right arguments set, you can save everything as MP3 instead of video files.
So, youtube-dl does what I want... only, it needs a bunch of arguments for that, and I don't really remember which ones are needed, so I used to look that up every time I wanted to download something. Now that I've become more aware of just how much material is available straight from Youtube, I figured I needed a script to simplify the downloading... and so I decided to try to make one.
You know I can't code, right? The most I've done before is make a few scripts that run a few commands in a row, and I've also done a few versions of the obligatory "Hello world" learning script, but that's all. For the youtube downloading script, I wanted to be able to use the same one both for playlists and single songs, so this is already a bit more than I've done before. I had a basic idea of what the code would need to do to accomplish what I wanted, though, so I figured it would be a fun challenge to see if I could make the script.
So, what does it do? It asks for a Youtube URL, which is then stored in a variable. Then it asks whether the URL is a playlist. (Yes/No or Y/N are acceptable answers, everything else returns "Invalid input"). Depending on your answer, it executes either the download code for playlists or individual songs. Oh, and files are saved to a specific "YT" folder under your "Music" folder.
Now, getting it to store the URL was easy enough. Then the first challenge was how to make sure the playlist question is answered properly. When I first tested this out, I simply created a variable for whatever answer the user supplied on that question, but of course that would be a bug if the user inputted some garbage instead of Y/N. Also, how to make it accept either full words, or just single letters, and make it case-insensitive? Okay, after a bit of googling I figured I could do it with a case statement.
So, the next bit proved the most difficult. Execute one bit of download code if the URL is a playlist, and another if it isn't. Understanding that I had to use an if/else statement for this was not the hard part... but I kept getting errors no matter what I did to my commands inside those statements. I didn't understand this, as the same commands work fine when used directly in the terminal window - I was simply copy/pasting the same set of command and arguments I always use.
Now, at first I was simply typing my code up in a regular text editor, but then I downloaded one that has both a built in terminal for testing, AND code highlighting (and probably a ton of other coding functionality that I have no chance of understanding yet). Okay, now it got much easier to see which code belongs together, and whether there is a missing closing " or ' or ) somewhere, because if something is not closed, the whole rest of the code gets the wrong colouring. So, the first flaws I noticed were a couple of extra spaces. Then, after some more fidgeting around, I finally figured out that I needed quotation marks around the path to the YT folder in the downloading command/arguments.
And, yes - I have a working script to download music from Youtube, now!!
Also, yes - I realise that it still needs a few tweaks. Like, right now everything is saved to the same folder, so if you download more than one album/song, you need to go in there manually and put things in the right folders if you don't want that folder to get messy. It should be possible to add a question to name a subfolder that will be used instead of the main YT folder.
Also, I haven't checked yet, but I believe there must be a bug that makes the script break if you input an invalid Youtube URL. Surely, there should be some way to check that the URL is valid - or at least that it follows URL structure, and isn't just "yajldjfldaj" or some other garbage.
This is for tomorrow or some other day soon, though. But right now, I'm quite proud of making my first "real" script that actually does something useful.