编写一个Python音乐流媒体播放器
我想用Python实现一个服务器,可以通过HTTP播放MP3格式的音乐。希望这个服务器能像广播电台一样,用户可以连接到这个音乐流,随时听到正在播放的音乐。
之前,我用SocketServer.TCPServer自己写过一个HTTP服务器(我知道还有BaseHTTPServer,但我就是想自己写一个小的HTTP堆栈),那么做一个音乐流媒体服务器在结构上会有什么不同呢?我需要关注哪些网络方面和MP3方面的库呢?
5 个回答
你需要了解如何提供 m3u 或 pls 文件。这些文件格式播放器都能很好地识别,这样它们就能通过你的http服务器来寻找mp3文件。
一个最简单的m3u文件其实就是一个普通的文本文件,每行写一个歌曲的链接。假设你在服务器上有以下这些链接:
/playlists/<playlist_name/playlist_id>
/songs/<song_name/song_id>
你可以通过这个链接来提供播放列表:
/playlists/myfirstplaylist
而这个资源的内容就应该是:
/songs/1
/songs/mysong.mp3
像Winamp这样的播放器可以打开你HTTP服务器上的m3u文件链接,然后开始播放播放列表中的第一首歌。你只需要像提供其他静态内容一样提供mp3文件就可以了。
如果你想支持更多的用户同时使用,你可能需要考虑使用像 Twisted 这样的库来实现异步输入输出,这样可以支持很多同时的流媒体播放。
既然你已经有了不错的Python经验(毕竟你已经写了一个HTTP服务器),我只能给你一些建议,帮助你在已有的基础上继续扩展:
准备好你的服务器来处理请求头,比如:
Accept-Encoding
、Range
、TE (Transfer Encoding)
等等。一个通过HTTP播放MP3的播放器(比如VLC)其实就是一个会“说”HTTP的MP3播放器,它能在文件中“跳转”到不同的位置。使用wireshark或tcpdump来捕捉VLC播放MP3时实际发送的HTTP请求,这样你就能知道会收到什么请求头,并且可以实现这些功能。
祝你的项目顺利!
mp3格式是为了流媒体播放而设计的,这让一些事情变得比你想象的简单。mp3的数据实际上是一串带有边界标记的音频帧,而不是一个文件头后面跟着原始数据。这意味着,一旦客户端准备好接收音频数据,你可以从任何一个现有的mp3源开始发送数据,无论是实时的还是文件,客户端会自动找到下一个音频帧并开始播放。太棒了!
当然,你需要给客户端提供一种方式来建立连接。现在的标准是SHOUTcast(ICY)协议。这和HTTP很像,但状态和头部字段稍有不同,因此不能直接和Python的内置http服务器库兼容。你可能可以让这些库帮你做一些工作,但它们的文档接口可能不足以完成任务;你需要查看它们的代码,了解如何让它们支持SHOUTcast。
这里有一些链接可以帮助你入门:
https://web.archive.org/web/20220912105447/http://forums.winamp.com/showthread.php?threadid=70403
https://web.archive.org/web/20190214132820/http://www.smackfu.com/stuff/programming/shoutcast.html
http://en.wikipedia.org/wiki/Shoutcast
我建议先从一个单独的mp3文件作为数据源,先建立客户端和服务器的连接并实现播放,然后再处理实时源、多种编码比特率、内嵌元数据和播放列表等问题。
播放列表一般是.pls或.m3u文件,基本上就是指向你直播流URL的静态文本文件。它们并不复杂,甚至不一定需要,因为很多(大多数?)mp3流媒体客户端都能接受没有播放列表的直播流URL。
至于架构,这方面的选择非常多。你可以选择和HTTP服务器一样多的选项。是多线程的?工作进程?事件驱动的?这都由你决定。对我来说,更有趣的问题是如何将来自单个输入流(广播者)的数据与服务多个输出流(播放器)的网络处理程序共享。为了避免进程间通信和同步的复杂性,我可能会从单线程的事件驱动设计开始。在Python 2中,像gevent这样的库能提供非常好的I/O性能,同时让你的代码结构更易于理解。在Python 3中,我更喜欢使用asyncio协程。