New configuration for ridgid card selection by client
This commit is contained in:
parent
a9c3d7ba12
commit
6182362acc
2 changed files with 132 additions and 43 deletions
|
@ -5,11 +5,13 @@ voice:
|
||||||
input_rate: 44100
|
input_rate: 44100
|
||||||
target_rate: 16000
|
target_rate: 16000
|
||||||
port: 4444
|
port: 4444
|
||||||
input_name: null
|
input_name: 'AK5371'
|
||||||
|
output_name: 'USB Audio Device'
|
||||||
|
input_mixer: 'Mic'
|
||||||
|
output_mixer: 'PCM'
|
||||||
|
input_volume: 90
|
||||||
|
output_volume: 60
|
||||||
file_address: "http://hugveycmd.local:8888"
|
file_address: "http://hugveycmd.local:8888"
|
||||||
play_device: 0 # alsa mixer nr
|
|
||||||
play_volume: 80
|
|
||||||
play_audiodev: "hw:2,0" # sox AUDIODEV
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
157
hugvey/client.py
157
hugvey/client.py
|
@ -36,14 +36,14 @@ def setLogger(hv_id):
|
||||||
class VoiceServer(object):
|
class VoiceServer(object):
|
||||||
"""A UDP server, providing mic data at 16 kHz"""
|
"""A UDP server, providing mic data at 16 kHz"""
|
||||||
|
|
||||||
def __init__(self, loop, hugvey, voice_port: int, input_rate: int, input_name: str = None, target_rate: int = 16000):
|
def __init__(self, loop, hugvey, config):
|
||||||
self.voice_port = voice_port
|
self.config = config
|
||||||
self.input_rate = input_rate
|
|
||||||
self.target_rate = target_rate
|
self.input_rate = self.config['voice']['input_rate']
|
||||||
|
self.target_rate = self.config['voice']['target_rate']
|
||||||
self.stopped = True
|
self.stopped = True
|
||||||
self.clients = []
|
self.clients = []
|
||||||
self.laststate = None
|
self.laststate = None
|
||||||
self.input_name = input_name
|
|
||||||
self.ctx = Context.instance()
|
self.ctx = Context.instance()
|
||||||
self.loop = loop
|
self.loop = loop
|
||||||
self.hugvey = hugvey
|
self.hugvey = hugvey
|
||||||
|
@ -53,22 +53,99 @@ class VoiceServer(object):
|
||||||
self.prerol_frame_count = math.ceil(self.input_rate / self.chunk)
|
self.prerol_frame_count = math.ceil(self.input_rate / self.chunk)
|
||||||
self.prerol_frames = collections.deque(maxlen = self.prerol_frame_count)
|
self.prerol_frames = collections.deque(maxlen = self.prerol_frame_count)
|
||||||
|
|
||||||
def get_input_idx(self):
|
self.p = pyaudio.PyAudio()
|
||||||
|
# wait a sec for the input devices to come up
|
||||||
|
logger.debug('wait for mic')
|
||||||
|
time.sleep(3)
|
||||||
|
logger.debug('done waiting for mic')
|
||||||
|
|
||||||
|
|
||||||
|
self.info = self.get_card_info()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def get_card_info(self):
|
||||||
|
output_device_idx = None
|
||||||
input_device_idx = None
|
input_device_idx = None
|
||||||
# input_device_idx = 6
|
|
||||||
# input_device_idx = 0
|
|
||||||
devices_count = self.p.get_device_count()
|
devices_count = self.p.get_device_count()
|
||||||
for i in range(devices_count):
|
for i in range(devices_count):
|
||||||
dev = self.p.get_device_info_by_index(i)
|
dev = self.p.get_device_info_by_index(i)
|
||||||
if input_device_idx is None and dev['maxInputChannels'] > 0:
|
if output_device_idx is None and dev['maxOutputChannels'] > 0:
|
||||||
if (self.input_name and self.input_name in dev['name']) or \
|
if (self.config['voice']['output_name'] and self.config['voice']['output_name'] in dev['name']) or \
|
||||||
(not self.input_name and dev['name'] != 'default'):
|
(not self.config['voice']['output_name'] and dev['name'] != 'default'):
|
||||||
input_device_idx = dev['index']
|
output_device_idx = dev['index']
|
||||||
logger.info("Use device {0}: {1}".format(
|
logger.info("Use output device {0}: {1}".format(
|
||||||
dev['index'], dev['name']))
|
dev['index'], dev['name']))
|
||||||
logger.debug("{} {:0d} {}".format(
|
if input_device_idx is None and dev['maxInputChannels'] > 0:
|
||||||
"* " if input_device_idx == i else "- ", i, dev['name']))
|
if (self.config['voice']['input_name'] and self.config['voice']['input_name'] in dev['name']) or \
|
||||||
return input_device_idx
|
(not self.config['voice']['input_name'] and dev['name'] != 'default'):
|
||||||
|
input_device_idx = dev['index']
|
||||||
|
logger.info("Use input device {0}: {1}".format(
|
||||||
|
dev['index'], dev['name']))
|
||||||
|
logger.debug("{} {:0d} {} (i: {}, o: {})".format(
|
||||||
|
"< " if output_device_idx == i else "> " if input_device_idx == i else "- ", i, dev['name'],
|
||||||
|
dev['maxInputChannels'],
|
||||||
|
dev['maxOutputChannels']))
|
||||||
|
|
||||||
|
# Don't continue without pyAudio indexes
|
||||||
|
if input_device_idx is None:
|
||||||
|
raise Exception("Input device is not found: {}".format(self.config['voice']['input_name']))
|
||||||
|
if output_device_idx is None:
|
||||||
|
raise Exception("Output device is not found: {}".format(self.config['voice']['output_name']))
|
||||||
|
|
||||||
|
try:
|
||||||
|
# get eg: "hw:1,0" or "hw:0,3" -> used by Sox' play
|
||||||
|
output_device_name = self.p.get_device_info_by_index(output_device_idx)['name'].split("(",1)[1][:-1]
|
||||||
|
# get eg: "hw:1" or "hw:0" -> used by alsaaudio.Mixer(device=..)
|
||||||
|
output_card_name = output_device_name.split(",",1)[0]
|
||||||
|
except IndexError as e:
|
||||||
|
output_device_name = None
|
||||||
|
output_card_name = None
|
||||||
|
try:
|
||||||
|
input_device_name = self.p.get_device_info_by_index(input_device_idx)['name'].split("(",1)[1][:-1]
|
||||||
|
input_card_name = input_device_name.split(",",1)[0]
|
||||||
|
except IndexError as e:
|
||||||
|
input_device_name = None
|
||||||
|
input_card_name = None
|
||||||
|
|
||||||
|
print(output_device_name, input_device_name)
|
||||||
|
|
||||||
|
|
||||||
|
return {
|
||||||
|
'input': {
|
||||||
|
'idx': input_device_idx,
|
||||||
|
'device': input_device_name,
|
||||||
|
'card': input_card_name
|
||||||
|
},
|
||||||
|
'output': {
|
||||||
|
'idx': output_device_idx,
|
||||||
|
'device': output_device_name,
|
||||||
|
'card': output_card_name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# def get_output_idxs(self):
|
||||||
|
# pass
|
||||||
|
#
|
||||||
|
# def get_input_idx(self):
|
||||||
|
# input_device_idx = None
|
||||||
|
# # input_device_idx = 6
|
||||||
|
# # input_device_idx = 0
|
||||||
|
# devices_count = self.p.get_device_count()
|
||||||
|
# for i in range(devices_count):
|
||||||
|
# dev = self.p.get_device_info_by_index(i)
|
||||||
|
# if input_device_idx is None and dev['maxInputChannels'] > 0:
|
||||||
|
# if (self.input_name and self.input_name in dev['name']) or \
|
||||||
|
# (not self.input_name and dev['name'] != 'default'):
|
||||||
|
# input_device_idx = dev['index']
|
||||||
|
# logger.info("Use device {0}: {1}".format(
|
||||||
|
# dev['index'], dev['name']))
|
||||||
|
# logger.debug("{} {:0d} {}".format(
|
||||||
|
# "* " if input_device_idx == i else "- ", i, dev['name']))
|
||||||
|
# return input_device_idx
|
||||||
|
|
||||||
def onBuffer(self, in_data, frame_count, time_info, status):
|
def onBuffer(self, in_data, frame_count, time_info, status):
|
||||||
if self.input_rate == self.target_rate:
|
if self.input_rate == self.target_rate:
|
||||||
|
@ -108,13 +185,28 @@ class VoiceServer(object):
|
||||||
CHANNELS = 1
|
CHANNELS = 1
|
||||||
CHUNK = 4096
|
CHUNK = 4096
|
||||||
|
|
||||||
self.p = pyaudio.PyAudio()
|
|
||||||
self.stopped = False
|
self.stopped = False
|
||||||
|
|
||||||
# wait a sec for the input devices to come up
|
|
||||||
logger.debug('wait for mic')
|
if 'alsaaudio' in sys.modules:
|
||||||
await asyncio.sleep(3)
|
if self.config['voice']['input_mixer'] and self.config['voice']['input_volume'] and self.info['input']['card']:
|
||||||
logger.debug('done waiting for mic')
|
logger.info("Set input volume on {}/{} to {}".format(
|
||||||
|
self.config['voice']['input_mixer'],
|
||||||
|
self.info['input']['card'],
|
||||||
|
self.config['voice']['input_volume']
|
||||||
|
))
|
||||||
|
alsaaudio.Mixer(self.config['voice']['input_mixer'], device=self.info['input']['card']).setvolume(
|
||||||
|
self.config['voice']['input_volume'])
|
||||||
|
|
||||||
|
if self.config['voice']['output_mixer'] and self.config['voice']['output_volume'] and self.info['output']['card']:
|
||||||
|
logger.info("Set output volume on {}/{} to {}".format(
|
||||||
|
self.config['voice']['output_mixer'],
|
||||||
|
self.info['output']['card'],
|
||||||
|
self.config['voice']['output_volume']
|
||||||
|
))
|
||||||
|
alsaaudio.Mixer(self.config['voice']['output_mixer'], device=self.info['output']['card']).setvolume(
|
||||||
|
self.config['voice']['output_volume'])
|
||||||
|
|
||||||
stream = self.p.open(
|
stream = self.p.open(
|
||||||
format=FORMAT,
|
format=FORMAT,
|
||||||
|
@ -123,12 +215,12 @@ class VoiceServer(object):
|
||||||
input=True,
|
input=True,
|
||||||
frames_per_buffer=CHUNK,
|
frames_per_buffer=CHUNK,
|
||||||
stream_callback=self.onBuffer,
|
stream_callback=self.onBuffer,
|
||||||
input_device_index=self.get_input_idx()
|
input_device_index=self.info['input']['idx']
|
||||||
)
|
)
|
||||||
|
|
||||||
while not self.stopped:
|
while not self.stopped:
|
||||||
try:
|
try:
|
||||||
address = "tcp://*:{}".format(self.voice_port + self.hugvey.id)
|
address = "tcp://*:{}".format(self.config['voice']['port'] + self.hugvey.id)
|
||||||
self.voice_socket = self.ctx.socket(zmq.PUB)
|
self.voice_socket = self.ctx.socket(zmq.PUB)
|
||||||
self.voice_socket.bind(address)
|
self.voice_socket.bind(address)
|
||||||
|
|
||||||
|
@ -335,25 +427,20 @@ class Hugvey(object):
|
||||||
|
|
||||||
loop = asyncio.get_event_loop()
|
loop = asyncio.get_event_loop()
|
||||||
|
|
||||||
if self.config['voice']['play_device'] and 'alsaaudio' in sys.modules:
|
self.voice_server = VoiceServer(
|
||||||
alsaaudio.Mixer(self.config['voice']['play_device']).setvolume(
|
loop=loop,
|
||||||
self.config['voice']['play_volume'])
|
hugvey=self,
|
||||||
|
config=self.config
|
||||||
|
)
|
||||||
|
|
||||||
self.cmd_server = CommandHandler(
|
self.cmd_server = CommandHandler(
|
||||||
hugvey_id=self.id,
|
hugvey_id=self.id,
|
||||||
cmd_address=self.config['events']['cmd_address'],
|
cmd_address=self.config['events']['cmd_address'],
|
||||||
publish_address=self.config['events']['publish_address'],
|
publish_address=self.config['events']['publish_address'],
|
||||||
file_address=self.config['voice']['file_address'],
|
file_address=self.config['voice']['file_address'],
|
||||||
play_audiodev=self.config['voice']['play_audiodev']
|
play_audiodev=self.voice_server.info['output']['device']
|
||||||
)
|
|
||||||
self.voice_server = VoiceServer(
|
|
||||||
loop=loop,
|
|
||||||
hugvey=self,
|
|
||||||
voice_port=int(self.config['voice']['port']),
|
|
||||||
input_rate=int(self.config['voice']['input_rate']),
|
|
||||||
input_name=self.config['voice']['input_name'],
|
|
||||||
target_rate=int(self.config['voice']['target_rate']),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
logger.info('start')
|
logger.info('start')
|
||||||
# self.voice_server.asyncStart(loop)
|
# self.voice_server.asyncStart(loop)
|
||||||
# loop.run_until_complete(self.voice_server.start())
|
# loop.run_until_complete(self.voice_server.start())
|
||||||
|
|
Loading…
Reference in a new issue