4cfad5ae0f
- 全新ui - 全面优化websocket逻辑,提高数字人和ui连接的稳定性及资源开销 - 全面优化唤醒逻辑,提供稳定的普通唤醒模式和前置词唤醒模式 - 优化拾音质量,支持多声道麦克风拾音 - 优化自动播放服务器的对接机制,提供稳定和兼容旧版ue工程的对接模式 - 数字人接口输出机器人表情,以适应新fay ui及单片机的数字人表情输出 - 使用更高级的音频时长计算方式,可以更精准控制音频播放完成后的逻辑 - 修复点击关闭按钮会导致程序退出的bug - 修复没有麦克风的设备开启麦克风会出错的问题 - 为服务器主机地址提供配置项,以方便服务器部署
74 lines
2.3 KiB
Python
74 lines
2.3 KiB
Python
import pyaudio
|
|
import websockets
|
|
import asyncio
|
|
from queue import Queue
|
|
import argparse
|
|
import json
|
|
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("--host", type=str, default="127.0.0.1", required=False, help="host ip, localhost, 0.0.0.0")
|
|
parser.add_argument("--port", type=int, default=10197, required=False, help="grpc server port")
|
|
parser.add_argument("--chunk_size", type=int, default=160, help="ms")
|
|
parser.add_argument("--vad_needed", type=bool, default=True)
|
|
args = parser.parse_args()
|
|
|
|
voices = Queue()
|
|
|
|
async def record():
|
|
global voices
|
|
FORMAT = pyaudio.paInt16
|
|
CHANNELS = 1
|
|
RATE = 16000
|
|
CHUNK = int(RATE / 1000 * args.chunk_size)
|
|
|
|
p = pyaudio.PyAudio()
|
|
|
|
stream = p.open(format=FORMAT, channels=CHANNELS, rate=RATE, input=True, frames_per_buffer=CHUNK)
|
|
|
|
while True:
|
|
data = stream.read(CHUNK)
|
|
voices.put(data)
|
|
await asyncio.sleep(0.01)
|
|
|
|
async def ws_send(websocket):
|
|
global voices
|
|
print("Started sending data!")
|
|
data_head = {
|
|
'vad_need': args.vad_needed,
|
|
'state': ''
|
|
}
|
|
await websocket.send(json.dumps(data_head))
|
|
|
|
while True:
|
|
while not voices.empty():
|
|
data = voices.get()
|
|
voices.task_done()
|
|
try:
|
|
await websocket.send(data)
|
|
except Exception as e:
|
|
print('Exception occurred:', e)
|
|
return # Return to attempt reconnection
|
|
await asyncio.sleep(0.01)
|
|
|
|
async def message(websocket):
|
|
while True:
|
|
try:
|
|
print(await websocket.recv())
|
|
except Exception as e:
|
|
print("Exception:", e)
|
|
return # Return to attempt reconnection
|
|
|
|
async def ws_client():
|
|
uri = "ws://{}:{}".format(args.host, args.port)
|
|
while True:
|
|
try:
|
|
async with websockets.connect(uri, subprotocols=["binary"], ping_interval=None) as websocket:
|
|
task1 = asyncio.create_task(record())
|
|
task2 = asyncio.create_task(ws_send(websocket))
|
|
task3 = asyncio.create_task(message(websocket))
|
|
await asyncio.gather(task1, task2, task3)
|
|
except Exception as e:
|
|
print("WebSocket connection failed: ", e)
|
|
await asyncio.sleep(5) # Wait for 5 seconds before trying to reconnect
|
|
|
|
asyncio.get_event_loop().run_until_complete(ws_client()) |