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

This script can be used to stream an existing mp3 file to multiple computers. It has a simple Tkinter GUI with only one button to start/stop the stream, and a slider to indicate or change the position.

Python, 129 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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#!/usr/bin/python

"""
author email: anton.vredegoor@gmail.com
last edit: June 9, 2013
license: GPL

this uses vlc.py to stream an mp3 file, 
for example to some addresses on a lan.

installing:
------------

-first create a file named "vlc2all.m3u" with the 
following content:

#EXTM3U
rtp://@:50004

-copy vlc2all.m3u to some computer

-modify this script to include the computer's ip address,
 it's in the 'destinations' tuple at the end of this script
 
running:
------------

-start the script:
>>> python vlc-stream.py some.mp3

-a tkinter window appears, click 'go' to start streaming

-listen to the stream by opening vlc2all.m3u on the 
receiving computer (of course open it with vlc!)

"""
from Tkinter import *
import vlc
import os
import sys

class App:
    
    def __init__(self,master,instream,destinations):
        self.master=master
        self.instream = instream
        self.destinations = destinations
        self.initialized,self.playing,self.changed,self.newpos = False,False,False,0
        self.initialize_player()
        self.master.bind("<Escape>", lambda _ : self.master.destroy())
        self.container=Frame()
        self.container.pack(fill=BOTH,expand=YES)
        self.slider = Scale(self.container, from_= 0, to=100, orient=HORIZONTAL,\
                command=lambda _: self.setpos())
        self.slider.pack(side=BOTTOM,fill=BOTH,expand=YES)
        self.urlbar = Text(self.container)
        self.urlbar.pack(side=LEFT,fill=BOTH,expand=YES)
        self.urlbar.delete(1.0,END)
        self.urlbar.insert(END, url)
        self.button1=Button(self.container, text='GO', command= self.playurl, width=80)
        self.button1.pack(side=RIGHT,fill=BOTH,expand=YES);

    def initialize_player(self):
        "initialize  a vlc player which plays locally and stream to the lan"
        self.inst = vlc.Instance()   
        self.p = self.inst.media_player_new() 
        cmd = [self.instream]
        s = "sout=#duplicate{"
        for ip,port in self.destinations:
            s+="dst=rtp{dst=%s,port=%s}," %(ip,port)
        s = s[:-1]
        s+="}"
        cmd.append(s)
        cmd.append("no-sout-rtp-sap")    
        cmd.append("no-sout-standard-sap")
        cmd.append("sout-keep")
        self.med=self.inst.media_new(*cmd)   
        self.med.get_mrl()    
        self.p.set_media(self.med)
        self.initialized = True
        
    def setpos(self):
        self.oldpos = self.newpos
        self.newpos = self.slider.get()
        #a bit of a hack, but this should prevent slider callbacks
        #not involving a mouse adjustment messing up the sound position
        if self.newpos-self.oldpos <> 1:
            self.changed = True
    
    def poll(self):
        #song ended?
        if self.p.get_state()==6:
            self.pauseurl()
            self.p.set_media(self.med)
        #slider adjusted?
        if self.changed:
            self.p.set_position(self.newpos/100.0)
            self.changed=False
        pos = self.p.get_position()
        self.slider.set(pos*100.0)
        self.master.after(100,self.poll)
    
    def pauseurl(self):
        if self.playing:
            self.p.set_pause(1)
            self.playing = False
            self.button1.configure(text = "GO",command = self.playurl)

    def playurl(self):
        if not self.playing:
            self.p.play()
            self.playing = True
        self.button1.configure(text = "PAUSE",command = self.pauseurl)
        self.poll()

if __name__=='__main__':
    if len(sys.argv)>1:
        fn = sys.argv[1]
    else:
        fn = "00000000.mp3"
    outport = 50004
    url = "file://"+os.path.abspath(fn)
    destinations = ("192.168.123.122",outport),("192.168.123.125",outport),\
        ("192.168.123.188",outport),("192.168.123.190",outport)
    root=Tk()
    root.geometry("680x80")
    root.title("vlc-stream")
    a = App(root,url,destinations)
    root.mainloop()






    
        
        
        
        

This script is useful for people who want to plug their headphones into a different computer than the one which the mp3 is stored on, or who want to have the audio available in multiple places simultaneously. I chose this solution because I like vlc and prefer controlling it using vlc.py. One should create a playlist file on the receiving computer to access the rtp stream, in order to not have to repeat typing too much stuff. On windows the script should be adapted, use an extra slash in the "file://" url. It is possible to run the script from a left click mouse menu by creating a desktop entry ~/.local/share/applications/vlc-stream.desktop. The GUI is extremely minimal. On the TODO list is an integration with my other script which downloads mp3 and creates cue files. The script uses a file called "00000000.mp3" in case it is called without arguments, but that file is not included here. When editing and testing the script it is handy to place a file with that name in the directory the script is in.

1 comment

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

Unfortunately, the last version of vlc that I know this script works for is 2.1.6 Rincewind.