Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Writing a Python Music Streamer

I would like to implement a server in Python that streams music in MP3 format over HTTP. I would like it to broadcast the music such that a client can connect to the stream and start listening to whatever is currently playing, much like a radio station.

Previously, I've implemented my own HTTP server in Python using SocketServer.TCPServer (yes I know BaseHTTPServer exists, just wanted to write a mini HTTP stack myself), so how would a music streamer be different architecturally? What libraries would I need to look at on the network side and on the MP3 side?

like image 502
AJ. Avatar asked Apr 16 '11 18:04

AJ.


People also ask

How do I stream music with Python?

You just have to create an instance of VLC player and pass the path of a media file to be played to a play() function provided by Python-VLC library. It can also be used to stream online music. You can also create a playlist using functions provided by the library and play the playlist from Python script itself.

Can Python make music?

Pymps - Pymps is the PYthon Music Playing System - a web based mp3/ogg jukebox. It's written in Python and utilises the PostgreSQL database. MusicPlayer - MusicPlayer is a high-quality music player implemented in Python, using FFmpeg and PortAudio. Pymserv - PyMServ is a graphical client for mserv, a music server.

How does a music streamer work?

Music streaming works in a very simple way: a streaming service delivers data to a streamer in small amounts so that the user can get pre-buffered music that has been pre-buffered a few minutes or even seconds before playing a song.


1 Answers

The mp3 format was designed for streaming, which makes some things simpler than you might have expected. The data is essentially a stream of audio frames with built-in boundary markers, rather than a file header followed by raw data. This means that once a client is expecting to receive audio data, you can just start sending it bytes from any point in an existing mp3 source, whether it be live or a file, and the client will sync up to the next frame it finds and start playing audio. Yay!

Of course, you'll have to give clients a way to set up the connection. The de-facto standard is the SHOUTcast (ICY) protocol. This is very much like HTTP, but with status and header fields just different enough that it isn't directly compatible with Python's built-in http server libraries. You might be able to get those libraries to do some of the work for you, but their documented interfaces won't be enough to get it done; you'll have to read their code to understand how to make them speak SHOUTcast.

Here are a few links to get you started:

http://forums.winamp.com/showthread.php?threadid=70403

http://forums.radiotoolbox.com/viewtopic.php?t=74

http://www.smackfu.com/stuff/programming/shoutcast.html

http://en.wikipedia.org/wiki/Shoutcast

I suggest starting with a single mp3 file as your data source, getting the client-server connection setup and playback working, and then moving on to issues like live sources, multiple encoding bit rates, inband meta-data, and playlists.

Playlists are generally either .pls or .m3u files, and essentially just static text files pointing at the URL for your live stream. They're not difficult and not even strictly necessary, since many (most?) mp3 streaming clients will accept a live stream URL with no playlist at all.

As for architecture, the field is pretty much wide open. You have as many options as there are for HTTP servers. Threaded? Worker processes? Event driven? It's up to you. To me, the more interesting question is how to share the data from a single input stream (the broadcaster) with the network handlers serving multiple output streams (the players). In order to avoid IPC and synchronization complications, I would probably start with a single-threaded event-driven design. In python 2, a library like gevent will give you very good I/O performance while allowing you to structure your code in a very understandable way. In python 3, I would prefer asyncio coroutines.

like image 192
ʇsәɹoɈ Avatar answered Oct 02 '22 03:10

ʇsәɹoɈ