2010-10-14 29 views
4

J'écris un simple frontend en Python pour jouer et enregistrer des canaux de radio internet (par exemple de shoutcast) en utilisant mplayer (dans un sous-processus). Lorsqu'un utilisateur clique sur une station le code suivant est exécuté:Python: Parse stream title avec 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) 
 

Cela fonctionne parfaitement, le courant commence à jouer comme il se doit. Bien que je voudrais en quelque sorte analyser le titre du flux. Il semble que j'ai besoin de récupérer le titre de la sortie mplayer. Ceci est la sortie lorsque je joue le flux dans un terminal:

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

Il s'exécute ensuite jusqu'à ce qu'il soit arrêté. Donc la question est, comment puis-je récupérer "(JustMusic.FM) Sous-sol - Zajac, Migren en direct à Justmusic 2010-10-09" et encore laisser le processus s'exécuter? Je ne pense pas que subprocess() stocke réellement la sortie, mais je pourrais me tromper. Toute aide est très apprécié :)

Répondre

5

l'ensemble argument stdout-PIPE et vous serez en mesure d'écouter la sortie de la commande:

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)') 
+0

Merci beaucoup! Bien que stdout = PIPE, stderr = STDOUT bloque totalement l'interface graphique de TK. Si je "casse" la boucle, mplayer s'arrête après environ 30 secondes. De toute façon autour de cela? Peut-être échapper à la boucle sans affecter le processus? – frigg

+0

Essayez d'abord avec 'p.communicate()'. Il semble qu'un tampon se remplisse et ne soit pas lu à temps pour une raison quelconque, ce qui empêche le processus de bloquer. Vous n'avez pas besoin de 'stdout' * et *' stderr'; sans doute le message que vous voulez ne sort que sur un de ceux-là, je ne sais pas lequel! Peut-être stderr, auquel cas essayez simplement 'stderr = PIPE'? – bobince

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()) 

Edit: J'ai eu un autre (plus simple) solution ici qui a cessé de fonctionner alors j'ai mis à jour ma solution. L'idée: mplayer s'arrête après 1 sec. (-endpos 1).