feat:初版

This commit is contained in:
2025-12-03 15:48:44 +08:00
commit b4df26f61d
199 changed files with 23434 additions and 0 deletions

View File

@@ -0,0 +1,298 @@
# 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` - 本文档