我想在Python中实现一个服务器,通过HTTP传输MP3格式的音乐。我希望它播放音乐,以便客户端可以连接到流并开始收听当前播放的内容,就像广播电台一样。
以前,我使用SocketServer.TCPServer在Python中实现了我自己的HTTP服务器(是的,我知道BaseHTTPServer存在,只是想自己编写一个迷你HTTP堆栈),那么音乐流媒体在架构上会有什么不同呢?我需要在网络侧和MP3端看哪些库?
答案 0 :(得分:35)
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文件开始作为您的数据源,使客户端 - 服务器连接设置和播放工作,然后继续讨论实时源,多个编码比特率,带内元数据和播放列表等问题。
播放列表通常是.pls或.m3u文件,基本上只是指向实时流的URL的静态文本文件。它们并不困难,甚至没有必要,因为许多(大多数?)mp3流媒体客户端将接受没有播放列表的实时流URL。
至于建筑,这个领域非常开放。您拥有与HTTP服务器一样多的选项。螺纹?工人流程?事件驱动?由你决定。对我来说,更有趣的问题是如何从单个输入流(广播公司)与服务于多个输出流(播放器)的网络处理器共享数据。为了避免IPC和同步复杂化,我可能会从单线程事件驱动设计开始。在python 2中,像gevent这样的库会为您提供very good I/O performance,同时允许您以一种非常易懂的方式构建代码。在python 3中,我更喜欢asyncio协同程序。
答案 1 :(得分:1)
由于你已经拥有良好的python经验(假设你已经编写了一个HTTP服务器),我只能提供一些关于如何扩展你已经完成的基础工作的指示:
准备服务器处理请求标题,例如:Accept-Encoding
,Range
,TE (Transfer Encoding)
等.MPAT-over-HTTP播放器(即VLC)只不过是一个知道如何“说”HTTP并“寻找”到文件中不同位置的mp3播放器。
在通过HTTP播放mp3时,使用wireshark或tcpdump来嗅探由VLC完成的实际HTTP请求,这样您就知道您将接收哪些请求标头并实施它们。
祝你的项目好运!
答案 2 :(得分:0)
您需要查看提供m3u或pls个文件。这应该给你一个文件格式,玩家可以很好地理解你的http服务器寻找mp3文件。
最小的m3u文件只是一个简单的文本文件,每行有一个歌曲网址。假设您的服务器上有以下URL:
/playlists/<playlist_name/playlist_id>
/songs/<song_name/song_id>
您将从网址提供播放列表:
/playlists/myfirstplaylist
资源的内容只是:
/songs/1
/songs/mysong.mp3
播放器(如Winamp)将能够打开HTTP服务器上m3u文件的URL,然后开始播放播放列表中的第一首歌曲。所有你需要做的就是支持这个就像你提供任何其他静态内容一样提供mp3文件。
根据您希望支持的客户端数量,您可能希望使用Twisted等库来查看异步IO,以支持大量的并发流。
答案 3 :(得分:0)
答案 4 :(得分:0)
你想要一个指向静态URI的文件(例如http://example.com/now_playing.mp3)的.m3u或.pls文件,然后在他们要求提供该文件时,从歌曲中的任何地方开始播放mp3数据。可能有一些小问题我在这里掩饰......但是,至少在森林指出的情况下,你可以从任何字节开始流式传输mp3数据。