GayMePy Gay Python Guide in Computational Chemistry

Lazy way to get that music right away

Pika

Konnichiwa minasan! Salut tout le monde! Well, I would like to inform you all that I’m still working hard in my promises, but as many of you may already know, we PhD fellows have not only our work to do but many other duties to accomplish before we find some time to our delight as this blog is for me.

So, as many of you might be as lazy as I’m, you know that sometimes you find yourself doing some repetitive work. Well, guess… LOL. As a computational chemist who loves to hear music, one of the things that sometimes bother me is not to have my music on when I’m working. However, living in a very poor country it’s not always that we have the privilege of having internet access all the time - yeah, folks, you can’t even dare to know what it is to live in Brazil. Brazil is not for beginners.

SOOOO, what’s up? Well, have you ever heard about youtube-dl? There are some folks saying it is written in Python, eh? The thing is, imagine you have plans to hear a song you like, but you might be offline when that happens. Then, it is good to be prepared by downloading that song. But that song happens to be within the whole album like this. Unfortunately, you haven’t found only the song you want - because you are too lazy to waste more than 1 minute searching for it. For this example you might found each song separately, but often you can’t find it - or you won’t find it for reasons you know why - and you have to download the whole thing. So what to do?

Well, fear not for I have made this super duper tool for you! Well, kinda. So, you first have to get youtube-dl to work properly in your system, then you want to make sure ffmpeg is also available. Both of them are easy to get, the first you can see here and the second here. Once everything is in place, you can create a file named cutsong.py and place the code below:

#!/usr/bin/env python

from sys import argv
from getopt import getopt, GetoptError
from re import findall
from subprocess import check_output, call
from youtube_dl import YoutubeDL
from glob import glob
from os import rename, remove

def do_the_magic(url, lista):
    ydl_opts = {\
        'format': 'bestaudio/best',\
        'postprocessors': [{\
            'key': 'FFmpegExtractAudio',\
            'preferredcodec': 'mp3',\
            'preferredquality': '192',\
        }]}
    
    with YoutubeDL(ydl_opts) as ydl:
        ydl.download([url])

    mp = glob('*.mp3')[0]
    rename(mp, 'o.mp3')
    cmd = 'ffprobe -i o.mp3 -show_entries format=duration -v \
    quiet -sexagesimal -of csv="p=0"'
    d = check_output([cmd], shell = True).decode('utf8').split('\n')[0]
    h0, m0, s0, l = [], [], [], []
    with open(lista, 'r') as mylist:
        for idx, line in enumerate(mylist):
            label = findall(r'[A-z]+\ ', line)
            timing = findall(r'[0-9]+', line)
            name = "".join(label)
            if len(timing) >= 3:
                h0.append(timing[0])
                m0.append(timing[1])
                s0.append(timing[2])
            elif len(timing) >= 2:
                m0.append(timing[0])
                s0.append(timing[1])
            l.append(name.replace(' ', '_')[:-1])
    if not h0:
        for idx, m in enumerate(m0):
            if idx == len(m0) - 1:
                cmd = 'ffmpeg -i o.mp3 -ss 00:{:s}:{:s} -to {:s} -c \
    copy {:03d}-{:s}.mp3'.format(m, s0[idx], d, idx, l[idx])
            else:
                cmd = 'ffmpeg -i o.mp3 -ss {:s}:{:s} -to {:s}:{:s} -c \
    copy {:03d}-{:s}.mp3'.format(m, s0[idx], m0[idx+1], s0[idx+1], idx, l[idx])
            call([cmd], shell = True)
    else:
        for idx, h in enumerate(h0):
            if idx == len(m0) - 1:
                cmd = 'ffmpeg -i o.mp3 -ss {:s}:{:s}:{:s} -to {:s} -c \
    copy {:03d}-{:s}.mp3'.format(h, m0[idx], s0[idx], d, idx, l[idx])
            else:
                cmd = 'ffmpeg -i o.mp3 -ss {:s}:{:s}:{:s} -to \
    {:s}:{:s}:{:s} -c copy {:03d}-{:s}.mp3'.format(h, m0[idx],\
                                         s0[idx], h0[idx+1], m0[idx+1],\
                                         s0[idx+1], idx, l[idx])
            call([cmd], shell = True)
    remove('o.mp3')

def usage():
    print('''

          Hi there, you might want to call me like this:
            cutsong.py --url '<your url>' --list '<your audio track list>'

          NOTA BENE: inputs must be with quotation mark.

''')
    exit()

if __name__ == '__main__':
    try:
        opts, args = getopt(argv[1:], 'hu:l:', ['help', 'url=', 'list='])
        for o, a in opts:
            if o in ('-h', '--help'):
                usage()
            elif o in ('-u', '--url'):
                url = a
            elif o in ('-l', '--list'):
                lista = a
            else:
                print('\n\nUnhandled operation.\n\n')
                usage()
    except GetoptError as err:
        print('\n', str(err))
        usage()
    do_the_magic(url, lista)

Now, to test it out you can just call it as this:

./cutsong.py --help

Now you might pay attention that very often there are kind people (angels) that leave a tracklist down the comments section of the youtube video. Like the one shown in figure 1 (oh, gosh how formal).

Look mam, band couplings! Figure 1: Beautiful super duper track list found just in the video description.

Anyway, the thing is you may want to copy it down, but pay attention to how things are written in the tracklist. You must have to have one line for each track, each line must have the song title and when it starts. There is no need for when the song ends, only when it starts. Also, there is no right order to place those infos, i.e., the first track must be the first line but the first line might be the track label followed by its start time, or its start time followed by the track label, any of those options will work.

So, now that you have both the script working and your tracklist, you will need to get the URL of youtube that points to the video you want to download. So, you will evoke cutsong.py as this:

./cutsong.py --url 'https://www.youtube.com/watch?v=-ionOzjravQ&t=2s&ab_channel=LadyBluemoon' --list 'list'

Then, you just need to sit and watch everything run. But be aware that it must be done in a place without any ‘.mp3’ file, otherwise you will suffer. :)

Take care.

Byeeeeeee.