Welcome, guest | Sign In | My Account | Store | Cart

This is an example of how to use vlc.py . It records an mp3 file from an online audio stream, using the track announcements to write an accompanying cue file.

Python, 103 lines
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
"""
vlc2cue.py

By Anton Vredegoor. Last edit: Monday July 25, 2011.

Send comments to: anton.vredegoor@gmail.com

License: GPL, however there are no warranties, use at your own risk.

This needs vlc.py, see http://wiki.videolan.org/Python_bindings

The idea is to play an online audio stream locally while also 
saving it to an mp3 file and record some meta data in a cue file. 

I made this because I often forget the name of the song I 
listened to, so I have to wait till it is played again, or compare
twitter feeds with the file date of my recorded mp3. And vlc
seems not to record meta info, at least not for mp3.

Writing this also made me appreciate and become more
comfortable with vlc.py. It is very nice! 

As a further benefit, vlc and many other players (foobar f.e.) can 
read cue files. So now I not only have the names of the songs I like 
but by clicking on them in the playlist (a playlist that has multiple 
songs in a single mp3 file) the cursor moves more or less to the 
starting time of the song.  It probably depends on the accuracy 
with which the broadcaster announces the change of track.
"""

import vlc
import time
import os

def new_filename(ext = '.mp3'):
    "find a free filename in 00000000..99999999"
    D = set(x[:8] for x in os.listdir('.')
        if (x.endswith(ext) or x.endswith('.cue')) and len(x) == 12)
    for i in xrange(10**8):
        s = "%08i" %i
        if s not in D:         
            return s

def initialize_cue_file(name,instream,audiofile):
    "create a cue file and write some data, then return it"
    cueout = '%s.cue' %name
    outf = file(cueout,'w')
    outf.write('PERFORMER "%s"\n' %instream)
    outf.write('TITLE "%s"\n' %name)
    outf.write('FILE "%s" WAVE\n' %audiofile)
    outf.flush()
    return outf
    
def initialize_player(instream, audiofile):
    "initialize  a vlc player which plays locally and saves to an mp3file"
    inst = vlc.Instance()   
    p = inst.media_player_new()   
    cmd1 = "sout=#duplicate{dst=file{dst=%s},dst=display}" %audiofile
    cmd2 ="no-sout-rtp-sap"
    cmd3 = "no-sout-standard-sap"
    cmd4 ="sout-keep"
    med=inst.media_new(instream,cmd1,cmd2,cmd3,cmd4)   
    med.get_mrl()    
    p.set_media(med)
    return p, med

def write_track_meta_to_cuefile(outf,instream,idx,meta,millisecs):
    "write the next track info to the cue file"
    outf.write('  TRACK %02i AUDIO\n' %idx)
    outf.write('    TITLE "%s"\n' %meta)
    outf.write('    PERFORMER "%s"\n' %instream)
    m = millisecs // 60000
    s = (millisecs - (m*60000)) // 1000
    hs = (millisecs - (m*60000) - (s*1000)) //10
    ts = '%02i:%02i:%02i'  %(m,s,hs)
    outf.write('    INDEX 01 %s\n' %ts)
    outf.flush()
    
def test():
    #some online audio stream for which this currently works ....
    instream = 'http://streamer-mtc-aa05.somafm.com:80/stream/1018'
    #if the output filename ends with mp3 vlc knows which mux to use
    ext = '.mp3'
    name = new_filename(ext)
    audiofile = '%s%s' %(name,ext)
    outf = initialize_cue_file(name,instream,audiofile)
    p,med = initialize_player(instream, audiofile)
    p.play()
    np = None
    i = 0
    while 1:
        time.sleep(.1)
        new = med.get_meta(12)
        if new != np:
            i +=1
            t = p.get_time()
            print "millisecs: %i" %t
            write_track_meta_to_cuefile(outf,instream,i,new,t)
            np = new
            print "now playing: %s" %np

if __name__=='__main__':
    test()
        
        

This is but a small example of what one can do with vlc.py . I have no connection to vlc or the authors of this module but it works great. The script could use a GUI. I am not quite sure if content holders would appreciate people using this to split the mp3 into separate songs. However the positioning is not very precise and recording audio is already as simple as pushing a button with vlc, so it's not like this would be problematic. However I'd advise to use this only for educational purposes.

1 comment

Anton Vredegoor (author) 10 years, 6 months ago  # | flag

That stream doesn't work anymore, but here's a two line fix to get it working again for an aac stream from the same station. I don't know how long this new stream will be available, but I hope the procedure to adapt the script is clear now.

change line 58: cmd1 = "#transcode{acodec=mp3,ab=128,channels=2,samplerate=44100,hq}:duplicate{dst=file{dst=%s},dst=display}" %audiofile

change line 81: instream = 'http://sfstream1.somafm.com:9002'

Note: it now gets an 64 kb aac stream and converts it to 128 kb mp3