8.0 KiB
8.0 KiB
Sora2API 插件修复说明
问题诊断
通过分析日志文件 hookbot.2025-11-25_22-18-49_952160.log,发现问题不是因为提示词太长,而是:
真正的问题:API 返回的视频 URL 存在两种情况
-
成功的情况(域名:
sora.goodnet.icu)- URL 示例:
https://sora.goodnet.icu/tmp/88dd7f3c0fa08c2115b05dae056b5c4e.mp4 - 可以正常下载 ✅
- URL 示例:
-
失败的情况(域名:
oscdn2.dyysy.com)- URL 示例:
https://oscdn2.dyysy.com/MP4/s_6925bc764f388191b51a9f46aa27b0f9.mp4 - 立即返回 404 错误 ❌
- URL 示例:
日志证据
# 成功案例
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)
修改前:
except Exception as e:
logger.error(f"请求异常: {e}")
continue
修改后:
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)
修改前:
logger.info(f"Sora2API请求: {model}, 提示词: {prompt[:50]}...")
修改后:
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)
# 添加提示词长度检查和警告
if len(prompt) > 1000:
logger.warning(f"提示词较长 ({len(prompt)} 字符),可能影响处理速度")
改进点:
- 当提示词超过 1000 字符时发出警告
- 帮助识别潜在的性能问题
4. 改进视频下载函数 (main.py:218-266)
核心改进:404 错误智能处理
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)
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 中可以调整重试次数:
[generation]
max_retry_attempts = 3 # 最大重试次数,建议保持 3 次
测试建议
-
运行测试脚本(可选):
cd WechatHookBot/plugins/Sora2API python test_sora.py -
实际测试:
- 发送命令:
/sora 科比打篮球被蔡徐坤单防 - 观察日志输出
- 如果遇到 404,应该会自动重试
- 发送命令:
-
查看日志:
# 查看最新日志 tail -f WechatHookBot/logs/hookbot.log # 搜索 Sora 相关日志 grep "Sora2API" WechatHookBot/logs/hookbot.log
预期效果
修复后,即使 API 返回 oscdn2.dyysy.com 域名的 404 链接,插件也会:
- ✅ 检测到 404 错误
- ✅ 记录警告日志
- ✅ 自动重试请求
- ✅ 获取新的视频链接
- ✅ 成功下载并发送视频
补充修复:ReadTimeout 超时问题
问题描述
在处理较长提示词(如 370 字符)时,可能会遇到 httpx.ReadTimeout 错误:
ERROR | 请求异常: ReadTimeout:
ERROR | 提示词长度: 370 字符
原因分析
- 视频生成需要较长时间(尤其是长提示词)
- 流式响应在等待数据时可能超过读取超时限制
- 原超时配置(300秒)对于复杂视频生成可能不够
修复方案
1. 增加超时时间 (main.py:114-121)
# 增加到 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)
except httpx.ReadTimeout:
logger.warning(f"读取超时(ReadTimeout),可能是视频生成时间过长,重试中... ({attempt + 1}/{max_retry})")
logger.info(f"提示词长度: {len(prompt)} 字符,建议缩短提示词或增加超时时间")
continue
改进点:
- 单独捕获
ReadTimeout异常 - 提供更友好的错误提示
- 自动重试(最多 3 次)
3. 更新配置文件 (config.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- 本文档