使用运行 Raspbian GNU/Linux 8 (jessie) 的 Raspberry Pi Model B+,带有蓝色“Snowball”USB 麦克风和连接到 3.5 毫米插孔输出的有源扬声器。尝试运行pushtotalk.py
来自GassistPi的 Google Assistant 示例。样本运行但会产生多个下溢错误和断断续续的音频输出。Git 搜索发现了这个类似的问题,并指出了缓冲区参数设置(此处audio_helpers.py
为完整代码)和可能的 CPU 问题。下面的代码片段显示了参数设置以及产生错误消息的代码。在这里查看了python-sounddevice的更详细的解释但它超出了我的范围(才刚刚开始学习 Python!)。寻找一个简洁(且相对简单)的问题答案,是什么决定了参数设置的值以及如何修改代码/参数以防止/减少下溢错误?
代码片段 #1 audio_helpers.py 示例中的参数设置:
import sounddevice as sd
DEFAULT_AUDIO_SAMPLE_RATE = 16000
DEFAULT_AUDIO_SAMPLE_WIDTH = 2
DEFAULT_AUDIO_ITER_SIZE = 3200
DEFAULT_AUDIO_DEVICE_BLOCK_SIZE = 6400
DEFAULT_AUDIO_DEVICE_FLUSH_SIZE = 25600
def normalize_audio_buffer(buf, volume_percentage, sample_width=2):
"""Adjusts the loudness of the audio data in the given buffer.
代码片段 #2 audio_helpers.py 示例中的错误报告代码:
class SoundDeviceStream(object):
"""Audio stream based on an underlying sound device.
It can be used as an audio source (read) and a audio sink (write).
Args:
sample_rate: sample rate in hertz.
sample_width: size of a single sample in bytes.
block_size: size in bytes of each read and write operation.
flush_size: size in bytes of silence data written during flush operation.
"""
def __init__(self, sample_rate, sample_width, block_size, flush_size):
if sample_width == 2:
audio_format = 'int16'
else:
raise Exception('unsupported sample width:', sample_width)
self._audio_stream = sd.RawStream(
samplerate=sample_rate, dtype=audio_format, channels=1,
blocksize=int(block_size/2), # blocksize is in number of frames.
)
self._block_size = block_size
self._flush_size = flush_size
self._sample_rate = sample_rate
def read(self, size):
"""Read bytes from the stream."""
buf, overflow = self._audio_stream.read(size)
if overflow:
logging.warning('SoundDeviceStream read overflow (%d, %d)',
size, len(buf))
return bytes(buf)
def write(self, buf):
"""Write bytes to the stream."""
underflow = self._audio_stream.write(buf)
if underflow:
logging.warning('SoundDeviceStream write underflow (size: %d)',
len(buf))
return len(buf)
最后是运行时的警告输出pushtotalk.py
WARNING:root:SoundDeviceStream write underflow (size: 4000)
WARNING:root:SoundDeviceStream write underflow (size: 4000)
WARNING:root:SoundDeviceStream write underflow (size: 4000)
WARNING:root:SoundDeviceStream write underflow (size: 4000)
WARNING:root:SoundDeviceStream write underflow (size: 4000)
WARNING:root:SoundDeviceStream write underflow (size: 4000)
更新OK,稍加修改我已经设法通过注释掉代码来减少断断续续的音频输出,该代码audio_helpers.py
会为下溢和溢出条件生成警告消息输出。似乎当检测到下溢/溢出情况时,logging.warning 正在输出到终端(stdout
?),这导致音频播放暂时中断。您仍然可以在音频输出中检测到轻微的断断续续,但比以前要好得多。理想情况下,与其阻止警告消息的输出,不如从一开始就阻止发生下溢/溢出情况!
下面的代码片段显示了在 中注释掉的两个 logging.warning 函数audio_helpers.py
。该文件位于/home/pi/env/lib/python3.5/site-packages/googlesamples/assistant/grpc
我的设置中。
def read(self, size):
"""Read bytes from the stream."""
buf, overflow = self._audio_stream.read(size)
# if overflow:
# logging.warning('SoundDeviceStream read overflow (%d, %d)',
# size, len(buf))"""
return bytes(buf)
def write(self, buf):
"""Write bytes to the stream."""
underflow = self._audio_stream.write(buf)
# if underflow:
# logging.warning('SoundDeviceStream write underflow (size: %d)',
# len(buf))"""
return len(buf)
Doc-String """ 的使用现在更改为 # 用于注释掉的部分
更新 2
在@Matthias 的建议中,详细说明了如何pushtotalk.py
启动以及使用 switch 的结果--audio-block-size
pi@raspberrypi:~ $ /home/pi/env/bin/googlesamples-assistant-pushtotalk --project-id 'gassistpi-xxxxx' --device-model-id 'gassistpi-xxxxx-gassistpi-xxxxx' --audio-block-size -77
Traceback (most recent call last):
File "/home/pi/env/bin/googlesamples-assistant-pushtotalk", line 11, in <module>
sys.exit(main())
File "/home/pi/env/lib/python3.5/site-packages/click/core.py", line 722, in __call__
return self.main(*args, **kwargs)
File "/home/pi/env/lib/python3.5/site-packages/click/core.py", line 697, in main
rv = self.invoke(ctx)
File "/home/pi/env/lib/python3.5/site-packages/click/core.py", line 895, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "/home/pi/env/lib/python3.5/site-packages/click/core.py", line 535, in invoke
return callback(*args, **kwargs)
File "/home/pi/env/lib/python3.5/site-packages/googlesamples/assistant/grpc/pushtotalk.py", line 351, in main
flush_size=audio_flush_size
File "/home/pi/env/lib/python3.5/site-packages/googlesamples/assistant/grpc/audio_helpers.py", line 190, in __init__
blocksize=int(block_size/2), # blocksize is in number of frames.
File "/home/pi/env/lib/python3.5/site-packages/sounddevice.py", line 1264, in __init__
**_remove_self(locals()))
File "/home/pi/env/lib/python3.5/site-packages/sounddevice.py", line 779, in __init__
callback_ptr, userdata),
OverflowError: can't convert negative number to unsigned
pi@raspberrypi:~ $
--audio-block-size
我还尝试了从 1024 到 65536的(有效二进制)值,也尝试了0 来衡量。所有产生相同的原始结果或运行时错误。