feat:修复一些BUG

This commit is contained in:
2026-01-08 09:49:01 +08:00
parent 820861752b
commit 472b1a0d5e
33 changed files with 1643 additions and 742 deletions

View File

@@ -28,6 +28,7 @@ from __future__ import annotations
import asyncio
import base64
import io
import json
import uuid
from dataclasses import dataclass, field
@@ -37,6 +38,14 @@ from typing import Any, Dict, Optional, TYPE_CHECKING
import aiohttp
from loguru import logger
# 图片处理支持
try:
from PIL import Image
PIL_AVAILABLE = True
except ImportError:
PIL_AVAILABLE = False
logger.warning("[ImageProcessor] Pillow 未安装GIF 转换功能不可用")
# 可选代理支持
try:
from aiohttp_socks import ProxyConnector
@@ -433,6 +442,60 @@ class ImageProcessor:
logger.error(traceback.format_exc())
return ""
def _convert_gif_to_png(self, image_base64: str) -> str:
"""
将 GIF 图片转换为 PNG提取第一帧
Args:
image_base64: GIF 图片的 base64 数据(带 data URI 前缀)
Returns:
PNG 图片的 base64 数据(带 data URI 前缀),失败返回原数据
"""
if not PIL_AVAILABLE:
logger.warning("[ImageProcessor] Pillow 未安装,无法转换 GIF")
return image_base64
try:
# 提取 base64 数据部分
if "," in image_base64:
base64_data = image_base64.split(",", 1)[1]
else:
base64_data = image_base64
# 解码 base64
gif_bytes = base64.b64decode(base64_data)
# 使用 Pillow 打开 GIF 并提取第一帧
img = Image.open(io.BytesIO(gif_bytes))
# 转换为 RGB 模式(去除透明通道)
if img.mode in ('RGBA', 'LA', 'P'):
# 创建白色背景
background = Image.new('RGB', img.size, (255, 255, 255))
if img.mode == 'P':
img = img.convert('RGBA')
background.paste(img, mask=img.split()[-1] if img.mode == 'RGBA' else None)
img = background
elif img.mode != 'RGB':
img = img.convert('RGB')
# 保存为 PNG
output = io.BytesIO()
img.save(output, format='PNG', optimize=True)
png_bytes = output.getvalue()
# 编码为 base64
png_base64 = base64.b64encode(png_bytes).decode()
result = f"data:image/png;base64,{png_base64}"
logger.debug(f"[ImageProcessor] GIF 已转换为 PNG原大小: {len(gif_bytes)} 字节,新大小: {len(png_bytes)} 字节")
return result
except Exception as e:
logger.error(f"[ImageProcessor] GIF 转换失败: {e}")
return image_base64
async def generate_description(
self,
image_base64: str,
@@ -450,6 +513,11 @@ class ImageProcessor:
Returns:
图片描述文本,失败返回空字符串
"""
# 检测并转换 GIF 格式(大多数视觉 API 不支持 GIF
if image_base64.startswith("data:image/gif"):
logger.debug("[ImageProcessor] 检测到 GIF 格式,转换为 PNG...")
image_base64 = self._convert_gif_to_png(image_base64)
description_model = model or self.config.model
messages = [
@@ -612,6 +680,13 @@ class ImageProcessor:
logger.error(f"[ImageProcessor] 视频 API 错误: {resp.status}, {error_text[:300]}")
return ""
# 检查响应类型是否为 JSON
content_type = resp.headers.get('Content-Type', '')
if 'application/json' not in content_type:
error_text = await resp.text()
logger.error(f"[ImageProcessor] 视频 API 返回非 JSON 响应: Content-Type={content_type}, Body={error_text[:500]}")
return ""
result = await resp.json()
# 检查安全过滤