hugvey/hugvey/voice/player.py

63 lines
2.0 KiB
Python

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()