python - 我应该使用哪种协议(protocol)来传输音频(非直播)?

标签 python http streaming audio-streaming

<分区>

我正在尝试编写一个 Python 服务器,从头到尾流式传输一个请求的 mp3 文件。 (没有直播)
我希望能够使用任何媒体播放器(如 VLC)播放该流并能够更改播放位置。

我听说过很多关于 HTTP 流式传输的信息,但在阅读了一些维基百科文章后,我觉得“HTTP 流式传输”只是不同流式传输协议(protocol)的总称,例如 RTSP。/RTCP/RTP .

然后我遇到了SHOUTcast这是一个专有软件(服务器!),用于使用自己的协议(protocol)进行流媒体传输。另一个似乎提供类似功能的现有服务器程序是 Icecast .
我不太确定 SHOUTcast 和 Icecast 之间的关系,但似乎有一个。

我认为流式传输一个特定的媒体文件与流式传输连续流(如网络广播)没有什么不同,所以我用谷歌搜索了第一个网络广播并下载了一个 .pls 或 .m3u 文件。
两者基本上都是包含 url 的文本文件。所以我启动了 wireshark 并将 VLC 指向该 url。
我看到的本质上是 HTTP 流量:

VLC:

GET /schizoid HTTP/1.1

VLC:

Host: <ip>:8000
User-Agent: VLC/2.0.5 LibVLC/2.0.5
Range: bytes=0-
Connection: close
Icy-MetaData: 1

服务器响应:

HTTP/1.0 200 OK
Content-Type: audio/mpeg
icy-br:128
ice-audio-info: bitrate=128
icy-br:128
icy-description:PsyTrance 24x7
icy-genre:psytrance
icy-name:Radio Schizoid
icy-pub:1
icy-url:http://schizoid.in:8000/schizoid
Server: Icecast 2.3.2
Cache-Control: no-cache
icy-metaint:16000

然后服务器开始发送原始数据,这似乎是 mp3 流。

According to Wikipedia这是 SHOUTcast 协议(protocol)。
(我不确定这是否与 Icecast 使用的协议(protocol)相同)

但我认为封闭 ( not documented ) 协议(protocol)不可能成为流媒体的标准。
所以我的问题是将流式传输(特定的 mp3 文件)集成到 python 服务器中的最佳(最简单和最受支持的)方法是什么?
我是否必须手动实现 SHOUTcast 协议(protocol)或类似 RTP 的方法?
(我不介意使用第三方库)

最佳答案

SHOUTcast 客户端协议(protocol)实际上与 HTTP/1.0 相同。唯一相关的区别是响应状态行:

ICY 200 OK

您得到的不是HTTP/1.0,而是ICY。真的是这样!从那里开始,它的行为是一样的。 Web 浏览器和大多数 HTTP 客户端忽略这一点。 Android 和一些浏览器会卡住,但大多数都很好。 Icecast 的客户端流行为与 SHOUTcast 的行为相同,除了它实际上返回 HTTP/1.0 200 OK 作为其状态行。

现在,您已经注意到在那些响应 header 中,有一些带有流信息的额外 header 。除了一个之外,其他所有信息都只是额外信息,不会对您返回的数据产生任何影响。如果您不请求元数据,那么服务器什么都不做,只会获取从源发送给它的每个字节,并将其转发给每个客户端(还有一点服务器端缓冲区)。

如果在请求 header 中指定 Icy-MetaData: 1,则行为会略有变化。在响应中,您将获得 Icy-MetaInt: 8192 或类似内容。这意味着每 8,192 个字节,就会有一个元数据 block 。有时该 block 只是 0x00,这意味着没有元数据更新。其他时候会有像 0x01 这样的字节。如果将该值乘以 16,您就会知道接下来的 16 个字节将是 ASCII 元数据,如 StreamTitle: 'My Stream';StreamUrl='';,由 0x00 填充>。我已经描述了 the metadata in more detail in another post ,如果你好奇的话。

综上所述,最流行的流媒体协议(protocol)实际上是 HTTP,并且 SHOUTcast/Icecast/许多其他服务器添加了一个请求 header ,您可以在其中将元数据插入流中。不请求元数据的 HTTP 客户端只会获得常规 MP3 流,浏览器会认为这只是某处的某个文件。毕竟,浏览器并不关心您如何获取数据。

现在,您应该使用什么?您的要求:

I'm trying to write a Python server that streams one requested mp3 file from start to end. (No live streaming)

HTTP 就是您所需要的。事实上,不需要为此编写一些服务器。 Apache/Nginx/任何东西都可以正常工作。只是一个简单的 HTTP 服务器!如果你想按 ID 提供文件,这就是你的 Python 的用武之地。写一些东西,并根据该 ID 从磁盘中获取适当的资源。为此,我不会为 RTSP 而烦恼……这对于您需要的东西来说开销太大,而且您会损害客户端兼容性。

I'd like to have the functionality to play that stream with any media player (like VLC) and be able to change playback position.

对于该要求,只需确保您的服务器支持 range requests .客户会处理剩下的事情。

总结一下

  • SHOUTcast/Icecast 服务器用于“实时”广播式流,所有客户端(大致)同时获得相同的音频流
  • HTTP 是向客户端交付任何内容(无论是否流式传输)的最兼容的协议(protocol)
  • RTSP/RTMP/RTP 和所有相关协议(protocol)都不是必需的,除非您正在流式传输长时间运行或实时流,其中基于客户端带宽可用性的可变比特率很重要。 (这些协议(protocol)还有其他功能,但这似乎是选择它们的决定性因素。如果您想了解更多信息,我建议您逐一阅读。)

关于python - 我应该使用哪种协议(protocol)来传输音频(非直播)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16743135/

相关文章:

python - Tensorflow 图形编辑器重新路由复杂网络

rest - 业务异常导致错误响应的http状态。语法正确,请求有意义

java - Apache 或其他一些 CLIENT JAVA 实现是否支持 HTTP/2?

java - 在 Apache Storm 中运行时编辑 Bolt 进程

ffmpeg - 如何流式传输文件夹中的所有视频?

带参数的 Python/Flask 嵌套装饰器

python - 按钮的像素宽度和高度?

Flink 上 RabbitMQ 的 Python API 流式传输示例

web-services - 网站 url-config 中 url 中的可选尾部斜杠

HTML5 和示例 RTP 流?