zlwu 11 months ago
parent
commit
176a8bb241

+ 1 - 0
frontend/SSL证书配置.md

@@ -127,5 +127,6 @@ ssl/
 
 
 
+
 
 

+ 2 - 4
frontend/src/pages/ChatBotPage copy.tsx

@@ -720,8 +720,6 @@ export const ChatBotPage = () => {
             width: `${layout.treesWidth}px`,
             height: 'auto',
             top: `${layout.treesTop}px`,
-            left: '50%',
-            transform: 'translateX(-50%)',
             opacity: 1,
             zIndex: 1,
           }}
@@ -850,7 +848,7 @@ export const ChatBotPage = () => {
               className="pointer-events-none"
               style={{
                 position: 'absolute',
-                top: '5px',
+                top: `${Math.round(4 * layout.avatarScale)}px`,
                 left: 0,
                 width: '100%',
                 height: '100%',
@@ -863,7 +861,7 @@ export const ChatBotPage = () => {
               className="pointer-events-none"
               style={{
                 position: 'absolute',
-                top: '5px',
+                top: `${Math.round(4 * layout.avatarScale)}px`,
                 left: 0,
                 width: '100%',
                 height: '100%',

+ 5 - 6
frontend/src/pages/ChatBotPage.tsx

@@ -737,17 +737,16 @@ export const ChatBotPage = () => {
           paddingRight: `${horizontalPadding}px`,
         }}
       >
-        {/* 树木装饰 - 设计稿:top 175px, 宽度 395.03px, 高度 220.66px, 左右居中 */}
+        {/* 树木装饰 - 设计稿:top 175px, 宽度 100%, left: -5px */}
         <img
           src={treesImage}
           alt="Trees"
           className="chatbot-trees absolute pointer-events-none"
           style={{
-            width: `${layout.treesWidth}px`,
+            width: '100%',
             height: 'auto',
             top: `${layout.treesTop}px`,
-            left: '50%',
-            transform: 'translateX(-50%)',
+            left: '-5px',
             opacity: 1,
             zIndex: 1,
           }}
@@ -879,7 +878,7 @@ export const ChatBotPage = () => {
               className="pointer-events-none"
               style={{
                 position: 'absolute',
-                top: '4px',
+                top: `${Math.round(5 * layout.avatarScale)}px`,
                 left: 0,
                 width: '100%',
                 height: '100%',
@@ -892,7 +891,7 @@ export const ChatBotPage = () => {
               className="pointer-events-none"
               style={{
                 position: 'absolute',
-                top: '4px',
+                top: `${Math.round(5 * layout.avatarScale)}px`,
                 left: 0,
                 width: '100%',
                 height: '100%',

+ 4 - 0
frontend/src/utils/screenSize.ts

@@ -281,6 +281,7 @@ const BASE_LAYOUT = {
   
   // 装饰元素
   treesWidth: 395,
+  treesLeft: -26,      // 设计稿中树木 left: -26px(向左偏移,部分超出屏幕)
   avatarCSize: 40,
   
   // 情感标签
@@ -320,6 +321,7 @@ export interface CalculatedLayout {
   avatarCTop: number;
   avatarCRight: number;
   treesTop: number;
+  treesLeft: number;   // 树木装饰 left 位置(自适应)
   animaZoneTop: number;
   mainAvatarTop: number;
   emotionTop: number;
@@ -415,6 +417,7 @@ export function calculateLayout(
   const avatarCTop = Math.round(63 * scale); // 设计稿中 Avatar-C 距顶部 63px
   const avatarCRight = Math.round(33 * scale); // 设计稿中 Avatar-C 距右侧 33px
   const treesTop = Math.round(175 * scale); // 设计稿中树木距顶部 175px
+  const treesLeft = Math.round(BASE.treesLeft * scale); // 设计稿中树木 left: -26px(自适应)
   const animaZoneTop = Math.round(BASE.avatarTop * scale); // 设计稿中头像距顶部 248px
   const mainAvatarTop = topSafeArea; // 头像区域从安全区域开始
   const emotionTop = Math.round(BASE.emotionTop * scale); // 设计稿中情感标签距顶部 50px
@@ -520,6 +523,7 @@ export function calculateLayout(
     avatarCTop,
     avatarCRight,
     treesTop,
+    treesLeft,
     animaZoneTop,
     mainAvatarTop,
     emotionTop,

+ 174 - 0
项目文档/STT问题分析报告.md

@@ -0,0 +1,174 @@
+# STT识别问题分析报告
+
+## 问题现象
+
+**时间**: 2025-11-19 11:26:13  
+**Request ID**: `6a34faed-0d2e-46b3-b0b8-2b211f41c886`  
+**错误**: 等待STT识别结果超时,未检测到有效语音
+
+## 日志分析
+
+### ✅ 正常流程
+
+1. **STT连接成功**
+   - WebSocket连接耗时: 331.3ms
+   - 会话创建成功: `sess_QAPuHeZkm26aDPdEIbVjq`
+   - 收到 `session.created` 事件
+
+2. **音频发送成功**
+   - 发送了 **22个音频块**
+   - 录音总时长: **1158ms** (约1.16秒)
+   - 所有音频块都发送成功(无错误)
+
+3. **音频提交成功**
+   - `commit_audio()` 调用成功,耗时: 0.3ms
+
+### ❌ 异常情况
+
+**关键问题:STT服务没有返回任何识别相关事件**
+
+#### 缺失的事件类型
+
+| 事件类型 | 是否收到 | 说明 |
+|---------|---------|------|
+| `session.created` | ✅ | 已收到(正常) |
+| `session.updated` | ❌ | 未收到(可能正常) |
+| `input_audio_buffer.committed` | ❌ | **未收到(异常)** |
+| `input_audio_buffer.speech_started` | ❌ | **未收到(异常)** |
+| `input_audio_buffer.speech_stopped` | ❌ | **未收到(异常)** |
+| `conversation.item.created` | ❌ | **未收到(异常)** |
+| `conversation.item.input_audio_transcription.text` | ❌ | **未收到(异常)** |
+| `conversation.item.input_audio_transcription.completed` | ❌ | **未收到(异常)** |
+
+#### 语音检测状态
+
+```
+speech_detected = False
+speech_start_count = 0
+speech_stop_count = 0
+```
+
+**结论**: STT服务完全没有检测到语音活动。
+
+## 可能原因分析
+
+### 1. 音频质量问题(最可能)
+
+**症状**: 音频数据发送成功,但STT无法识别
+
+**可能原因**:
+- 音频数据是静音(音量太低或没有声音)
+- 音频格式不正确(虽然发送成功,但内容无效)
+- 采样率/声道数不匹配
+
+**验证方法**:
+- 检查前端录音是否正常工作
+- 检查音频数据是否包含有效声音
+- 验证音频格式参数(16kHz, 单声道, PCM)
+
+### 2. STT服务配置问题
+
+**症状**: 连接成功但无响应
+
+**可能原因**:
+- `enable_turn_detection=False` 但需要手动触发
+- `transcription_params` 配置不正确
+- 语言设置问题(当前: `zh`)
+
+**验证方法**:
+- 检查会话配置是否正确应用
+- 查看是否有 `session.updated` 事件
+
+### 3. 音频提交时机问题
+
+**症状**: 提交后无确认事件
+
+**可能原因**:
+- `commit()` 调用时机不对
+- 需要等待更多音频数据
+- STT服务处理延迟
+
+**验证方法**:
+- 检查是否收到 `input_audio_buffer.committed` 事件
+- 增加等待时间观察
+
+### 4. 网络/服务端问题
+
+**症状**: 连接正常但无事件返回
+
+**可能原因**:
+- STT服务端处理异常(静默失败)
+- WebSocket连接实际已断开但未检测到
+- API限流或配额问题
+
+## 建议的解决方案
+
+### 方案1: 增强音频数据验证
+
+```python
+# 在发送音频前验证音频数据
+def validate_audio_data(audio_data: bytes) -> bool:
+    """验证音频数据是否包含有效声音"""
+    # 检查音频数据是否全为0(静音)
+    if all(b == 0 for b in audio_data):
+        return False
+    
+    # 检查音频振幅(简单验证)
+    import struct
+    samples = struct.unpack(f'<{len(audio_data)//2}h', audio_data)
+    max_amplitude = max(abs(s) for s in samples)
+    if max_amplitude < 100:  # 阈值可调
+        return False
+    
+    return True
+```
+
+### 方案2: 增加事件监听超时
+
+```python
+# 在等待识别结果时,增加中间事件检查
+async def wait_for_final_result(self, timeout: float = 3.0):
+    # 检查是否收到任何事件
+    if not self.callback.received_any_event:
+        logger.warning("STT服务未返回任何事件")
+```
+
+### 方案3: 添加音频数据采样日志
+
+```python
+# 记录音频数据的统计信息
+logger.info(
+    f"音频数据统计: "
+    f"长度={len(audio_data)}, "
+    f"最大振幅={max_amplitude}, "
+    f"平均振幅={avg_amplitude}, "
+    f"零值比例={zero_ratio:.2%}"
+)
+```
+
+### 方案4: 检查STT服务配置
+
+确认以下配置是否正确:
+- `language='zh'` - 中文识别
+- `sample_rate=16000` - 采样率
+- `input_audio_format='pcm'` - 音频格式
+- `enable_turn_detection=False` - 禁用VAD(手动控制)
+
+## 下一步行动
+
+1. **立即检查**: 前端录音功能是否正常,音频数据是否包含有效声音
+2. **添加日志**: 在发送音频前记录音频数据统计(振幅、零值比例等)
+3. **延长超时**: 将等待超时从3秒增加到5秒,观察是否有延迟响应
+4. **验证配置**: 确认STT会话配置是否正确应用
+5. **测试用例**: 使用已知有效的音频文件进行测试
+
+## 相关日志片段
+
+```
+[STT连接成功] request_id=6a34faed-0d2e-46b3-b0b8-2b211f41c886, 尝试次数=1, 耗时=335.0ms
+[STT] request_id=6a34faed-0d2e-46b3-b0b8-2b211f41c886, 准备发送音频: 原始长度=1024 bytes, Base64长度=1368 chars
+... (22个音频块发送成功) ...
+[STT] request_id=6a34faed-0d2e-46b3-b0b8-2b211f41c886, 音频提交成功, 耗时=0.3ms
+[STT警告] request_id=6a34faed-0d2e-46b3-b0b8-2b211f41c886, 错误类型=等待识别结果超时, 超时时间=3.0秒, 等待耗时=3001.8ms, 当前识别文本=, 语音检测状态=speech_detected=False, speech_start_count=0, speech_stop_count=0
+```
+