mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-25 08:33:53 +08:00
合并main分支
This commit is contained in:
@@ -12,9 +12,9 @@ from core.providers.tts.dto.dto import TTSMessageDTO, MsgType
|
||||
from core.utils import p3
|
||||
from core.handle.sendAudioHandle import send_stt_message
|
||||
from plugins_func.register import register_function, ToolType, ActionResponse, Action
|
||||
from core.utils.dialogue import Message
|
||||
|
||||
TAG = __name__
|
||||
logger = setup_logging()
|
||||
|
||||
MUSIC_CACHE = {}
|
||||
|
||||
@@ -22,13 +22,13 @@ play_music_function_desc = {
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "play_music",
|
||||
"description": "唱歌、听歌、播放音乐方法。比如用户说播放音乐,参数为:random,比如用户说播放两只老虎,参数为:两只老虎",
|
||||
"description": "唱歌、听歌、播放音乐的方法。",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"song_name": {
|
||||
"type": "string",
|
||||
"description": "歌曲名称,如果没有指定具体歌名则为'random'",
|
||||
"description": "歌曲名称,如果用户没有指定具体歌名则为'random', 明确指定的时返回音乐的名字 示例: ```用户:播放两只老虎\n参数:两只老虎``` ```用户:播放音乐 \n参数:random ```",
|
||||
}
|
||||
},
|
||||
"required": ["song_name"],
|
||||
@@ -46,7 +46,7 @@ def play_music(conn, song_name: str):
|
||||
|
||||
# 检查事件循环状态
|
||||
if not conn.loop.is_running():
|
||||
logger.bind(tag=TAG).error("事件循环未运行,无法提交任务")
|
||||
conn.logger.bind(tag=TAG).error("事件循环未运行,无法提交任务")
|
||||
return ActionResponse(
|
||||
action=Action.RESPONSE, result="系统繁忙", response="请稍后再试"
|
||||
)
|
||||
@@ -60,9 +60,9 @@ def play_music(conn, song_name: str):
|
||||
def handle_done(f):
|
||||
try:
|
||||
f.result() # 可在此处理成功逻辑
|
||||
logger.bind(tag=TAG).info("播放完成")
|
||||
conn.logger.bind(tag=TAG).info("播放完成")
|
||||
except Exception as e:
|
||||
logger.bind(tag=TAG).error(f"播放失败: {e}")
|
||||
conn.logger.bind(tag=TAG).error(f"播放失败: {e}")
|
||||
|
||||
future.add_done_callback(handle_done)
|
||||
|
||||
@@ -70,7 +70,7 @@ def play_music(conn, song_name: str):
|
||||
action=Action.NONE, result="指令已接收", response="正在为您播放音乐"
|
||||
)
|
||||
except Exception as e:
|
||||
logger.bind(tag=TAG).error(f"处理音乐意图错误: {e}")
|
||||
conn.logger.bind(tag=TAG).error(f"处理音乐意图错误: {e}")
|
||||
return ActionResponse(
|
||||
action=Action.RESPONSE, result=str(e), response="播放音乐时出错了"
|
||||
)
|
||||
@@ -151,7 +151,7 @@ async def handle_music_command(conn, text):
|
||||
|
||||
"""处理音乐播放指令"""
|
||||
clean_text = re.sub(r"[^\w\s]", "", text).strip()
|
||||
logger.bind(tag=TAG).debug(f"检查是否是音乐命令: {clean_text}")
|
||||
conn.logger.bind(tag=TAG).debug(f"检查是否是音乐命令: {clean_text}")
|
||||
|
||||
# 尝试匹配具体歌名
|
||||
if os.path.exists(MUSIC_CACHE["music_dir"]):
|
||||
@@ -166,7 +166,7 @@ async def handle_music_command(conn, text):
|
||||
if potential_song:
|
||||
best_match = _find_best_match(potential_song, MUSIC_CACHE["music_files"])
|
||||
if best_match:
|
||||
logger.bind(tag=TAG).info(f"找到最匹配的歌曲: {best_match}")
|
||||
conn.logger.bind(tag=TAG).info(f"找到最匹配的歌曲: {best_match}")
|
||||
await play_local_music(conn, specific_file=best_match)
|
||||
return True
|
||||
# 检查是否是通用播放音乐命令
|
||||
@@ -174,12 +174,31 @@ async def handle_music_command(conn, text):
|
||||
return True
|
||||
|
||||
|
||||
def _get_random_play_prompt(song_name):
|
||||
"""生成随机播放引导语"""
|
||||
# 移除文件扩展名
|
||||
clean_name = os.path.splitext(song_name)[0]
|
||||
prompts = [
|
||||
f"正在为您播放,{clean_name}",
|
||||
f"请欣赏歌曲,{clean_name}",
|
||||
f"即将为您播放,{clean_name}",
|
||||
f"为您带来,{clean_name}",
|
||||
f"让我们聆听,{clean_name}",
|
||||
f"接下来请欣赏,{clean_name}",
|
||||
f"为您献上,{clean_name}",
|
||||
]
|
||||
# 直接使用random.choice,不设置seed
|
||||
return random.choice(prompts)
|
||||
|
||||
|
||||
async def play_local_music(conn, specific_file=None):
|
||||
global MUSIC_CACHE
|
||||
"""播放本地音乐文件"""
|
||||
try:
|
||||
if not os.path.exists(MUSIC_CACHE["music_dir"]):
|
||||
logger.bind(tag=TAG).error(f"音乐目录不存在: " + MUSIC_CACHE["music_dir"])
|
||||
conn.logger.bind(tag=TAG).error(
|
||||
f"音乐目录不存在: " + MUSIC_CACHE["music_dir"]
|
||||
)
|
||||
return
|
||||
|
||||
# 确保路径正确性
|
||||
@@ -188,23 +207,33 @@ async def play_local_music(conn, specific_file=None):
|
||||
music_path = os.path.join(MUSIC_CACHE["music_dir"], specific_file)
|
||||
else:
|
||||
if not MUSIC_CACHE["music_files"]:
|
||||
logger.bind(tag=TAG).error("未找到MP3音乐文件")
|
||||
conn.logger.bind(tag=TAG).error("未找到MP3音乐文件")
|
||||
return
|
||||
selected_music = random.choice(MUSIC_CACHE["music_files"])
|
||||
music_path = os.path.join(MUSIC_CACHE["music_dir"], selected_music)
|
||||
|
||||
if not os.path.exists(music_path):
|
||||
logger.bind(tag=TAG).error(f"选定的音乐文件不存在: {music_path}")
|
||||
conn.logger.bind(tag=TAG).error(f"选定的音乐文件不存在: {music_path}")
|
||||
return
|
||||
text = f"正在播放{selected_music}"
|
||||
text = _get_random_play_prompt(selected_music)
|
||||
await send_stt_message(conn, text)
|
||||
conn.dialogue.put(Message(role="assistant", content=text))
|
||||
conn.tts_first_text_index = 0
|
||||
conn.tts_last_text_index = 0
|
||||
|
||||
tts_file = await asyncio.to_thread(conn.tts.to_tts, text)
|
||||
if tts_file is not None and os.path.exists(tts_file):
|
||||
conn.tts_last_text_index = 1
|
||||
opus_packets, _ = conn.tts.audio_to_opus_data(tts_file)
|
||||
conn.audio_play_queue.put((opus_packets, None, 0))
|
||||
os.remove(tts_file)
|
||||
|
||||
conn.llm_finish_task = True
|
||||
|
||||
if music_path.endswith(".p3"):
|
||||
opus_packets, duration = p3.decode_opus_from_file(music_path)
|
||||
opus_packets, _ = p3.decode_opus_from_file(music_path)
|
||||
else:
|
||||
opus_packets, duration = conn.tts.audio_to_opus_data(music_path)
|
||||
opus_packets, _ = conn.tts.audio_to_opus_data(music_path)
|
||||
conn.tts.tts_audio_queue.put(
|
||||
TTSMessageDTO(
|
||||
u_id=conn.u_id,
|
||||
@@ -226,5 +255,5 @@ async def play_local_music(conn, specific_file=None):
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
logger.bind(tag=TAG).error(f"播放音乐失败: {str(e)}")
|
||||
logger.bind(tag=TAG).error(f"详细错误: {traceback.format_exc()}")
|
||||
conn.logger.bind(tag=TAG).error(f"播放音乐失败: {str(e)}")
|
||||
conn.logger.bind(tag=TAG).error(f"详细错误: {traceback.format_exc()}")
|
||||
|
||||
Reference in New Issue
Block a user