【问题标题】:Which protocol should I use for streaming audio (not live)? [closed]我应该使用哪种协议来流式传输音频(非实时)? [关闭]
【发布时间】:2013-05-20 12:53:16
【问题描述】:

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

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

然后我遇到了SHOUTcast,这是一个专有软件(服务器!),用于使用自己的协议进行流媒体。另一个似乎提供类似功能的现有服务器程序是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 协议。
(我不确定这是否与 Icecast 使用的协议相同)

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

【问题讨论】:

  • 您链接到的icecast 的维基百科页面明确表示“Icecast 服务器能够通过 SHOUTcast 使用的协议将内容流式传输为... MP3...”以及您清楚地捕获的 SHOUTcast 协议标头也说Server: Icecast 2.3.2
  • 无论如何,世界上没有可以“使用任何媒体播放器播放该流”的协议。 Icecast 可以为各种各样的玩家玩,但肯定不是所有。 HTML5 和/或 Flash(无论是 RTMP、RTMFP 还是 HTTP)或 Silverlight 流媒体可以在大多数 Web 浏览器上播放,但不能在许多其他客户端上播放。什么是合适的取决于您没有真正描述的用例。
  • 最终,听起来您的问题是“什么是最好的流协议”,这正是FAQ 描述为“不适合此站点”的那种东西。跨度>
  • 当我写“媒体播放器”时,我并没有考虑浏览器,抱歉。我正在尝试构建一个从客户端获取请求(ID 不是实际文件名)的服务器(客户端和服务器共享一个数据库,其中包含有关什么 ID 是什么歌曲的信息)我将编写自己的客户端应用程序,但我想使用最普遍的协议。 (我认为所有媒体播放器都支持任何东西)我在问最好的(在python服务器中最容易实现)流协议是做什么的. (我并不是很期待实现反向引擎 undocum.protocol)
  • 您是否有理由需要从 Python 中实际提供数据,而不是仅仅控制一个库存的 icecast 服务器? (在 client 端,ice 库有很好的绑定。)

标签: python http streaming audio-streaming


【解决方案1】:

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

ICY 200 OK

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

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

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

所有这一切都表明,最流行的流协议实际上是 HTTP,并且 SHOUTcast/Icecast/许多其他服务器都添加了一个请求标头,您可以在其中将元数据交错到流中。不请求元数据的 HTTP 客户端只会获得常规的 MP3 流,浏览器会认为它只是某个地方的某个文件。毕竟,浏览器并不关心你如何获取数据。

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

我正在尝试编写一个 Python 服务器,它可以从头到尾传输一个请求的 mp3 文件。 (没有直播)

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

我希望能够使用任何媒体播放器(如 VLC)播放该流并能够更改播放位置。

对于该要求,只需确保您的服务器支持range requests。其余的由客户负责。

总结一下

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-03
    • 2010-10-23
    • 1970-01-01
    相关资源
    最近更新 更多