Files
WechatHookBot/plugins/Sora2API/修复说明.md
2025-12-03 15:48:44 +08:00

299 lines
8.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Sora2API 插件修复说明
## 问题诊断
通过分析日志文件 `hookbot.2025-11-25_22-18-49_952160.log`,发现问题**不是因为提示词太长**,而是:
### 真正的问题API 返回的视频 URL 存在两种情况
1. **成功的情况**(域名:`sora.goodnet.icu`
- URL 示例:`https://sora.goodnet.icu/tmp/88dd7f3c0fa08c2115b05dae056b5c4e.mp4`
- 可以正常下载 ✅
2. **失败的情况**(域名:`oscdn2.dyysy.com`
- URL 示例:`https://oscdn2.dyysy.com/MP4/s_6925bc764f388191b51a9f46aa27b0f9.mp4`
- 立即返回 404 错误 ❌
### 日志证据
```
# 成功案例
22:18:51 | Sora2API请求: sora-video-portrait-15s, 提示词: 科比打篮球...
22:22:47 | 提取到视频URL: https://sora.goodnet.icu/tmp/88dd7f3c0fa08c2115b05dae056b5c4e.mp4
22:22:58 | 视频下载成功 ✅
# 失败案例
22:25:45 | Sora2API请求: sora-video-landscape-15s, 提示词: 科比在篮球场上打篮球...
22:26:00 | 提取到视频URL: https://oscdn2.dyysy.com/MP4/s_6925bc764f388191b51a9f46aa27b0f9.mp4
22:26:03 | ERROR | 下载视频失败: Client error '404 Not Found' ❌
```
## 修复方案
### 1. 改进错误日志 (main.py:180-185)
**修改前:**
```python
except Exception as e:
logger.error(f"请求异常: {e}")
continue
```
**修改后:**
```python
except Exception as e:
import traceback
logger.error(f"请求异常: {type(e).__name__}: {str(e)}")
logger.error(f"异常详情:\n{traceback.format_exc()}")
logger.error(f"提示词长度: {len(prompt)} 字符")
continue
```
**改进点:**
- 显示完整的异常类型和堆栈跟踪
- 记录提示词长度,便于诊断
- 不再截断错误信息
### 2. 增强调试信息 (main.py:106-109)
**修改前:**
```python
logger.info(f"Sora2API请求: {model}, 提示词: {prompt[:50]}...")
```
**修改后:**
```python
logger.info(f"Sora2API请求: {model}, 提示词长度: {len(prompt)} 字符")
logger.debug(f"完整提示词: {prompt}")
logger.debug(f"请求URL: {url}")
logger.debug(f"Payload大小: {len(str(payload))} 字节")
```
**改进点:**
- 记录提示词长度而不是截断内容
- 添加 DEBUG 级别的详细信息
- 便于排查请求问题
### 3. 添加长提示词警告 (main.py:120-122)
```python
# 添加提示词长度检查和警告
if len(prompt) > 1000:
logger.warning(f"提示词较长 ({len(prompt)} 字符),可能影响处理速度")
```
**改进点:**
- 当提示词超过 1000 字符时发出警告
- 帮助识别潜在的性能问题
### 4. 改进视频下载函数 (main.py:218-266)
**核心改进404 错误智能处理**
```python
async def _download_video(self, url: str, retry_on_404: bool = True) -> Optional[str]:
"""
下载视频到本地
Args:
url: 视频URL
retry_on_404: 是否在404时返回None以触发重试
"""
try:
# ... 下载逻辑 ...
# 检查是否是404错误
if response.status_code == 404:
logger.warning(f"视频URL返回404: {url}")
if retry_on_404:
logger.info("将触发重试以获取新的视频链接")
return None # 返回 None 触发重试
response.raise_for_status()
# ... 保存文件 ...
except httpx.HTTPStatusError as e:
if e.response.status_code == 404:
logger.warning(f"视频URL返回404: {url}")
if retry_on_404:
logger.info("将触发重试以获取新的视频链接")
return None # 返回 None 触发重试
logger.error(f"下载视频失败: {e}")
```
**改进点:**
- 专门处理 404 错误
- 返回 `None` 触发上层重试逻辑
- 区分 404 和其他错误类型
### 5. 添加自动重试机制 (main.py:170-179)
```python
if video_url:
# 下载视频
video_path = await self._download_video(video_url)
if video_path:
logger.success("成功生成视频")
return [video_path]
else:
# 下载失败可能是404继续重试
logger.warning(f"视频下载失败,将重试 ({attempt + 1}/{max_retry})")
continue
```
**改进点:**
- 当下载失败时,自动重新请求 API
- 利用现有的重试机制max_retry_attempts
- 每次重试都会获取新的视频 URL
## 工作原理
### 修复前的流程:
```
1. 请求 API 生成视频
2. 获取视频 URL (可能是 oscdn2.dyysy.com)
3. 尝试下载 → 404 错误
4. ❌ 失败,不再重试
```
### 修复后的流程:
```
1. 请求 API 生成视频
2. 获取视频 URL (可能是 oscdn2.dyysy.com)
3. 尝试下载 → 404 错误
4. 检测到 404返回 None
5. 触发重试机制
6. 重新请求 API 生成视频
7. 获取新的视频 URL (可能是 sora.goodnet.icu)
8. 下载成功 ✅
```
## 配置说明
`config.toml` 中可以调整重试次数:
```toml
[generation]
max_retry_attempts = 3 # 最大重试次数,建议保持 3 次
```
## 测试建议
1. **运行测试脚本**(可选):
```bash
cd WechatHookBot/plugins/Sora2API
python test_sora.py
```
2. **实际测试**
- 发送命令:`/sora 科比打篮球被蔡徐坤单防`
- 观察日志输出
- 如果遇到 404应该会自动重试
3. **查看日志**
```bash
# 查看最新日志
tail -f WechatHookBot/logs/hookbot.log
# 搜索 Sora 相关日志
grep "Sora2API" WechatHookBot/logs/hookbot.log
```
## 预期效果
修复后,即使 API 返回 `oscdn2.dyysy.com` 域名的 404 链接,插件也会:
1. ✅ 检测到 404 错误
2. ✅ 记录警告日志
3. ✅ 自动重试请求
4. ✅ 获取新的视频链接
5. ✅ 成功下载并发送视频
## 补充修复ReadTimeout 超时问题
### 问题描述
在处理较长提示词(如 370 字符)时,可能会遇到 `httpx.ReadTimeout` 错误:
```
ERROR | 请求异常: ReadTimeout:
ERROR | 提示词长度: 370 字符
```
### 原因分析
- 视频生成需要较长时间(尤其是长提示词)
- 流式响应在等待数据时可能超过读取超时限制
- 原超时配置300秒对于复杂视频生成可能不够
### 修复方案
#### 1. 增加超时时间 (main.py:114-121)
```python
# 增加到 10 分钟
max_timeout = min(api_config["timeout"], 600)
timeout = httpx.Timeout(
connect=10.0, # 连接超时10秒
read=max_timeout, # 读取超时10分钟两次数据块之间的最大间隔
write=10.0, # 写入超时10秒
pool=10.0 # 连接池超时10秒
)
```
**关键点:**
- 对于流式响应,`read` 超时是指**两次数据块之间的最大间隔**,而不是总时间
- 增加到 600 秒10分钟以应对长时间的视频生成
#### 2. 专门处理 ReadTimeout (main.py:200-203)
```python
except httpx.ReadTimeout:
logger.warning(f"读取超时ReadTimeout可能是视频生成时间过长重试中... ({attempt + 1}/{max_retry})")
logger.info(f"提示词长度: {len(prompt)} 字符,建议缩短提示词或增加超时时间")
continue
```
**改进点:**
- 单独捕获 `ReadTimeout` 异常
- 提供更友好的错误提示
- 自动重试(最多 3 次)
#### 3. 更新配置文件 (config.toml)
```toml
[api]
timeout = 600 # 请求超时时间(秒),流式响应的读取超时
```
### 工作流程
```
1. 发送长提示词请求
2. 开始接收流式响应
3. 等待视频生成...
4. 如果超过 10 分钟无数据 → ReadTimeout
5. 捕获异常,记录日志
6. 自动重试attempt 2/3
7. 重新请求 API
8. 成功接收响应 ✅
```
## 注意事项
- 如果 3 次重试都失败,会返回错误提示
- 每次重试之间有指数退避延迟2^attempt 秒,最多 10 秒)
- 404 错误不会计入熔断器的失败次数
- ReadTimeout 会自动重试,不影响其他请求
- 代理配置目前被临时禁用(第 124、241 行),如需启用请取消注释
- 如果经常遇到超时,建议:
- 缩短提示词长度
- 或在 `config.toml` 中增加 `timeout` 值(当前 600 秒)
## 相关文件
- `main.py` - 主要修改文件
- `config.toml` - 配置文件
- `test_sora.py` - 测试脚本(新增)
- `修复说明.md` - 本文档