|
|
@@ -10,12 +10,16 @@ import json
|
|
|
import time
|
|
|
import asyncio
|
|
|
import requests
|
|
|
+import pysilk
|
|
|
+import wave
|
|
|
+from pydub import AudioSegment
|
|
|
from typing import Optional, Union
|
|
|
from wechaty_puppet import MessageType, FileBox, ScanStatus # type: ignore
|
|
|
from wechaty import Wechaty, Contact
|
|
|
from wechaty.user import Message, Room, MiniProgram, UrlLink
|
|
|
from channel.channel import Channel
|
|
|
from common.log import logger
|
|
|
+from common.tmp_dir import TmpDir
|
|
|
from config import conf
|
|
|
|
|
|
|
|
|
@@ -89,6 +93,48 @@ class WechatyChannel(Channel):
|
|
|
await self._do_send_img(content, to_user_id)
|
|
|
else:
|
|
|
await self._do_send(content, to_user_id)
|
|
|
+ elif room is None and msg.type() == MessageType.MESSAGE_TYPE_AUDIO:
|
|
|
+ if not msg.is_self(): # 接收语音消息
|
|
|
+ # 下载语音文件
|
|
|
+ voice_file = await msg.to_file_box()
|
|
|
+ silk_file = TmpDir().path() + voice_file.name
|
|
|
+ await voice_file.to_file(silk_file)
|
|
|
+ logger.info("[WX]receive voice file: " + silk_file)
|
|
|
+ # 将文件转成wav格式音频
|
|
|
+ wav_file = silk_file.replace(".slk", ".wav")
|
|
|
+ with open(silk_file, 'rb') as f:
|
|
|
+ silk_data = f.read()
|
|
|
+ pcm_data = pysilk.decode(silk_data)
|
|
|
+
|
|
|
+ with wave.open(wav_file, 'wb') as wav_data:
|
|
|
+ wav_data.setnchannels(1)
|
|
|
+ wav_data.setsampwidth(2)
|
|
|
+ wav_data.setframerate(24000)
|
|
|
+ wav_data.writeframes(pcm_data)
|
|
|
+ if os.path.exists(wav_file):
|
|
|
+ converter_state = "true" # 转换wav成功
|
|
|
+ else:
|
|
|
+ converter_state = "false" # 转换wav失败
|
|
|
+ logger.info("[WX]receive voice converter: " + converter_state)
|
|
|
+ # 语音识别为文本
|
|
|
+ query = super().build_voice_to_text(wav_file)
|
|
|
+ # 交验关键字
|
|
|
+ match_prefix = self.check_prefix(query, conf().get('single_chat_prefix'))
|
|
|
+ if match_prefix is not None:
|
|
|
+ if match_prefix != '':
|
|
|
+ str_list = query.split(match_prefix, 1)
|
|
|
+ if len(str_list) == 2:
|
|
|
+ query = str_list[1].strip()
|
|
|
+ # 返回消息
|
|
|
+ if conf().get('voice_reply_voice'):
|
|
|
+ await self._do_send_voice(query, from_user_id)
|
|
|
+ else:
|
|
|
+ await self._do_send(query, from_user_id)
|
|
|
+ else:
|
|
|
+ logger.info("[WX]receive voice check prefix: " + 'False')
|
|
|
+ # 清除缓存文件
|
|
|
+ os.remove(wav_file)
|
|
|
+ os.remove(silk_file)
|
|
|
elif room and msg.type() == MessageType.MESSAGE_TYPE_TEXT:
|
|
|
# 群组&文本消息
|
|
|
room_id = room.room_id
|
|
|
@@ -135,6 +181,39 @@ class WechatyChannel(Channel):
|
|
|
except Exception as e:
|
|
|
logger.exception(e)
|
|
|
|
|
|
+
|
|
|
+ async def _do_send_voice(self, query, reply_user_id):
|
|
|
+ try:
|
|
|
+ if not query:
|
|
|
+ return
|
|
|
+ context = dict()
|
|
|
+ context['session_id'] = reply_user_id
|
|
|
+ reply_text = super().build_reply_content(query, context)
|
|
|
+ if reply_text:
|
|
|
+ # 转换 mp3 文件为 silk 格式
|
|
|
+ mp3_file = super().build_text_to_voice(reply_text)
|
|
|
+ silk_file = mp3_file.replace(".mp3", ".silk")
|
|
|
+ # Load the MP3 file
|
|
|
+ audio = AudioSegment.from_file(mp3_file, format="mp3")
|
|
|
+ # Convert to WAV format
|
|
|
+ audio = audio.set_frame_rate(24000).set_channels(1)
|
|
|
+ wav_data = audio.raw_data
|
|
|
+ sample_width = audio.sample_width
|
|
|
+ # Encode to SILK format
|
|
|
+ silk_data = pysilk.encode(wav_data, 24000)
|
|
|
+ # Save the silk file
|
|
|
+ with open(silk_file, "wb") as f:
|
|
|
+ f.write(silk_data)
|
|
|
+ # 发送语音
|
|
|
+ t = int(time.time())
|
|
|
+ file_box = FileBox.from_file(silk_file, name=str(t) + '.silk')
|
|
|
+ await self.send(file_box, reply_user_id)
|
|
|
+ # 清除缓存文件
|
|
|
+ os.remove(mp3_file)
|
|
|
+ os.remove(silk_file)
|
|
|
+ except Exception as e:
|
|
|
+ logger.exception(e)
|
|
|
+
|
|
|
async def _do_send_img(self, query, reply_user_id):
|
|
|
try:
|
|
|
if not query:
|