Ai_GirlFriend/xuniYou/最终问题总结和解决方案.md
2026-03-02 18:57:11 +08:00

6.9 KiB
Raw Permalink Blame History

最终问题总结和解决方案

🎉 进展

已解决的问题

  1. 语法错误已修复
  2. 按钮事件可以触发
  3. 录音功能可以启动
  4. 录音文件可以生成
  5. duration/fileSize undefined 问题已绕过

当前问题

问题1: WebSocket 连接不稳定

09:19:33.273 🔌 WebSocket 状态0=CONNECTING, 1=OPEN, 2=CLOSING, 3=CLOSED
09:20:28.752 ⭕ 录音已停止 WebSocket...
09:20:28.753 等待重新连接 WebSocket 连接...
09:20:28.907 WebSocket onOpen[Object] {}

原因

  • WebSocket 在录音过程中断开了
  • 触发了自动重连机制
  • 重连后才开始发送数据

影响

  • 延迟了数据发送
  • 可能导致超时

问题2: 服务器还是 60 秒超时

09:21:29.115 📥 消息内容:{"type":"error","msg":"idle timeout"}

原因

  • 服务器配置可能没有生效
  • 或者服务器没有重启

🔧 解决方案

方案1: 确保服务器配置生效(最重要)

步骤1: 检查服务器 .env 文件

# 在服务器上执行
cat lover/.env

应该看到:

VOICE_CALL_IDLE_TIMEOUT=120

步骤2: 确认服务器已重启

# 停止旧进程
pkill -f "uvicorn.*main:app"

# 确认进程已停止
ps aux | grep uvicorn

# 启动新进程
cd /path/to/lover
uvicorn main:app --host 0.0.0.0 --port 30101 --reload

步骤3: 验证配置

启动后,服务器应该加载新的配置。可以在服务器日志中看到。

方案2: 修复 WebSocket 连接稳定性

问题分析

WebSocket 在录音过程中断开,可能的原因:

  1. 网络不稳定
  2. 服务器主动断开(因为超时)
  3. 客户端没有发送心跳

解决方案A: 添加心跳机制

phone.vue 中添加心跳:

data() {
    return {
        heartbeatTimer: null
    }
},

connectWebSocket() {
    // ... 原有代码 ...
    
    this.socketTask.onOpen((res) => {
        console.log('WebSocket onOpen:', res)
        this.startTimer()
        
        // 启动心跳
        this.startHeartbeat()
    })
},

startHeartbeat() {
    // 清除旧的心跳
    if (this.heartbeatTimer) {
        clearInterval(this.heartbeatTimer)
    }
    
    // 每 30 秒发送一次心跳
    this.heartbeatTimer = setInterval(() => {
        if (this.socketTask && this.socketTask.readyState === 1) {
            console.log('💓 发送心跳')
            this.socketTask.send({
                data: 'ping',
                success: () => {
                    console.log('✅ 心跳发送成功')
                },
                fail: (err) => {
                    console.error('❌ 心跳发送失败:', err)
                }
            })
        }
    }, 30000)  // 30 秒
},

stopCall() {
    // ... 原有代码 ...
    
    // 停止心跳
    if (this.heartbeatTimer) {
        clearInterval(this.heartbeatTimer)
    }
}

解决方案B: 增加 WebSocket 连接检查

在发送数据前,确保 WebSocket 已连接:

async sendAudioInChunks(audioData) {
    // 检查 WebSocket 状态
    if (!this.socketTask || this.socketTask.readyState !== 1) {
        console.error('❌ WebSocket 未连接,等待重连...')
        
        // 等待最多 5 秒
        for (let i = 0; i < 50; i++) {
            await new Promise(resolve => setTimeout(resolve, 100))
            if (this.socketTask && this.socketTask.readyState === 1) {
                console.log('✅ WebSocket 已重连')
                break
            }
        }
        
        // 如果还是未连接,放弃
        if (!this.socketTask || this.socketTask.readyState !== 1) {
            uni.showToast({
                title: 'WebSocket 连接失败',
                icon: 'none'
            })
            return
        }
    }
    
    // 继续原有逻辑...
}

方案3: 临时增加客户端等待时间

如果服务器配置无法立即修改,可以临时在客户端增加等待:

// 在 sendAudioInChunks 中
const chunkDelay = 200  // 从 100ms 增加到 200ms

这样可以延长发送时间,减少超时的可能性。

📊 当前状态分析

时间线

09:19:28 - 开始录音
09:19:33 - 停止录音(录音 5 秒)
09:19:33 - WebSocket 状态检查
09:20:28 - WebSocket 断开并重连(约 55 秒后)
09:20:28 - WebSocket 重新连接
09:21:29 - 收到 idle timeout61 秒后)

问题分析

  1. 录音到停止正常5 秒)
  2. WebSocket 断开:在 55 秒时断开,说明服务器还是 60 秒超时
  3. 重连后发送:重连成功,但已经超过 60 秒
  4. 收到超时:服务器返回 idle timeout

结论

服务器配置没有生效! 服务器还在使用 60 秒的超时配置。

🚀 立即操作

1. 确认服务器配置

在服务器上执行:

cat lover/.env | grep VOICE_CALL_IDLE_TIMEOUT

应该显示:

VOICE_CALL_IDLE_TIMEOUT=120

2. 重启服务器

pkill -f "uvicorn.*main:app"
cd /path/to/lover
uvicorn main:app --host 0.0.0.0 --port 30101 --reload

3. 验证服务器启动

服务器启动后,应该看到:

INFO:     Uvicorn running on http://0.0.0.0:30101

4. 重新测试

  1. 进入语音通话页面
  2. 按住说话 3-5 秒
  3. 松开按钮
  4. 观察日志

5. 预期结果

如果服务器配置生效,应该:

  • 不会在 60 秒时断开
  • 能够完整发送音频数据
  • 收到 ASR 识别结果
  • 收到 LLM 回复
  • 听到 TTS 语音

🐛 如果还是超时

检查1: 服务器是否真的重启了

ps aux | grep uvicorn

查看进程的启动时间,应该是最近的时间。

检查2: 配置文件是否正确

cat lover/.env

确认 VOICE_CALL_IDLE_TIMEOUT=120 存在。

检查3: 服务器是否加载了配置

在服务器代码中添加日志:

# lover/config.py
print(f"VOICE_CALL_IDLE_TIMEOUT = {settings.VOICE_CALL_IDLE_TIMEOUT}")

重启服务器后应该看到:

VOICE_CALL_IDLE_TIMEOUT = 120

💡 临时解决方案

如果服务器配置无法立即生效,可以:

方案A: 直接修改服务器代码

lover/routers/voice_call.py 中:

async def _idle_watchdog(self):
    timeout = 120  # 直接硬编码 120 秒
    # timeout = settings.VOICE_CALL_IDLE_TIMEOUT or 0
    if timeout <= 0:
        return
    # ...

方案B: 加快客户端发送速度

phone.vue 中:

const chunkSize = 3200
const chunkDelay = 50  // 从 100ms 减少到 50ms

这样可以更快地发送完数据。

📞 需要帮助?

如果以上方案都不行,请提供:

  1. 服务器 .env 文件内容
  2. 服务器启动日志
  3. 服务器是否真的重启了
  4. 客户端完整日志

当前状态: 代码正常,但服务器配置未生效
核心问题: 服务器还在使用 60 秒超时
解决方案: 确认服务器配置并重启
预计时间: 5 分钟