可以从终端控制mpg123:
$ mpg123 -C -q ~/Music/Oginsky\ -\ Gold\ Collection/05\ -\ Oginsky\ -\ Oginsky\ Polonaise\ Fmaj.mp3
# 's' typed
Stopped.
# 'm' typed
MPEG 1.0 L III vbr 44100 j-s
# 'k' typed
[BOOKMARK] track 1 frame 97
# 's' typed
$
半双工 Python 控制 mpg123 也可以工作:
import os
import subprocess
import time
track = ('/home/vlz/Music/Oginsky - Gold Collection/'
'05 - Oginsky - Oginsky Polonaise Fmaj.mp3')
master, slave = os.openpty()
p = subprocess.Popen(['mpg123', '-C', '-q', track], stdin=master)
time.sleep(3)
os.write(slave, b's')
os.write(slave, b'm')
time.sleep(3)
os.write(slave, b'k')
time.sleep(3)
os.write(slave, b's')
time.sleep(6)
os.write(slave, b'q')
(修改了代码 pausing-mpg123-through-subprocess-in-python
我也想捕获“k”、“m”命令的输出:
[m] print MPEG header info (again)
[k] print out current position in playlist and track, for the benefit of some external tool to store bookmarks
尝试直接或通过 input() 读取描述符 0 失败。我想我干扰了 pty 流程,上面的脚本停止工作(没有完成)。
我需要 mpg123 命令的“实时”输出(在命令发出后立即)。在一个简单的 Python mp3 播放器中,我试图显示正在播放的曲目还剩多少时间(“k”命令)。
使用
Python 3.9.2
Debian GNU/Linux 11(靶心)
花了相当长的时间寻找 subprocess.Popen() 的解决方案。看起来 pexpect 是一种更简单的方法。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import pexpect
import time
mp3 = ('/home/vlz/Music/Oginsky - Gold Collection/'
'05 - Oginsky - Oginsky Polonaise Fmaj.mp3')
cmd = f'mpg123 -C -q "{mp3}"'
def main():
p = pexpect.spawn(cmd)
time.sleep(3)
p.send('s')
time.sleep(3)
p.send('k')
# [BOOKMARK] track 1 frame 97
p.expect(r'frame (\d+)')
pos = p.match.group(1)
p.send('m')
# MPEG 1.0 L III vbr 44100 j-s
p.expect(r'vbr (\d+) ')
len = p.match.group(1)
p.send('s')
time.sleep(3)
p.send('q')
print(f'{pos = }, {len = }')
if __name__ == '__main__':
main()
已测试。它打印:
$ python mpg123_script.py
pos = b'125', len = b'44100'