import pyaudio import logging import audioop logger = logging.getLogger("player") class Player: """ Play the streamed audio """ def __init__(self, src_rate, out_rate): self.p = None self.src_rate = src_rate self.out_rate = out_rate # unfortunately not every device plays 16kHz audio streams self.cv_laststate = None try: self.p = p = pyaudio.PyAudio() self.stream = p.open(format=pyaudio.paInt16, channels=1, rate=out_rate, output=True, output_device_index=self.get_output_idx() ) except Exception as e: logger.critical(f"Player not instatiated: {e}") if self.p: self.p.terminate() self.p = None def get_output_idx(self): output_device_idx = None devices_count = self.p.get_device_count() for i in range(devices_count): dev = self.p.get_device_info_by_index(i) # print(dev) if output_device_idx is None and dev['maxOutputChannels'] > 0: output_device_idx = dev['index'] logger.info("Use device {0}: {1} {2}".format(dev['index'],dev['name'], dev['maxOutputChannels'])) logger.debug("{} {:0d} {}".format("* " if output_device_idx == i else "- ", i, dev['name'])) return output_device_idx def receive(self, chunk): if not self.p: return # logger.debug('receive {}'.format(len(chunk))) if self.src_rate == self.out_rate: data = chunk else: data, self.cv_laststate = audioop.ratecv(chunk, 2, 1, self.src_rate, self.out_rate, self.cv_laststate) self.stream.write(data) def shutdown(self): if not self.p: return self.stream.close() self.p.terminate()