'commit'
This commit is contained in:
@@ -56,18 +56,18 @@ async def get_history(target_name="对方"):
|
||||
# 调用 WxUtil 中的分析函数
|
||||
dialogue_log, input_box = await analyze_chat_image(save_path, analyzed_path, device=d, target_name=target_name)
|
||||
|
||||
# 检查是否正在转换
|
||||
if isinstance(dialogue_log, list) and any("[正在转换语音...]" in str(msg) for msg in dialogue_log):
|
||||
logger.info("检测到语音正在转文字,T2 任务暂停。")
|
||||
return
|
||||
|
||||
logger.info("✅ T2 执行完成。历史对话如下:")
|
||||
logger.info("✅ T2 识别结果:")
|
||||
if dialogue_log:
|
||||
for log in dialogue_log:
|
||||
print(log) # 打印到控制台
|
||||
else:
|
||||
logger.info("未提取到对话内容或当前屏幕无对话气泡。")
|
||||
|
||||
# 检查是否触发了转换
|
||||
if isinstance(dialogue_log, list) and any("[正在转换语音...]" in str(msg) for msg in dialogue_log):
|
||||
logger.info("检测到语音正在转文字,建议等待转换完成后重新运行 T2 以获取完整内容。")
|
||||
return
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"❌ T2 执行失败: {e}")
|
||||
|
||||
|
||||
114
WeiXin/WxUtil.py
114
WeiXin/WxUtil.py
@@ -124,42 +124,56 @@ async def get_vlm_analysis(image_path):
|
||||
|
||||
# 构造 Prompt
|
||||
prompt = """
|
||||
请分析这张微信聊天截图。
|
||||
请分析这张微信聊天截图,提取所有对话消息。
|
||||
|
||||
【核心任务】
|
||||
识别图中的【语音消息气泡】和【文本消息气泡】,并区分【发送者】。
|
||||
⚠️ **特别注意**:必须识别屏幕上**所有**的消息,特别是位于**屏幕最底部**的消息,哪怕只有一部分,也要识别!
|
||||
|
||||
【重要判别规则】
|
||||
1. 👤 **发送者 (Sender)**:
|
||||
- **对方 (Other)**:气泡在屏幕**左侧**,通常为白色或灰色,头像在左边。
|
||||
- **我 (Me)**:气泡在屏幕**右侧**,通常为绿色,头像在右边。
|
||||
|
||||
2. 🔊 **语音消息 (Voice)**:
|
||||
- **视觉特征**:
|
||||
- **高度**:固定(单行)。
|
||||
- **宽度**:随时长(1"~60")变化。
|
||||
- **极短 (1"-2")**:气泡非常短,形状接近一个小正方形。
|
||||
- **极长 (60")**:气泡很长,宽度接近屏幕的一半。
|
||||
- **内容**:气泡内**只有一个**表示时长的数字(如 `8"`)和一个声波图标。
|
||||
- **辅助文字**:语音气泡右侧可能会有灰色的“转文字”或“取消转文字”字样,**请忽略这些文字**,依然将该气泡识别为语音消息!
|
||||
- **绝对排除**:凡是包含汉字、长句子的气泡,**统统不是**语音消息。
|
||||
|
||||
3. 📝 **文本消息 (Text)**:
|
||||
- **视觉特征**:气泡内包含汉字、标点符号、表情等文本内容。
|
||||
|
||||
4. 🔴 **未读状态 (Unread) - 极度重要!**:
|
||||
- **特征**:语音气泡的右上角(或紧邻右侧)有一个明显的**红色圆形小点**。
|
||||
- **判别**:
|
||||
- 只要看到红色小点,`is_unread` 必须为 **true**。
|
||||
- 如果没有红色小点,`is_unread` 为 false。
|
||||
- **注意**:红点可能很小,请仔细观察!这是判断是否处理的关键依据。即使红点旁边有灰色的“转文字”字样,只要有红点,就是未读!
|
||||
【核心规则 - 优先级最高】
|
||||
1. 🚀 **从下往上扫描**:必须确保屏幕最底部的消息被识别。很多时候最底部的消息是最重要的。
|
||||
2. 🔴 **未读红点 (Unread)**:极度关注语音气泡右上角的红点。如果有红点,`is_unread` 必须为 true。
|
||||
3. 📦 **完整性**:识别图中【所有】可见的消息气泡,包括文本消息、语音消息、系统提示(如“昨天 10:36”、“你撤回了一条消息”)。
|
||||
|
||||
【消息类型判别】
|
||||
- **发送者 (Sender)**:左侧头像为“对方”(Other),右侧头像为“我”(Me)。
|
||||
- **语音 (Voice)**:
|
||||
- 气泡内只有时长(如 5")和声波图标。
|
||||
- **重点**:如果语音气泡右侧有灰色的“转文字”字样或红点,且下方没有对应的文本翻译气泡,说明它【尚未转换】。
|
||||
- `status` 判断:只有当语音气泡【正下方】紧跟着一个相同发送者的文本气泡(内容是翻译结果),`status` 才为 "converted"。否则为 "unconverted"。
|
||||
- **文本 (Text)**:气泡内包含具体的文字内容。
|
||||
|
||||
【坐标系统】
|
||||
**必须使用 [0-1000] 的归一化坐标系。**
|
||||
- 左上角为 [0, 0],右下角为 [1000, 1000]。
|
||||
- 请返回气泡的**几何中心点**的归一化坐标。
|
||||
- 使用 [0-1000] 归一化坐标。返回气泡的几何中心点 `center`。
|
||||
- 识别底部输入框的位置 `input_box`。
|
||||
|
||||
【输出格式】
|
||||
请返回纯 JSON 格式:
|
||||
{
|
||||
"is_chat_interface": true,
|
||||
"input_box": [x, y],
|
||||
"messages": [
|
||||
{
|
||||
"type": "voice" | "text" | "system",
|
||||
"sender": "对方" | "我" | "系统",
|
||||
"status": "converted" | "unconverted",
|
||||
"is_unread": true | false,
|
||||
"center": [x, y],
|
||||
"content": "消息内容或时长"
|
||||
},
|
||||
...
|
||||
]
|
||||
}
|
||||
"""
|
||||
2. <EFBFBD> **红点 (Unread)**:极度关注语音气泡右上角的红点。如果有红点,`is_unread` 必须为 true。
|
||||
3. 📦 **完整性**:识别图中【所有】可见的消息气泡。不要遗漏任何一个,特别是连续的语音消息。
|
||||
|
||||
【消息类型判别】
|
||||
- **发送者 (Sender)**:左侧头像为“对方”(Other),右侧头像为“我”(Me)。
|
||||
- **语音 (Voice)**:气泡内只有时长(如 5")和声波图标。
|
||||
- 语音气泡右侧可能有“转文字”或“取消”等灰色小字,请忽略这些文字,气泡依然是 Voice。
|
||||
- `status` 判断:如果语音气泡下方【紧接着】有一个属于同一人的文本气泡,且内容看起来像翻译结果,则 `status` 为 "converted",否则为 "unconverted"。
|
||||
- **文本 (Text)**:气泡内包含具体的文字内容。
|
||||
|
||||
【坐标系统】
|
||||
- 使用 [0-1000] 归一化坐标。返回气泡的几何中心点 `center`。
|
||||
- 识别底部输入框的位置 `input_box`。
|
||||
|
||||
【输出格式】
|
||||
请返回纯 JSON 格式:
|
||||
@@ -175,24 +189,15 @@ async def get_vlm_analysis(image_path):
|
||||
"center": [x, y],
|
||||
"content": "8\""
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"sender": "对方" | "我",
|
||||
"center": [x, y],
|
||||
"content": "这里是文本内容"
|
||||
}
|
||||
...
|
||||
]
|
||||
}
|
||||
注意:
|
||||
1. 坐标 `center` 和 `input_box` 必须是 [0-1000] 的归一化坐标。
|
||||
2. `status` 判断:如果语音气泡的正下方紧挨着一条文本消息(通常是转换出的文字),则为 `converted`,否则为 `unconverted`。
|
||||
3. `is_unread` 判断:务必准确识别红点!如果有红点则为 true。
|
||||
4. 请按从上到下的顺序输出所有消息。
|
||||
"""
|
||||
|
||||
try:
|
||||
# 调用 VLM
|
||||
response = await vlm_kit.analyze_image(image_path, prompt)
|
||||
logger.info(f"VLM Raw Response: {response}") # 打印原始响应以便调试
|
||||
json_str = vlm_kit.extract_json(response)
|
||||
result_data = json.loads(json_str)
|
||||
|
||||
@@ -272,27 +277,38 @@ async def analyze_chat_image(image_path, output_path, device=None, target_name="
|
||||
content = msg.get('content', '')
|
||||
coords = msg.get('center', [0, 0]) # center
|
||||
status = msg.get('status', 'unconverted')
|
||||
is_unread = msg.get('is_unread', False)
|
||||
is_converted = (status == "converted")
|
||||
|
||||
unread_mark = "[未读]" if is_unread else ""
|
||||
|
||||
# 记录对话日志
|
||||
if msg_type == 'voice':
|
||||
if is_converted:
|
||||
dialogue_log.append(f"{sender}: [语音] {content} (已转换)")
|
||||
dialogue_log.append(f"{sender}: {unread_mark}[语音] {content} (已转换)")
|
||||
else:
|
||||
dialogue_log.append(f"{sender}: [语音] (待转换)")
|
||||
dialogue_log.append(f"{sender}: {unread_mark}[语音] (待转换)")
|
||||
# 将 center 转换为 coordinates 供后续使用
|
||||
msg['coordinates'] = coords
|
||||
unconverted_voices.append(msg)
|
||||
elif msg_type == 'text':
|
||||
dialogue_log.append(f"{sender}: {content}")
|
||||
|
||||
logger.info(f"VLM 识别: {sender} [{msg_type}] {content} (Converted: {is_converted})")
|
||||
logger.info(f"VLM 识别: {sender} [{msg_type}] {content} (Converted: {is_converted}, Unread: {is_unread})")
|
||||
|
||||
# 处理未转换的语音消息
|
||||
if unconverted_voices:
|
||||
logger.info(f"发现 {len(unconverted_voices)} 条未转换的语音消息,将仅处理最后一条...")
|
||||
# 仅保留最后一条语音消息进行处理
|
||||
unconverted_voices = [unconverted_voices[-1]]
|
||||
# 优先级:1. 有红点的最后一条 2. 没红点的最后一条
|
||||
unread_voices = [v for v in unconverted_voices if v.get('is_unread')]
|
||||
if unread_voices:
|
||||
logger.info(f"发现 {len(unread_voices)} 条未读语音消息,优先处理最后一条...")
|
||||
voice_to_process = unread_voices[-1]
|
||||
else:
|
||||
logger.info(f"发现 {len(unconverted_voices)} 条未转换语音消息,处理最后一条...")
|
||||
voice_to_process = unconverted_voices[-1]
|
||||
|
||||
# 仅保留选中的一条进行处理
|
||||
unconverted_voices = [voice_to_process]
|
||||
|
||||
# 使用传入的 device 或创建新连接
|
||||
d = device if device else connect_device()
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user