编写 Python 音乐流媒体

发布于 2024-11-01 09:52:12 字数 245 浏览 2 评论 0原文

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

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

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

绝影如岚 2024-11-08 09:52:12

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/20170714033851 /https://www.radiotoolbox.com/community/forums/viewtopic.php?t=74

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 服务器一样多。螺纹?工作进程?事件驱动?由你决定。对我来说,更有趣的问题是如何与服务多个输出流(播放器)的网络处理程序共享来自单个输入流(广播者)的数据。为了避免 IPC 和同步复杂化,我可能会从单线程事件驱动设计开始。在 python 2 中,像 gevent 这样的库将为您提供 非常好的 I/O 性能,同时允许您以非常容易理解的方式构建代码。在 python 3 中,我更喜欢 asyncio 协程。

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:

https://web.archive.org/web/20220912105447/http://forums.winamp.com/showthread.php?threadid=70403

https://web.archive.org/web/20170714033851/https://www.radiotoolbox.com/community/forums/viewtopic.php?t=74

https://web.archive.org/web/20190214132820/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.

月下凄凉 2024-11-08 09:52:12

由于您已经拥有良好的 python 经验(假定您已经编写了 HTTP 服务器),因此我只能提供一些关于如何扩展您已经完成的基础工作的指导:

  • 准备您的服务器以处理带有请求标头,例如:Accept-EncodingRangeTE(传输编码) 等。 MP3-over-HTTP播放器(即VLC)是只是一个知道如何“说出”HTTP 并“寻找”文件中不同位置的 mp3 播放器。

  • 实际 HTTP 请求,这样您就知道如何接收并实现它们的请求标头。

祝你的项目好运!

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:

  • Prepare your server for dealing with Request Headers like: Accept-Encoding, Range, TE (Transfer Encoding), etc. An MP3-over-HTTP player (i.e. VLC) is nothing but an mp3 player that knows how to "speak" HTTP and "seek" to different positions in the file.

  • 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.

Good luck with your project!

§普罗旺斯的薰衣草 2024-11-08 09:52:12

您需要考虑提供 m3upls 文件。这将为您提供一种玩家能够充分理解的文件格式,以便您可以访问您的 http 服务器来查找 mp3 文件。

最小的 m3u 文件只是一个简单的文本文件,每行一个歌曲 url。假设您的服务器上有以下可用 URL:

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

您将从该 url 提供播放列表:

/playlists/myfirstplaylist

并且资源的内容将是:

/songs/1
/songs/mysong.mp3

播放器(如 Winamp)将能够打开 m3u 文件的 URL在您的 HTTP 服务器上,然后将开始播放播放列表中的第一首歌曲。要支持此功能,您所要做的就是提供 mp3 文件,就像提供任何其他静态内容一样。

根据您想要支持的客户端数量,您可能需要使用像 Twisted 这样的库来研究异步 IO,以支持大量并发溪流。

You'll want to look into serving m3u or pls files. That should give you a file format that players understand well enough to hit your http server looking for mp3 files.

A minimal m3u file would just be a simple text file with one song url per line. Assuming you've got the following URLs available on your server:

/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. All you'll have to do to support this is serve the mp3 file just like you'd serve any other static content.

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.

淡笑忘祈一世凡恋 2024-11-08 09:52:12

您需要一个指向静态 URI 的 .m3u 或 .pls 文件(例如 http://example. com/now_playing.mp3),然后当他们要求该文件时,从您在歌曲中的任何位置开始向他们提供 mp3 数据。可能有很多小问题我在这里掩盖了......但是,至少正如森林指出的那样,您可以开始从任何字节流式传输 mp3 数据。

You'll want to have a .m3u or .pls file that points at a static URI (e.g. http://example.com/now_playing.mp3) then give them mp3 data starting wherever you are in the song when they ask for that file. 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文