Page 1 of 2 12 LastLast
Results 1 to 10 of 19

Thread: Python script to record Pandora internet radio (done!)

  1. #1
    Join Date
    Oct 2013
    Beans
    13

    Python script to record Pandora internet radio (done!)

    Hello all. Here's my second Ubuntu forums thread. This time I've written a rough Python script to record streaming Pandora audio.
    The goals of the project were as follows:
    1. No use of the web interface which would mean using flash. Use pianobar program as backend instead,
    2. Sort songs into a folder hierarchy. Artist/Album/Song. Basically create the non-existent ones on the fly.
    3. Save as either .ogg or .mp3 with same quality as the sound coming out of the speakers.

    The goals at this time do not include interaction. It's just run it and sit back while it builds you a local library.

    This script uses python's popen methods to communicate with a pianobar process(play) and a avconv process(record). Avconv simply grabs the audio output from the speakers and records it in this case. Unfortunately, this means that anything else coming through the sound card will be recorded along with the song. This wasn't a concern for me because I was thinking of just having a headless machine in the corner set up to record.

    For this to work you will need to:

    1. Install libav-tools package and pianobar package from the software center.
    2. edit the line in /etc/pulse/daemon.conf that looks like this:
    Code:
    ;default-sample-rate = whatever it was before
    and change it to this:
    Code:
    default-sample-rate = 48000
    So basically uncomment that line and change the rate to 48000.

    3.
    Here is the original code for recording indefinetely to a file from your speakers:
    Code:
    avconv -f pulse -i alsa_output.pci-0000_00_14.2.analog-stereo.monitor -acodec libvorbis -ac 2 -ar 48000 -vn out.ogg
    Note that this is set up for my specific sound card output. So this is the next task.
    Open a terminal and enter this:
    Code:
    pactl list sources
    Your most likely looking for Source #0 and you will have to copy and paste what shows up under Name: into my python code in place of what I have there for my soundcard.
    Mine was this:
    Code:
     alsa_output.pci-0000_00_14.2.analog-stereo.monitor
    So just edit that one line of my script, but be careful not to remove the quotes.

    To run the script, open a terminal and cd to the script, then do:
    Code:
    python record-pandora_1.0.py
    Here's the script:
    Code:
    import subprocess, time, os
    
    def startRecord(playingInfo1, playingInfo2, playingInfo3):
        global p2
        try: #try to create new artist dir if not already there
            if(not os.path.exists("music/" + playingInfo1)):
                os.mkdir("music/" + playingInfo1)
                print "Created new Artist dir"
            #create new Album dir if not already there
            if(not os.path.exists("music/" + playingInfo1 + "/" + playingInfo2)):
                os.mkdir("music/" + playingInfo1 + "/" + playingInfo2)
                print "Created new Album dir"
            #record new song if not already recorded
            if(not os.path.exists("music/" + playingInfo1 + "/" + playingInfo2 + "/" + playingInfo3 + ".ogg")):
                try: ### the next line is for specific sound card, edit it
                    avconvCmd = "avconv", "-f", "pulse", "-i", "alsa_output.pci-0000_00_14.2.analog-stereo.monitor", "-acodec", "libvorbis", "-ac", "2", "-ar", "48000", "-vn" , 'music/' + playingInfo1 + '/' + playingInfo2 + '/' + playingInfo3 + '.ogg'
                    p2 = subprocess.Popen(avconvCmd)
                    print "Created new Song file, now recording...\n"
                except:
                    print "Error opening avconv! Is libav-tools installed?\n"
        except:
            print "Couldn't create new Song file!\n"
                    
            
    
    
    ### program start here ###
    
    #variables and lists
    p2 = ""
    
    #create music dir if it doesn't exist
    if(not os.path.exists("music")):
        os.mkdir("music")
    
    #try to run pianobar
    try:
        cmd = "pianobar"
        p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE)
        output = p.stdout.readline()
    except:
        print "Error opening pianobar! Is it installed?\n"
    
    while(output):
        if('|>  "' in output): #beginning of songs playing
            try:
                p2.kill() #kill recording of last song
            except:
                print
            try: #try to clean up and format pianobar's output
                cleanPianobarChars = output.split('|>  "', 1)
                songName = cleanPianobarChars[1].split('" by "', 1)
                artistName = songName[1].split('" on "', 1)
                albumName = artistName[1].split('"', 1)
                #put Artist name, Album name and Song name into a list
                playingInfo1 = artistName[0]
                playingInfo2 = albumName[0]
                playingInfo3 = songName[0]
                print "\nArtist: " + playingInfo1 + "\nAlbum: " + playingInfo2 + "\nSong: " + playingInfo3 + "\n"
                #start dir check or creation and record to file
                startRecord(playingInfo1, playingInfo2, playingInfo3)
            except:
                print "Something went wrong with cleaning up pianobar output...\n"
        output = p.stdout.readline()
    Enjoy!

  2. #2
    Join Date
    Oct 2013
    Beans
    13

    Re: Python script to record Pandora internet radio (done!)

    Hello again,

    I've revised and updated the code and instructions somewhat.
    Differences in code and functionality:
    1. Bugfixes: Now records whole song instead of cutting off the last few seconds
    2. Now supports configuration files! no need to edit the code for your specific sound card. Eg: record-pandora.conf
    3. Now supports ads detection. In my experience, in odd cases ads can slip through and play through pianobar. On the second line of record-pandora.conf, put a number Eg: 800. This is the minimum recorded file size to keep after recording. Any song this number size and under will be deleted.
    4. Now supports artist whitelist. Eg: whitelist-artists.txt This will not skip the non-whitelisted song (too many issues) it will simply not record it.

    Instructions:
    1. You don't need to edit /etc/pulse/daemon.conf Just run this:
    Code:
    pactl list sources
    and get the Source. Mine was this:
    Code:
    alsa_output.pci-0000_00_1b.0.analog-stereo.monitor
    and put it in record-pandora.conf as the first line.

    2. Put your preferred Kilobyte size on the second line of record-pandora.conf. Example conf file would be:
    Code:
    alsa_output.pci-0000_00_1b.0.analog-stereo.monitor
    800
    This line is for new feature 3 listed above.

    3. Optional, create a whitelist-artists.txt file with the names of the artists you only want to hear/record. Each line must be capitalized as pianobar shows them and the last line must have a blank line under it. Example:
    Code:
    Modest Mouse
    Pink Floyd
    4. You must set up pianobar prior to running this script. First make a pianobar conf file: /home/username/.config/pianobar/config It should contain: At least a user = pandorausername line and a password = pandorapassword line. Thats 2 seperate lines.

    4.1 Then run pianobar for the first time and select the station to play. Then press q. This is all that is needed in pianobar to run my script. If you want to change stations repeat this step.

    5. All config files must be in the same directory as the record-pandora.py and make sure you have packages libav-tools and pianobar installed and then open a terminal in the same directory as the record-pandora.py and do:
    Code:
    ./record-pandora.py
    Enjoy!

    Here's the revised code to save into a new file:

    Code:
    #!/usr/bin/python
    import subprocess, time, os
    
    def startRecord(playingInfo1, playingInfo2, playingInfo3):
        try: #try to create new artist dir if not already there
            if(not os.path.exists("music/" + playingInfo1)):
                os.mkdir("music/" + playingInfo1)
                print "Created new Artist dir"
            #create new Album dir if not already there
            if(not os.path.exists("music/" + playingInfo1 + "/" + playingInfo2)):
                os.mkdir("music/" + playingInfo1 + "/" + playingInfo2)
                print "Created new Album dir"
            #record new song if not already recorded
            if(not os.path.exists("music/" + playingInfo1 + "/" + playingInfo2 + "/" + playingInfo3 + ".ogg")):
                try: ### the next line is for specific sound card, edit it
                    os.system('avconv -loglevel panic -f pulse -i ' + audioDevName + ' -acodec libvorbis -ac 2 -vn "music/' + playingInfo1 + '/' + playingInfo2 + '/' + playingInfo3 + '.ogg" &')
                    print "Created new Song file, now recording...\n"
                except:
                    print "Error opening avconv! Is libav-tools installed?\n"
        except:
            print "Couldn't create new Song file!\n"
                    
    
    ### program start here ###
    
    #variables and lists
    p2 = ""
    
    #create music dir if it doesn't exist
    if(not os.path.exists("music")):
        os.mkdir("music")
        
    #read configuration file
    try:
        if(os.path.exists("record-pandora.conf")):
            confFile = open("record-pandora.conf", "r")
            audioDevName = confFile.readline()
            audioDevName = audioDevName.rstrip("\n")
            delFileSize = confFile.readline()
            delFileSize = delFileSize.rstrip("\n")
            confFile.close()
        else:
            print "record-pandora.conf not found, please create it\nwith your audio device name and desired delete file size in bytes.\n"
            print "Example:\nalsa_output.pci-0000_00_14.2.analog-stereo.monitor\n800"
    except:
        print "Error trying to read conf file"
    
    ### whitelist section ###
    def whiteListArtists():
        try:
            if(os.path.exists("whitelist-artists.txt")):
                whitelistArtists = open("whitelist-artists.txt", "r")
                whitelistArtistsList = whitelistArtists.readlines()
                whitelistArtists.close()
            else:
                whitelistArtistsList = ""
                print "Couldn't find whitelist-artists.txt.\nWill play/record all. "
        except:
            print "Error tying to read whitelist-artists.txt"
        
        return(whitelistArtistsList)
    ### end whitelist section ###
        
    #try to run pianobar
    try:
        cmd = "pianobar"
        p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE)
        output = p.stdout.readline()
    except:
        print "Error opening pianobar! Is it installed?\n"
    
    while(True):
        if('|>  "' in output): #beginning of songs playing
            try:
                #kill recording of last song
                os.system("killall avconv")
                if(os.path.getsize("music/" + playingInfo1 + "/" + playingInfo2 + "/" + playingInfo3 + ".ogg") <= int(delFileSize)):
                    os.remove("music/" + playingInfo1 + "/" + playingInfo2 + "/" + playingInfo3 + ".ogg")
                    print "Removed: music/" + playingInfo1 + "/" + playingInfo2 + "/" + playingInfo3 + ".ogg"
            except:
                print
            try:
                #try to clean up and format pianobar's output
                cleanPianobarChars = output.split('|>  "', 1)
                songName = cleanPianobarChars[1].split('" by "', 1)
                artistName = songName[1].split('" on "', 1)
                albumName = artistName[1].split('"', 1)
                #put Artist name, Album name and Song name into a list
                playingInfo1 = artistName[0]
                playingInfo2 = albumName[0]
                playingInfo3 = songName[0]
                #skip all artists not in whitelist
                whiteList = whiteListArtists()
                if(playingInfo1 + "\n" in whiteList or whiteList == ""):
                    print "\nArtist: " + playingInfo1 + "\nAlbum: " + playingInfo2 + "\nSong: " + playingInfo3 + "\n"
                    #start dir check or creation and record to file
                    startRecord(playingInfo1, playingInfo2, playingInfo3)
                else:
                    print "Not recording\nArtist: " + playingInfo1 + "\nAlbum: " + playingInfo2 + "\nSong: " + playingInfo3 + "\n(Not in whitelist)\n"
            except:
                print "Something went wrong with cleaning up pianobar output...\n"
        output = p.stdout.readline()
    Last edited by inexplikibled; August 2nd, 2014 at 09:15 PM.

  3. #3
    Join Date
    Aug 2014
    Beans
    1

    Re: Python script to record Pandora internet radio (done!)

    What would the difference in quality be between using this script, great work by the way, and inspecting elements on the pandora page and downloading the song from the source?

  4. #4
    Join Date
    Oct 2013
    Beans
    13

    Re: Python script to record Pandora internet radio (done!)

    While I haven't done much research into how pandora web client works(I think it uses flash), I believe pianobar (what my script uses) and pithos (a great gui pandora app) both use tags in pandoras site to stream the music as is anyway. So I guess my answer would be: Unless you have a pay for Pandora account, the quality whould be the same with web or with pianobar. Of couse pay for Pandora accounts provide higher quality streaming access, so that would probably improve the quality of the end recording. Thanks for the complement too!

    Also, I've updated the code in my second post so that the whitelist-artists.txt file can be edited while the script is running so you don't have to stop recording. It re-reads it on every new song.
    Last edited by inexplikibled; August 2nd, 2014 at 09:17 PM.

  5. #5
    Join Date
    Dec 2014
    Beans
    2

    Re: Python script to record Pandora internet radio (done!)



    Anyone have this running on raspberry pi?

    thanks..
    Last edited by sparky5; December 25th, 2014 at 11:17 PM.

  6. #6
    Join Date
    Oct 2013
    Beans
    13

    Re: Python script to record Pandora internet radio (done!)

    Hi sparky5 in reply to a message from you in my email (can't seem to find that post here):
    Does it also at some point say:
    sh: 1: avconv: not found
    If that's the case, have you installed libav-tools so that avconv is available to my script?
    Code:
    sudo apt-get install libav-tools
    Each time you start the script it will say:
    avconv: no process found
    as it's first output, but thats only because the first action is to kill all avconv processes that may be running so that it can start a new one to record. Since there was no avconv process running yet, it outputs that message.

    As far as it working on the raspberry pi... Well honestly that would be great. It consumes very little power so leaving it running wouldn't be an issue. However I'm not sure if the pi has enough processing power to actually encode the audio to a file in real time without stutter or something. I have thought about trying this out on one of my pi's but never have yet. I might give it a try sometime though and post back with results. A good size USB drive would probably be a good idea to store the recordings if it did work.

  7. #7
    Join Date
    Dec 2014
    Beans
    2

    Re: Python script to record Pandora internet radio (done!)

    Thanks for the reply. I found that I had not insgtalled libav-tools.. and the first avconv: no process found message had distracted me. I have it running on an old laptop under ubuntu. I started trying to get your code running on a raspberry, with no luck. pianobar runs fine, and your code starts and creates the directories, but no music files. Now that I have it running on a different system, I'll go back and see what I can do again on the raspberry.
    Thanks again

  8. #8
    Join Date
    Jul 2012
    Beans
    3

    Re: Python script to record Pandora internet radio (done!)

    I can't seem to get the script to work. I have the libav-tools installed, and it's not giving any of those libav related messages like the replies above. When I execute the script with ./, I get this message:
    Code:
    jake@jake-MS-7759:~/.config/pianobar$ ./record-pandora.py
    from: can't read /var/mail/pithos.plugin
    from: can't read /var/mail/pithos.pithosconfig
    from: can't read /var/mail/mutagen.mp4
    import: unable to open image `os': Permission denied @ error/blob.c/OpenBlob/2709.
    from: can't read /var/mail/shutil
    from: can't read /var/mail/glob
    ./record-pandora.py: line 24: syntax error near unexpected token `('
    ./record-pandora.py: line 24: `class SavePlugin(PithosPlugin):'
    When I invoke python to run the command, I get less text output. It looks like this:

    Code:
    jake@jake-MS-7759:~/.config/pianobar$ python record-pandora.py
    Traceback (most recent call last):
      File "record-pandora.py", line 17, in <module>
        from pithos.plugin import PithosPlugin
    ImportError: No module named pithos.plugin
    Anyone know how to get it working?

  9. #9
    Join Date
    Oct 2013
    Beans
    13

    Re: Python script to record Pandora internet radio (done!)

    Hello nanoViral, Can you give me some more info?

    1. What version of Ubuntu are you running?
    2. Did you install pianobar?

    The errors you're getting don’t look like they're actually related to my script.

    Your .config/pianobar/config file should look like this with two lines:
    user = yourpandorausername
    password = yourpandorapassword

    You have to run pianobar itself first before running my script so that you can set it up to play the stations you want. So in a terminal:
    Code:
    pianobar
    Another thing you may want to try is to put record-pandora.py in a standard directory such as /home/yourusername/Documents/record-pandora.py or in another standard directory and then run it from there. I'm guessing some of the problem may be related to running it in the hidden .config/pianobar/ directory. That is, if that's where your running it from...

    Last, double check that you copied all the code for my script correctly.

  10. #10
    Join Date
    Jul 2012
    Beans
    3

    Re: Python script to record Pandora internet radio (done!)

    So, I had the code from a completely different script (written by someone else haha) instead of yours, but named the same and with the config file unchanged. It kinda works now...I followed your advice and put the script-config in documents. It ran, and created a music folder. But no matter how many times I run the script, hit q, and restart pianobar, (pianobar and the script running in different terminals) no music is created in the music folder. It doesn't print anything after I run the script either, but It's definitely since it created the folder. (Plus it doesn't print the working directory, so it's running.) My config looks like this:

    alsa_output.pci-0000_00_1b.0.analog-stereo.monitor
    128

    I'm running ubuntu 15.04.

Page 1 of 2 12 LastLast

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •