简体   繁体   English

编写Python音乐流媒体

[英]Writing a Python Music Streamer

I would like to implement a server in Python that streams music in MP3 format over HTTP. 我想在Python中实现一个服务器,它通过HTTP传输MP3格式的音乐。 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? 以前,我使用SocketServer.TCPServer在Python中实现了自己的HTTP服务器(是的,我知道BaseHTTPServer存在,只是想自己编写一个迷你HTTP堆栈),那么音乐流媒体在架构上会有什么不同呢? What libraries would I need to look at on the network side and on the MP3 side? 我需要在网络端和MP3端看哪些库?

The mp3 format was designed for streaming, which makes some things simpler than you might have expected. mp3格式是专为流媒体设计的,这使得一些事情比你想象的更简单。 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. 这意味着一旦客户端期望接收音频数据,您就可以开始从现有mp3源中的任何点发送字节,无论是实时还是文件,客户端将同步到它找到的下一帧,开始播放音频。 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. 事实上的标准是SHOUTcast(ICY)协议。 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. 这与HTTP非常相似,但是状态和头字段的区别不同,它与Python的内置http服务器库不直接兼容。 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. 你必须阅读他们的代码,以了解如何让他们说SHOUTcast。

Here are a few links to get you started: 以下是一些可以帮助您入门的链接:

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

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

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

http://en.wikipedia.org/wiki/Shoutcast 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. 我建议从单个mp3文件开始作为您的数据源,使客户端 - 服务器连接设置和回放工作,然后继续讨论实时源,多个编码比特率,带内元数据和播放列表等问题。

Playlists are generally either .pls or .m3u files, and essentially just static text files pointing at the URL for your live stream. 播放列表通常是.pls或.m3u文件,基本上只是指向实时流的URL的静态文本文件。 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. 它们并不困难,甚至没有必要,因为许多(大多数?)mp3流媒体客户端将接受没有播放列表的直播流URL。

As for architecture, the field is pretty much wide open. 至于建筑,这个领域非常开阔。 You have as many options as there are for HTTP servers. 您拥有与HTTP服务器一样多的选项。 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. 为了避免IPC和同步复杂化,我可能会从单线程事件驱动设计开始。 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. 在python 2中,像gevent这样的库将为您提供非常好的I / O性能,同时允许您以一种非常容易理解的方式构建代码。 In python 3, I would prefer asyncio coroutines. 在python 3中,我更喜欢asyncio协同程序。

Since you already have good python experience (given you've already written an HTTP server) I can only provide a few pointers on how to extend the ground-work you've already done: 既然你已经拥有良好的python经验(假设你已经编写了一个HTTP服务器),我只能提供一些关于如何扩展你已经完成的基础工作的指示:

  • Prepare your server for dealing with Request Headers like: Accept-Encoding , Range , TE (Transfer Encoding) , etc. An MP3-over-HTTP player (ie VLC) is nothing but an mp3 player that knows how to "speak" HTTP and "seek" to different positions in the file. 准备服务器以处理请求标头,例如: Accept-EncodingRangeTE (Transfer Encoding)等.MP3-over-HTTP播放器(即VLC)只不过是一个知道如何“说”HTTP和MP3的MP3播放器。 “寻找”文件中的不同位置。

  • Use wireshark or tcpdump to sniff actual HTTP requests done by VLC when playing an mp3 over HTTP, so you know how what request headers you'll be receiving and implement them. 使用wireshark或tcpdump来嗅探通过HTTP播放mp3时由VLC完成的实际HTTP请求 ,因此您知道您将接收哪些请求标头并实施它们。

Good luck with your project! 祝你的项目好运!

You'll want to have a .m3u or .pls file that points at a static URI (eg http://example.com/now_playing.mp3 ) then give them mp3 data starting wherever you are in the song when they ask for that file. 你想要一个指向静态URI的.m3u或.pls文件(例如http://example.com/now_playing.mp3 )然后在他们要求的时候从歌曲中的任何地方开始给他们mp3数据文件。 Probably there are a bunch of minor issues I'm glossing over here...However, at least as forest points out, you can just start streaming the mp3 data from any byte. 可能有一些小问题我在这里掩饰......但是,至少森林指出,你可以从任何字节开始流式传输mp3数据。

You'll want to look into serving m3u or pls files. 您需要查看服务m3upls文件。 That should give you a file format that players understand well enough to hit your http server looking for mp3 files. 这应该给你一个文件格式,玩家可以很好地理解你的http服务器寻找mp3文件。

A minimal m3u file would just be a simple text file with one song url per line. 最小的m3u文件只是一个简单的文本文件,每行有一个歌曲网址。 Assuming you've got the following URLs available on your server: 假设您的服务器上有以下URL:

/playlists/<playlist_name/playlist_id>
/songs/<song_name/song_id>

You'd serve a playlist from the url: 您将从网址提供播放列表:

/playlists/myfirstplaylist

And the contents of the resource would be just: 资源的内容只是:

/songs/1
/songs/mysong.mp3

A player (like Winamp) will be able to open the URL to the m3u file on your HTTP server and will then start streaming the first song on the playlist. 播放器(如Winamp)将能够打开HTTP服务器上m3u文件的URL,然后开始播放播放列表中的第一首歌曲。 All you'll have to do to support this is serve the mp3 file just like you'd serve any other static content. 所有你需要做的就是支持这个就像你提供任何其他静态内容一样提供mp3文件。

Depending on how many clients you want to support you may want to look into asynchronous IO using a library like Twisted to support tons of simultaneous streams. 根据您希望支持的客户端数量,您可能希望使用像Twisted这样的库来查看异步IO,以支持大量的并发流。

Study these before getting too far: 在走得太远之前研究这些:

http://wiki.python.org/moin/PythonInMusic http://wiki.python.org/moin/PythonInMusic

Specifically 特别

http://edna.sourceforge.net/ http://edna.sourceforge.net/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM