Python SoundDeviceStream ошибки записи / чтения недополнения / переполнения - PullRequest
0 голосов
/ 09 ноября 2018

Использование Raspberry Pi Model B + под управлением Raspbian GNU / Linux 8 (jessie) с USB-микрофоном Blue Snowball и активными динамиками, подключенными к выходу 3,5 мм. Попытка запустить pushtotalk.py, образец Google Assistant от GassistPi . Образец запускается, но выдает несколько ошибок недостаточного значения и прерывистый вывод звука. Git search обнаружил эту похожую проблему и указывает на настройки параметров буфера в audio_helpers.py, (полный код здесь ) и возможные проблемы с процессором. Фрагменты кода ниже показывают настройки параметров, а также код, который выдает сообщение об ошибке. Посмотрел более подробное объяснение 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)

ОБНОВЛЕНИЕ ОК, немного повозившись. Мне удалось уменьшить прерывистый звук, закомментировав код в 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)

Использование строки документа "" "теперь изменено на # для закомментированных разделов

ОБНОВЛЕНИЕ 2 По предложению @Matthias, подробности запуска pushtotalk.py, а также результаты использования ключа --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 для хорошей меры. Все выдали одинаковый исходный результат или ошибки во время выполнения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...