PyAudio可以工作,但每次都会输出错误消息

49

我正在使用PyAudio录制麦克风输入。

由于音频对我来说录制得很好,所以我是否应该尝试简单地抑制其错误消息呢?或者有没有办法解决它们?

ALSA lib pcm.c:2212:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.rear
ALSA lib pcm.c:2212:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.center_lfe
ALSA lib pcm.c:2212:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.side
ALSA lib audio/pcm_bluetooth.c:1613:(audioservice_expect) BT_GET_CAPABILITIES failed : Input/output error(5)
ALSA lib audio/pcm_bluetooth.c:1613:(audioservice_expect) BT_GET_CAPABILITIES failed : Input/output error(5)
ALSA lib audio/pcm_bluetooth.c:1613:(audioservice_expect) BT_GET_CAPABILITIES failed : Input/output error(5)
ALSA lib audio/pcm_bluetooth.c:1613:(audioservice_expect) BT_GET_CAPABILITIES failed : Input/output error(5)
ALSA lib pcm_dmix.c:957:(snd_pcm_dmix_open) The dmix plugin supports only playback stream
ALSA lib pcm_dmix.c:1018:(snd_pcm_dmix_open) unable to open slave
Cannot connect to server socket err = No such file or directory
Cannot connect to server socket
jack server is not running or cannot be started
8个回答

49

你可以尝试清理你的ALSA配置,例如:

ALSA lib pcm.c:2212:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.rear
ALSA lib pcm.c:2212:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.center_lfe
ALSA lib pcm.c:2212:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.side

是由 /usr/share/alsa/alsa.conf 引起的:

pcm.rear cards.pcm.rear
pcm.center_lfe cards.pcm.center_lfe
pcm.side cards.pcm.side

一旦您将这些行注释掉,那些错误消息就会消失。您可能还想检查 ~/.asoundrc/etc/asound.conf

话虽如此,其中一些消息正在告诉您配置存在问题,尽管它们不会造成任何真正的问题。我不建议您清理 alsa.conf,因为它最初来自 ALSA,当您更新 alsa-lib 时可能会被覆盖。

有一种方法可以在 Python 中抑制这个消息,以下是一个示例代码:

#!/usr/bin/env python
from ctypes import *
import pyaudio

# From alsa-lib Git 3fd4ab9be0db7c7430ebd258f2717a976381715d
# $ grep -rn snd_lib_error_handler_t
# include/error.h:59:typedef void (*snd_lib_error_handler_t)(const char *file, int line, const char *function, int err, const char *fmt, ...) /* __attribute__ ((format (printf, 5, 6))) */;
# Define our error handler type
ERROR_HANDLER_FUNC = CFUNCTYPE(None, c_char_p, c_int, c_char_p, c_int, c_char_p)
def py_error_handler(filename, line, function, err, fmt):
  print 'messages are yummy'
c_error_handler = ERROR_HANDLER_FUNC(py_error_handler)

asound = cdll.LoadLibrary('libasound.so')
# Set error handler
asound.snd_lib_error_set_handler(c_error_handler)
# Initialize PyAudio
p = pyaudio.PyAudio()
p.terminate()

print '-'*40
# Reset to default error handler
asound.snd_lib_error_set_handler(None)
# Re-initialize
p = pyaudio.PyAudio()
p.terminate()

我的电脑输出:

messages are yummy
messages are yummy
messages are yummy
messages are yummy
messages are yummy
messages are yummy
----------------------------------------
ALSA lib pcm_dmix.c:1018:(snd_pcm_dmix_open) unable to open slave
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.rear
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.center_lfe
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.side
ALSA lib pcm_dmix.c:957:(snd_pcm_dmix_open) The dmix plugin supports only playback stream
ALSA lib pcm_dmix.c:1018:(snd_pcm_dmix_open) unable to open slave

这些消息是由alsa-lib打印出来的,而不是PyAudio或PortAudio。 该代码直接使用alsa-lib的snd_lib_error_set_handler函数设置错误处理程序py_error_handler,您可以使用它来删除任何消息。

我已经检查了其他Python ALSA绑定,pyalsa和PyAlsaAudio,它们不支持设置错误处理程序。然而,在PortAudio上有一个问题,所有ALSA错误消息似乎在之前都被抑制了。


这不会清除JACK的消息,对吧? - Matthias
我想知道那些要注释掉的行到底是什么意思,以便弄清楚它们的删除是否会产生其他影响。 - matanster

34

上述所有内容都是正确的并且是一个好的解决方案。我只是来这里建议一种更好的重新使用错误处理程序代码的方式:

from ctypes import *
from contextlib import contextmanager
import pyaudio

ERROR_HANDLER_FUNC = CFUNCTYPE(None, c_char_p, c_int, c_char_p, c_int, c_char_p)

def py_error_handler(filename, line, function, err, fmt):
    pass

c_error_handler = ERROR_HANDLER_FUNC(py_error_handler)

@contextmanager
def noalsaerr():
    asound = cdll.LoadLibrary('libasound.so')
    asound.snd_lib_error_set_handler(c_error_handler)
    yield
    asound.snd_lib_error_set_handler(None)

完成此操作后,您可以通过使用noalsaerr上下文来重新使用错误处理程序:

with noalsaerr():
    p = pyaudio.PyAudio()
stream = p.open(format=pyaudio.paFloat32, channels=1, rate=44100, output=1)
...

2
那绝对是一个优雅的解决方案。 - mertyildiran

6
我曾经遇到过同样的问题。只需要在命令的结尾添加2>/dev/null就可以解决问题了。我只是想要抑制错误消息,这个方法很有效。
例如:python marvin.py 2>/dev/null

我遇到了ALSA pcm.c的underrun错误。这个解决方案可以帮助消除这个错误。 - Drwaish

5

1
我在那里提供了一个稍微详细一些的答案: https://dev59.com/hZbfa4cB1Zd3GeqPwJ2N#36966379 - Matthias
这是唯一对我有效的解决方案。 - Thomas

4
这将在创建 PyAudio 对象时抑制错误消息。
这来自于Matthais的精彩帖子。
import time, os, sys, contextlib

@contextlib.contextmanager
def ignoreStderr():
    devnull = os.open(os.devnull, os.O_WRONLY)
    old_stderr = os.dup(2)
    sys.stderr.flush()
    os.dup2(devnull, 2)
    os.close(devnull)
    try:
        yield
    finally:
        os.dup2(old_stderr, 2)
        os.close(old_stderr)

 ...
 ...
 with ignoreStderr():
     self._audio_interface = pyaudio.PyAudio()

4

这些看起来像是正常的调试信息,用于确定如何在你的系统上运行。我认为你可以抑制它们,没有必要保留。

你可能会想要关闭对jack服务器、蓝牙设备、环绕声等的检测,但这并不是必须的,而且你可能会弄坏它们。不要碰那些已经工作正常的东西!


谢谢您的建议!我的问题是,脚本显示需要记录的文本。一旦您开始录制,这些调试消息就会将该文本基本上挤出视线。 - eoinoc
如果你的问题是如何抑制它们,尝试将stderr重定向到一个文件。stderr = open(logfile, 'wb')然后sys.stderr = stderr。让我知道它是否有效。 - agf
1
那似乎很有道理,但没有任何效果。例如,消息可能是通过另一个输出流传输的吗? - eoinoc

1
如果您的默认音频子系统是Pulseaudio(常见于Fedora,Ubuntu,Debian),最好使用Pulseaudio支持重新编译PyAudio和底层C库Portaudio,而不是使用Jack和其他子系统。

0

小的额外注意事项:

  1. 确保将alsa.conf复制到另一个备份位置。
  2. 编辑alsa.conf时,请确保使用Sudo运行编辑器(例如sudo vi alsa.conf),这样您就不需要更改alsa.conf文件的权限

在我的情况下,这仍然会引发以下ALSA错误:

  • ALSA lib pcm_route.c:867:(find_matching_chmap)找不到匹配的通道映射
  • ALSA lib pcm_route.c:867:(find_matching_chmap)找不到匹配的通道映射
  • ALSA lib pcm_route.c:867:(find_matching_chmap)找不到匹配的通道映射
  • ALSA lib pcm_route.c:867:(find_matching_chmap)找不到匹配的通道映射

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接