2011-04-16 71 views
20

我想实现一个Python中的服务器,通过HTTP流式传输MP3格式的音乐。我希望它播放音乐,以便客户端可以连接到流,并开始听任何正在播放的内容,就像电台一样。编写一个Python音乐流光

以前,我使用SocketServer.TCPServer在Python中实现了自己的HTTP服务器(是的,我知道BaseHTTPServer存在,只是想自己编写一个迷你HTTP协议栈),所以音乐流媒体如何在架构上有所不同?我需要在网络端和MP3端查看哪些库?

+0

你想让VLC这样的东西能够链接到流中,还是只编写自己的客户端? – thenoviceoof 2011-04-17 06:24:50

+0

@thenoviceoof - 很好的问题,是的,我想要“主流”的客户端能够连接。 iTunes,Winamp,VLC等 – 2011-04-17 09:15:56

+0

您是在实时压缩音频还是在流式传输预先创建的MP3文件? – rakslice 2011-04-24 01:41:48

回答

26

mp3格式是专为流式传输而设计的,它使得一些事情比您预想的要简单。数据本质上是一个audio frames的流,带有内置的边界标记,而不是文件头,然后是原始数据。这意味着,一旦客户希望接收音频数据,您就可以从现有mp3源中的任意点开始发送字节,无论是实时还是文件,并且客户端将同步到它找到的下一帧,开始播放音频。好极了!

当然,您必须为客户提供设置连接的方法。事实上的标准是SHOUTcast(ICY)协议。这非常类似于HTTP,但是状态和头部字段的差异足以与Python内置的http服务器库不直接兼容。您可能可以让这些库为您完成一些工作,但他们记录的接口不足以完成它;你必须阅读他们的代码才能理解如何让他们说出SHOUTcast。

这里有一些链接,让你开始:

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

我建议从一个单一的MP3文件作为数据源,获取客户端 - 服务器连接设置和p后期工作,然后继续讨论诸如实时数据源,多种编码比特率,带内元数据和播放列表等问题。

播放列表通常是.pls或.m3u文件,基本上只是指向您的直播流的URL的静态文本文件。它们并不困难,甚至不是绝对必要的,因为许多(大多数?)mp3流媒体客户端将接受没有播放列表的实时流URL。

至于建筑,这个领域是非常开放的。您拥有与HTTP服务器相同的选项。螺纹?工作进程?事件驱动?随你便。对我而言,更有趣的问题是如何将来自单个输入流(广播公司)的数据与服务于多个输出流(播放器)的网络处理器共享。为了避免IPC和同步问题,我可能会从单线程事件驱动设计开始。在Python 2中,像gevent这样的库会给你very good I/O performance,同时允许你以一种非常容易理解的方式构建代码。在python 3中,我更喜欢asyncio协程。

+0

会动态生成.mp3数据需要高级的python编程吗? – MikeiLL 2014-09-09 23:42:29

0

你会想看看服务m3upls文件。这应该给你一个文件格式,让玩家理解得足以击中你的http服务器寻找mp3文件。

一个最小的m3u文件只是一个简单的文本文件,每行一首歌曲url。假设你有以下网址提供的服务器上:

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

你会成为从URL播放列表:

/playlists/myfirstplaylist 

和资源的内容将只是:

/songs/1 
/songs/mysong.mp3 

一位玩家(如Winamp)将能够打开您的HTTP服务器上的m3u文件的URL,然后开始播放播放列表中的第一首歌曲。您需要做的所有事情都是为了支持这一点,就像服务于任何其他静态内容一样。

取决于您希望支持多少客户端,您可能希望使用像Twisted这样的库来查看异步IO以支持大量同步流。越来越走得太远

+4

这听起来很像我喜欢的SHOUTcast(http://en.wikipedia.org/wiki/SHOUTcast)。我的问题是:如何使其工作,使“播放列表”文件只是一个通用的URL,指向“流”,而不是一个特定的MP3文件?即使URL是“/somefile.mp3”,我也不希望为每首歌曲**生成一个播放列表。相反,我希望它是一个连续不断的歌曲/广告等,就像电台一样。事实上,这是一个很好的例子。广播电台如何从他们的网站上做到这一点,你可以在那里收听他们的现场直播? – 2011-04-22 12:41:15

+0

我假设他们只是继续将音频内容写入客户端http连接。没有理由你给定的URL不能代表无限的数据流。如果你没有关闭连接,客户端将继续收听,因此当你完成流式传输歌曲文件时,只需开始将商业广告写入套接字,然后再播放另一首歌曲。你能分享一些代码,以便我们看看你的简单HTTP服务器,也许更具体地谈论你需要做什么? – stderr 2011-04-26 02:48:52

+1

这个答案没有解决“开始听任何正在播放的东西,就像一个广播电台”。 – 2013-01-16 21:56:18

0

你会希望有一个指向一个静态的URI m3u格式或.PLS文件(例如http://example.com/now_playing.mp3),然后在他们要求该文件时,向他们发送mp3数据,无论你在歌曲中的哪个位置。可能有一些小问题我在这里琢磨......但是,至少在森林指出,你可以开始从任何字节流式传输mp3数据。

+0

实际上,只要客户要求,你几乎可以**在客户端开始播放mp3数据。 MP3编码不使用文件标题。 – 2013-01-18 19:05:10

+0

嗯,有趣。你是对的,它是整个文件中的交错标题/数据。但是,这样做会错过任何ID3标签,而且我的主要观点是,您可能不应该从任何字节位置开始,而必须从其中一个标头开始。 – mike 2013-01-20 09:50:49

+0

你绝对应该从任何字节位置开始。格式就是为此而设计的。同步比特出现在每个帧中专门用于该目的。 – 2013-01-20 20:35:16

1

既然你已经有很好的经验蟒(给你已经写了一个HTTP服务器),我只能提供关于如何扩展您已经完成了地面工作几个要点:

  • 准备你的服务器处理请求头请求处理器如:Accept-Encoding,Range,TE (Transfer Encoding)等。一个MP3-over-HTTP播放器(即VLC)不过是一个MP3播放器,知道如何“说”HTTP和“寻找”文件中的不同位置。

  • 使用wireshark或tcpdump到当通过HTTP播放mp3时,通过VLC嗅探实际的HTTP请求,所以您知道您将如何接收并实施它们。

祝您的项目顺利!