Python:用mplayer解析流媒体标题

4 投票
2 回答
5600 浏览
提问于 2025-04-16 05:27

我正在用Python写一个简单的前端程序,目的是播放和录制网络电台(比如从shoutcast获取的电台),我使用的是mplayer(在一个子进程中运行)。当用户点击某个电台时,下面的代码就会执行:


url = http://77.111.88.131:8010 # only an example
cmd = "mplayer %s" % url
p = subprocess.Popen(cmd.split(), shell=False)
wait = os.waitpid(p.pid, 1)
return int(p.pid)

这个代码运行得非常好,电台的音频可以正常播放。不过,我想要找一种方法来解析这个电台的标题。看起来我需要从mplayer的输出中获取这个标题。当我在终端中播放这个电台时,输出是这样的:

$ mplayer http://77.111.88.131:8010
MPlayer 1.0rc4-4.4.5 (C) 2000-2010 MPlayer Team
mplayer: could not connect to socket
mplayer: No such file or directory
Failed to open LIRC support. You will not be able to use your remote control.

Playing http://77.111.88.131:8010.
Resolving 77.111.88.131 for AF_INET6...
Couldn't resolve name for AF_INET6: 77.111.88.131
Connecting to server 77.111.88.131[77.111.88.131]: 8010...
Name   : Justmusic.Fm
Genre  : House
Website: http://www.justmusic.fm
Public : yes
Bitrate: 192kbit/s
Cache size set to 320 KBytes
Cache fill:  0.00% (0 bytes)   
ICY Info: StreamTitle='(JustMusic.FM) Basement - Zajac, Migren live at Justmusic 2010-10-09';StreamUrl='http://www.justmusic.fm';
Cache fill: 17.50% (57344 bytes)   
Audio only file format detected.

这个过程会一直运行,直到我手动停止。那么问题来了,我该如何获取到“(JustMusic.FM) Basement - Zajac, Migren live at Justmusic 2010-10-09”这个信息,同时又让这个进程继续运行呢?我觉得subprocess()并不会实际保存输出,但我可能错了。任何帮助都非常感谢 :)

2 个回答

1
import re
import shlex
from subprocess import PIPE, Popen

URL = 'http://relay2.slayradio.org:8000/'

def get_exitcode_stdout_stderr(cmd):
    """
    Execute the external command and get its exitcode, stdout and stderr.
    """
    args = shlex.split(cmd)

    proc = Popen(args, stdout=PIPE, stderr=PIPE)
    out, err = proc.communicate()
    exitcode = proc.returncode
    #
    return exitcode, out, err

def get_title():
    cmd = "mplayer -endpos 1 -ao null {url}".format(url=URL)
    out = get_exitcode_stdout_stderr(cmd)[1]

    for line in out.split("\n"):
#        print(line)
        if line.startswith('ICY Info:'):
            match = re.search(r"StreamTitle='(.*)';StreamUrl=", line)
            title = match.group(1)
            return title

def main():
    print(get_title())

编辑:我之前有一个不同的(更简单的)解决方案,但它不再有效,所以我更新了我的方案。这个想法是:mplayer在1秒后停止播放。(-endpos 1)。

5

stdout 这个参数设置为 PIPE,这样你就可以监听命令的输出了:

p= subprocess.Popen(['mplayer', url], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
for line in p.stdout:
    if line.startswith('ICY Info:'):
        info = line.split(':', 1)[1].strip()
        attrs = dict(re.findall("(\w+)='([^']*)'", info))
        print 'Stream title: '+attrs.get('StreamTitle', '(none)')

撰写回答