【问题标题】:get info from streaming radio从流媒体广播中获取信息
【发布时间】:2017-10-18 09:59:24
【问题描述】:

有一些标准方法可以向流媒体广播服务询问当前正在播放的歌曲吗? 我目前对每个站点以不同的方式进行操作,例如(SomaFM):

  $wg=join("\n",`wget -q -O - https://somafm.com/secretagent/songhistory.html`);
  $wg=~/\(Now\).*>([^<]*)<\/a><\/td><td>([^<]*)/s;  
  print "Secret Agent\n$1\n$2\n"

或(Radio Svizzera Classica):

$wg=join("\n",`wget -q -O - http://www.radioswissclassic.ch/en`);
$wg=~/On Air.*?titletag">([^<]*).*?artist">([^<]*)/s;
print "Radio Svizzera Classic\n$1\n$2\n"

...但我想知道是否有更标准的方法可以做到这一点,而不是依赖于下载迟早会改变的html页面

【问题讨论】:

    标签: streaming audio-streaming internet-radio


    【解决方案1】:

    对于带有 ICY 元数据的 SHOUTcast/Icecast 风格的电台(构成大部分互联网广播电台),最好的办法是从流本身获取这些数据。

    首先,您需要一个指向实际流的 URL。如果您访问 SomaFM 的特工页面http://somafm.com/secretagent/,您会看到其他播放器的收听链接。例如,让我们使用指向http://somafm.com/secretagent130.pls 的128k AAC 链接。这不是实际的流……它是一个播放列表文件,其中包含指向实际流的链接。在你喜欢的文本或代码编辑器中打开它,看看我的意思:

    [playlist]
    numberofentries=2
    File1=http://ice1.somafm.com/secretagent-128-aac
    Title1=SomaFM: Secret Agent (#1  ): The soundtrack for your stylish, mysterious, dangerous life. For Spies and PIs too!
    Length1=-1
    File2=http://ice2.somafm.com/secretagent-128-aac
    Title2=SomaFM: Secret Agent (#2  ): The soundtrack for your stylish, mysterious, dangerous life. For Spies and PIs too!
    Length2=-1
    Version=2
    

    互联网广播电台通常在此处包含多个服务器以进行故障转移。如果侦听器与其中一个断开连接,则播放器通常会滚动到下一个项目。当一个服务器达到其监听器限制时,这也很有用......玩家将(希望)最终访问另一台处于活动状态的服务器。

    无论如何,启动 Wireshark 或其他数据包嗅探器的副本。点击音频播放器中的 URL 之一,并检查流量。我们首先要看的是请求和响应。

    GET /secretagent-128-aac HTTP/1.1
    Host: ice1.somafm.com
    User-Agent: VLC/2.2.4 LibVLC/2.2.4
    Range: bytes=0-
    Connection: close
    Icy-MetaData: 1
    
    HTTP/1.0 200 OK
    Content-Type: audio/aacp
    Date: Sat, 20 May 2017 20:43:56 GMT
    icy-br:128
    icy-genre:Various
    icy-name:Secret Agent from SomaFM [SomaFM]
    icy-notice1:<BR>This stream requires <a href="http://www.winamp.com/">Winamp</a><BR>
    icy-notice2:SHOUTcast Distributed Network Audio Server/Linux v1.9.5<BR>
    icy-pub:0
    icy-url:http://SomaFM.com
    Server: Icecast 2.4.0-kh3
    Cache-Control: no-cache, no-store
    Pragma: no-cache
    Access-Control-Allow-Origin: *
    Access-Control-Allow-Headers: Origin, Accept, X-Requested-With, Content-Type
    Access-Control-Allow-Methods: GET, OPTIONS, HEAD
    Connection: Close
    Expires: Mon, 26 Jul 1997 05:00:00 GMT
    icy-metaint:45000
    

    这些网络广播服务器要么是 HTTP(在 Icecast 和其他的情况下)要么非常接近它(旧版 SHOUTcast),并接受正常的GET 请求。在这种情况下,我的播放器 (VLC) 向 /secretagent-128-aac 发出 GET 请求,这是实际流的路径。

    我的播放器还包含一键请求头:

    Icy-MetaData: 1
    

    Icy-MetaData 标头要求服务器将元数据与音频流数据混合。也就是说,“正在播放”的曲目信息将定期发送到流中。

    在服务器响应标头中,还有另一个关键标头:

    icy-metaint:45000
    

    这告诉我们两件事……第一件事是服务器同意发送元数据。第二个是元数据间隔是45000字节。每 45,000 个字节,服务器将注入一大块元数据。让我们回到我们的数据包嗅探器,看看它是什么样子的:

    元数据块的第一个字节0x06 告诉我们元数据块有多长。取那个字节的值,乘以 16,你将得到元数据块的长度(以字节为单位)。也就是说,第一个元数据块字节的0x06 告诉我们接下来的 96 个字节将是元数据,然后再返回常规流数据。请注意,这意味着整个元数据为 97 个字节...长度指示符为 1 个字节,其余为 96 个字节(在本例中)。

    现在,让我们进入实际的文本元数据格式:

    StreamTitle='Buscemi - First Flight To London';StreamUrl='http://SomaFM.com/secretagent/';
    

    它看起来很简单。 key='value',分号 ; 分隔。不过,这有一些大问题。例如......没有真正标准的方法来转义单引号。如果元数据值需要包含单引号,有时是\',有时是'''。有时根本逃不掉!

    此外,并非所有服务器都使用相同的字符编码。您可能可以放心地假设 UTF-8,但确实希望某些服务器可能有所不同,或者只是简单地破坏了它们自己的元数据编码。

    无论如何,既然您知道所有这些是如何工作的,那么您就可以实施了。如果你愿意,我有一些你可以授权的代码。一个是 Node.js API 服务器,当给定一个流 URL 时,它将为您返回元数据,在服务器端执行所有缓冲和解析。另一个是基于 MSE 的客户端播放器……请注意,这仅适用于支持 CORS 的服务器,据我所知,今天只有我自己的服务器(AudioPump CDN)可以这样做。如果您对此代码感兴趣,请随时通过 brad@audiopump.co 给我发送电子邮件。如果您对我在 Stack Overflow 上的回答有任何疑问,请在此处发表评论。

    【讨论】:

    • 感谢您详细而完整的回答!我会尝试让它在我的程序中工作(我使用 python)......
    • 布拉德,感谢您的解释,我发现了这个:“people.kth.se/~johanmon/dse/casty.pdf” 深入的解释,但很老。还有效吗?
    • 注意事项:根据经验,一些收音机倾向于在接近歌曲开头时发送元数据,然后在下一首歌曲开始之前发送 0 长度元数据。
    猜你喜欢
    • 1970-01-01
    • 2012-07-21
    • 1970-01-01
    • 2023-03-20
    • 2021-08-26
    • 2011-11-08
    • 1970-01-01
    • 2014-11-03
    • 1970-01-01
    相关资源
    最近更新 更多