mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-28 21:23:52 +08:00
update:audio_to_data改成异步方法
This commit is contained in:
@@ -101,7 +101,7 @@ async def checkWakeupWords(conn, text):
|
|||||||
}
|
}
|
||||||
|
|
||||||
# 获取音频数据
|
# 获取音频数据
|
||||||
opus_packets = audio_to_data(response.get("file_path"))
|
opus_packets = await audio_to_data(response.get("file_path"))
|
||||||
# 播放唤醒词回复
|
# 播放唤醒词回复
|
||||||
conn.client_abort = False
|
conn.client_abort = False
|
||||||
|
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ async def max_out_size(conn):
|
|||||||
text = "不好意思,我现在有点事情要忙,明天这个时候我们再聊,约好了哦!明天不见不散,拜拜!"
|
text = "不好意思,我现在有点事情要忙,明天这个时候我们再聊,约好了哦!明天不见不散,拜拜!"
|
||||||
await send_stt_message(conn, text)
|
await send_stt_message(conn, text)
|
||||||
file_path = "config/assets/max_output_size.wav"
|
file_path = "config/assets/max_output_size.wav"
|
||||||
opus_packets = audio_to_data(file_path)
|
opus_packets = await audio_to_data(file_path)
|
||||||
conn.tts.tts_audio_queue.put((SentenceType.LAST, opus_packets, text))
|
conn.tts.tts_audio_queue.put((SentenceType.LAST, opus_packets, text))
|
||||||
conn.close_after_chat = True
|
conn.close_after_chat = True
|
||||||
|
|
||||||
@@ -142,7 +142,7 @@ async def check_bind_device(conn):
|
|||||||
|
|
||||||
# 播放提示音
|
# 播放提示音
|
||||||
music_path = "config/assets/bind_code.wav"
|
music_path = "config/assets/bind_code.wav"
|
||||||
opus_packets = audio_to_data(music_path)
|
opus_packets = await audio_to_data(music_path)
|
||||||
conn.tts.tts_audio_queue.put((SentenceType.FIRST, opus_packets, text))
|
conn.tts.tts_audio_queue.put((SentenceType.FIRST, opus_packets, text))
|
||||||
|
|
||||||
# 逐个播放数字
|
# 逐个播放数字
|
||||||
@@ -150,7 +150,7 @@ async def check_bind_device(conn):
|
|||||||
try:
|
try:
|
||||||
digit = conn.bind_code[i]
|
digit = conn.bind_code[i]
|
||||||
num_path = f"config/assets/bind_code/{digit}.wav"
|
num_path = f"config/assets/bind_code/{digit}.wav"
|
||||||
num_packets = audio_to_data(num_path)
|
num_packets = await audio_to_data(num_path)
|
||||||
conn.tts.tts_audio_queue.put((SentenceType.MIDDLE, num_packets, None))
|
conn.tts.tts_audio_queue.put((SentenceType.MIDDLE, num_packets, None))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
conn.logger.bind(tag=TAG).error(f"播放数字音频失败: {e}")
|
conn.logger.bind(tag=TAG).error(f"播放数字音频失败: {e}")
|
||||||
@@ -162,5 +162,5 @@ async def check_bind_device(conn):
|
|||||||
text = f"没有找到该设备的版本信息,请正确配置 OTA地址,然后重新编译固件。"
|
text = f"没有找到该设备的版本信息,请正确配置 OTA地址,然后重新编译固件。"
|
||||||
await send_stt_message(conn, text)
|
await send_stt_message(conn, text)
|
||||||
music_path = "config/assets/bind_not_found.wav"
|
music_path = "config/assets/bind_not_found.wav"
|
||||||
opus_packets = audio_to_data(music_path)
|
opus_packets = await audio_to_data(music_path)
|
||||||
conn.tts.tts_audio_queue.put((SentenceType.LAST, opus_packets, text))
|
conn.tts.tts_audio_queue.put((SentenceType.LAST, opus_packets, text))
|
||||||
|
|||||||
@@ -17,7 +17,12 @@ async def sendAudioMessage(conn, sentenceType, audios, text):
|
|||||||
|
|
||||||
if sentenceType == SentenceType.FIRST:
|
if sentenceType == SentenceType.FIRST:
|
||||||
# 同一句子的后续消息加入流控队列,其他情况立即发送
|
# 同一句子的后续消息加入流控队列,其他情况立即发送
|
||||||
if hasattr(conn, "audio_rate_controller") and conn.audio_rate_controller and getattr(conn, "audio_flow_control", {}).get("sentence_id") == conn.sentence_id:
|
if (
|
||||||
|
hasattr(conn, "audio_rate_controller")
|
||||||
|
and conn.audio_rate_controller
|
||||||
|
and getattr(conn, "audio_flow_control", {}).get("sentence_id")
|
||||||
|
== conn.sentence_id
|
||||||
|
):
|
||||||
conn.audio_rate_controller.add_message(
|
conn.audio_rate_controller.add_message(
|
||||||
lambda: send_tts_message(conn, "sentence_start", text)
|
lambda: send_tts_message(conn, "sentence_start", text)
|
||||||
)
|
)
|
||||||
@@ -120,7 +125,8 @@ def _get_or_create_rate_controller(conn, frame_duration, is_single_packet):
|
|||||||
# 判断是否需要重置:单包模式且 sentence_id 变化,或者控制器不存在
|
# 判断是否需要重置:单包模式且 sentence_id 变化,或者控制器不存在
|
||||||
need_reset = (
|
need_reset = (
|
||||||
is_single_packet
|
is_single_packet
|
||||||
and getattr(conn, "audio_flow_control", {}).get("sentence_id") != conn.sentence_id
|
and getattr(conn, "audio_flow_control", {}).get("sentence_id")
|
||||||
|
!= conn.sentence_id
|
||||||
) or not hasattr(conn, "audio_rate_controller")
|
) or not hasattr(conn, "audio_rate_controller")
|
||||||
|
|
||||||
if need_reset:
|
if need_reset:
|
||||||
@@ -138,7 +144,9 @@ def _get_or_create_rate_controller(conn, frame_duration, is_single_packet):
|
|||||||
}
|
}
|
||||||
|
|
||||||
# 启动后台发送循环
|
# 启动后台发送循环
|
||||||
_start_background_sender(conn, conn.audio_rate_controller, conn.audio_flow_control)
|
_start_background_sender(
|
||||||
|
conn, conn.audio_rate_controller, conn.audio_flow_control
|
||||||
|
)
|
||||||
|
|
||||||
return conn.audio_rate_controller, conn.audio_flow_control
|
return conn.audio_rate_controller, conn.audio_flow_control
|
||||||
|
|
||||||
@@ -152,6 +160,7 @@ def _start_background_sender(conn, rate_controller, flow_control):
|
|||||||
rate_controller: 速率控制器
|
rate_controller: 速率控制器
|
||||||
flow_control: 流控状态
|
flow_control: 流控状态
|
||||||
"""
|
"""
|
||||||
|
|
||||||
async def send_callback(packet):
|
async def send_callback(packet):
|
||||||
# 检查是否应该中止
|
# 检查是否应该中止
|
||||||
if conn.client_abort:
|
if conn.client_abort:
|
||||||
@@ -165,7 +174,9 @@ def _start_background_sender(conn, rate_controller, flow_control):
|
|||||||
rate_controller.start_sending(send_callback)
|
rate_controller.start_sending(send_callback)
|
||||||
|
|
||||||
|
|
||||||
async def _send_audio_with_rate_control(conn, audio_list, rate_controller, flow_control, send_delay):
|
async def _send_audio_with_rate_control(
|
||||||
|
conn, audio_list, rate_controller, flow_control, send_delay
|
||||||
|
):
|
||||||
"""
|
"""
|
||||||
使用 rate_controller 发送音频包
|
使用 rate_controller 发送音频包
|
||||||
|
|
||||||
@@ -235,7 +246,7 @@ async def send_tts_message(conn, state, text=None):
|
|||||||
stop_tts_notify_voice = conn.config.get(
|
stop_tts_notify_voice = conn.config.get(
|
||||||
"stop_tts_notify_voice", "config/assets/tts_notify.mp3"
|
"stop_tts_notify_voice", "config/assets/tts_notify.mp3"
|
||||||
)
|
)
|
||||||
audios = audio_to_data(stop_tts_notify_voice, is_opus=True)
|
audios = await audio_to_data(stop_tts_notify_voice, is_opus=True)
|
||||||
await sendAudio(conn, audios)
|
await sendAudio(conn, audios)
|
||||||
# 等待所有音频包发送完成
|
# 等待所有音频包发送完成
|
||||||
await _wait_for_audio_completion(conn)
|
await _wait_for_audio_completion(conn)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import json
|
|||||||
import copy
|
import copy
|
||||||
import wave
|
import wave
|
||||||
import socket
|
import socket
|
||||||
|
import asyncio
|
||||||
import requests
|
import requests
|
||||||
import subprocess
|
import subprocess
|
||||||
import numpy as np
|
import numpy as np
|
||||||
@@ -268,13 +269,15 @@ def audio_to_data_stream(
|
|||||||
pcm_to_data_stream(raw_data, is_opus, callback)
|
pcm_to_data_stream(raw_data, is_opus, callback)
|
||||||
|
|
||||||
|
|
||||||
def audio_to_data(audio_file_path: str, is_opus: bool = True) -> list[bytes]:
|
async def audio_to_data(audio_file_path: str, is_opus: bool = True) -> list[bytes]:
|
||||||
"""
|
"""
|
||||||
将音频文件转换为Opus/PCM编码的帧列表
|
将音频文件转换为Opus/PCM编码的帧列表
|
||||||
Args:
|
Args:
|
||||||
audio_file_path: 音频文件路径
|
audio_file_path: 音频文件路径
|
||||||
is_opus: 是否进行Opus编码
|
is_opus: 是否进行Opus编码
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def _sync_audio_to_data():
|
||||||
# 获取文件后缀名
|
# 获取文件后缀名
|
||||||
file_type = os.path.splitext(audio_file_path)[1]
|
file_type = os.path.splitext(audio_file_path)[1]
|
||||||
if file_type:
|
if file_type:
|
||||||
@@ -319,6 +322,10 @@ def audio_to_data(audio_file_path: str, is_opus: bool = True) -> list[bytes]:
|
|||||||
|
|
||||||
return datas
|
return datas
|
||||||
|
|
||||||
|
loop = asyncio.get_running_loop()
|
||||||
|
# 在单独的线程中执行同步的音频处理操作
|
||||||
|
return await loop.run_in_executor(None, _sync_audio_to_data)
|
||||||
|
|
||||||
|
|
||||||
def audio_bytes_to_data_stream(
|
def audio_bytes_to_data_stream(
|
||||||
audio_bytes, file_type, is_opus, callback: Callable[[Any], Any]
|
audio_bytes, file_type, is_opus, callback: Callable[[Any], Any]
|
||||||
|
|||||||
Reference in New Issue
Block a user