Merge branch 'master' of https://github.com/MoFox-Studio/MoFox_Bot
This commit is contained in:
@@ -206,7 +206,7 @@ class APITestHandler(BaseEventHandler):
|
|||||||
@register_plugin
|
@register_plugin
|
||||||
class NapcatAdapterPlugin(BasePlugin):
|
class NapcatAdapterPlugin(BasePlugin):
|
||||||
plugin_name = CONSTS.PLUGIN_NAME
|
plugin_name = CONSTS.PLUGIN_NAME
|
||||||
enable_plugin: bool = True
|
enable_plugin: bool = False
|
||||||
dependencies: List[str] = [] # 插件依赖列表
|
dependencies: List[str] = [] # 插件依赖列表
|
||||||
python_dependencies: List[str] = [] # Python包依赖列表
|
python_dependencies: List[str] = [] # Python包依赖列表
|
||||||
config_file_name: str = "config.toml" # 配置文件名
|
config_file_name: str = "config.toml" # 配置文件名
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ class EnergyManager:
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
# 判断当前是否为睡眠时间
|
# 判断当前是否为睡眠时间
|
||||||
is_sleeping = schedule_manager.is_sleeping(self.context.wakeup_manager)
|
is_sleeping = schedule_manager.is_sleeping()
|
||||||
|
|
||||||
if is_sleeping:
|
if is_sleeping:
|
||||||
# 睡眠中:减少睡眠压力
|
# 睡眠中:减少睡眠压力
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ from maim_message import Seg, UserInfo, BaseMessageInfo, MessageBase
|
|||||||
from src.common.logger import get_logger
|
from src.common.logger import get_logger
|
||||||
from src.chat.utils.utils_image import get_image_manager
|
from src.chat.utils.utils_image import get_image_manager
|
||||||
from src.chat.utils.utils_voice import get_voice_text
|
from src.chat.utils.utils_voice import get_voice_text
|
||||||
from src.chat.utils.utils_video import get_video_analyzer
|
from src.chat.utils.utils_video import get_video_analyzer, is_video_analysis_available
|
||||||
from src.config.config import global_config
|
from src.config.config import global_config
|
||||||
from .chat_stream import ChatStream
|
from .chat_stream import ChatStream
|
||||||
|
|
||||||
@@ -203,6 +203,12 @@ class MessageRecv(Message):
|
|||||||
self.is_voice = False
|
self.is_voice = False
|
||||||
self.is_video = True
|
self.is_video = True
|
||||||
logger.info(f"接收到视频消息,数据类型: {type(segment.data)}")
|
logger.info(f"接收到视频消息,数据类型: {type(segment.data)}")
|
||||||
|
|
||||||
|
# 检查视频分析功能是否可用
|
||||||
|
if not is_video_analysis_available():
|
||||||
|
logger.warning("⚠️ Rust视频处理模块不可用,跳过视频分析")
|
||||||
|
return "[视频]"
|
||||||
|
|
||||||
if global_config.video_analysis.enable:
|
if global_config.video_analysis.enable:
|
||||||
logger.info("已启用视频识别,开始识别")
|
logger.info("已启用视频识别,开始识别")
|
||||||
if isinstance(segment.data, dict):
|
if isinstance(segment.data, dict):
|
||||||
@@ -378,6 +384,12 @@ class MessageRecvS4U(MessageRecv):
|
|||||||
self.is_emoji = False
|
self.is_emoji = False
|
||||||
|
|
||||||
logger.info(f"接收到视频消息,数据类型: {type(segment.data)}")
|
logger.info(f"接收到视频消息,数据类型: {type(segment.data)}")
|
||||||
|
|
||||||
|
# 检查视频分析功能是否可用
|
||||||
|
if not is_video_analysis_available():
|
||||||
|
logger.warning("⚠️ Rust视频处理模块不可用,跳过视频分析")
|
||||||
|
return "[视频]"
|
||||||
|
|
||||||
if global_config.video_analysis.enable:
|
if global_config.video_analysis.enable:
|
||||||
logger.info("已启用视频识别,开始识别")
|
logger.info("已启用视频识别,开始识别")
|
||||||
if isinstance(segment.data, dict):
|
if isinstance(segment.data, dict):
|
||||||
|
|||||||
@@ -25,10 +25,18 @@ from src.common.database.sqlalchemy_models import get_db_session, Videos
|
|||||||
|
|
||||||
logger = get_logger("utils_video")
|
logger = get_logger("utils_video")
|
||||||
|
|
||||||
# 导入 Rust 视频处理模块
|
# Rust模块可用性检测
|
||||||
import rust_video
|
RUST_VIDEO_AVAILABLE = False
|
||||||
|
try:
|
||||||
logger.info("✅ Rust 视频处理模块加载成功")
|
import rust_video
|
||||||
|
RUST_VIDEO_AVAILABLE = True
|
||||||
|
logger.info("✅ Rust 视频处理模块加载成功")
|
||||||
|
except ImportError as e:
|
||||||
|
logger.warning(f"⚠️ Rust 视频处理模块加载失败: {e}")
|
||||||
|
logger.warning("⚠️ 视频识别功能将自动禁用")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"❌ 加载Rust模块时发生错误: {e}")
|
||||||
|
RUST_VIDEO_AVAILABLE = False
|
||||||
|
|
||||||
# 全局正在处理的视频哈希集合,用于防止重复处理
|
# 全局正在处理的视频哈希集合,用于防止重复处理
|
||||||
processing_videos = set()
|
processing_videos = set()
|
||||||
@@ -44,6 +52,14 @@ class VideoAnalyzer:
|
|||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""初始化视频分析器"""
|
"""初始化视频分析器"""
|
||||||
|
# 检查Rust模块是否可用
|
||||||
|
if not RUST_VIDEO_AVAILABLE:
|
||||||
|
logger.warning("⚠️ Rust视频处理模块不可用,视频分析器将以降级模式运行")
|
||||||
|
self.disabled = True
|
||||||
|
return
|
||||||
|
|
||||||
|
self.disabled = False
|
||||||
|
|
||||||
# 使用专用的视频分析配置
|
# 使用专用的视频分析配置
|
||||||
try:
|
try:
|
||||||
self.video_llm = LLMRequest(
|
self.video_llm = LLMRequest(
|
||||||
@@ -58,7 +74,7 @@ class VideoAnalyzer:
|
|||||||
request_type="vlm"
|
request_type="vlm"
|
||||||
)
|
)
|
||||||
logger.warning(f"video_analysis配置不可用({e}),回退使用vlm配置")
|
logger.warning(f"video_analysis配置不可用({e}),回退使用vlm配置")
|
||||||
|
|
||||||
# 从配置文件读取参数,如果配置不存在则使用默认值
|
# 从配置文件读取参数,如果配置不存在则使用默认值
|
||||||
config = global_config.video_analysis
|
config = global_config.video_analysis
|
||||||
|
|
||||||
@@ -138,6 +154,10 @@ class VideoAnalyzer:
|
|||||||
|
|
||||||
def _log_system_info(self):
|
def _log_system_info(self):
|
||||||
"""记录系统信息"""
|
"""记录系统信息"""
|
||||||
|
if not RUST_VIDEO_AVAILABLE:
|
||||||
|
logger.info("⚠️ Rust模块不可用,跳过系统信息获取")
|
||||||
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
system_info = rust_video.get_system_info()
|
system_info = rust_video.get_system_info()
|
||||||
logger.info(f"🔧 系统信息: 线程数={system_info.get('threads', '未知')}")
|
logger.info(f"🔧 系统信息: 线程数={system_info.get('threads', '未知')}")
|
||||||
@@ -240,6 +260,10 @@ class VideoAnalyzer:
|
|||||||
|
|
||||||
async def extract_frames(self, video_path: str) -> List[Tuple[str, float]]:
|
async def extract_frames(self, video_path: str) -> List[Tuple[str, float]]:
|
||||||
"""提取视频帧 - 使用 Rust 实现"""
|
"""提取视频帧 - 使用 Rust 实现"""
|
||||||
|
if not RUST_VIDEO_AVAILABLE:
|
||||||
|
logger.error("❌ Rust视频处理模块不可用,无法提取视频帧")
|
||||||
|
return []
|
||||||
|
|
||||||
# 优先尝试高级接口,失败时回退到基础接口
|
# 优先尝试高级接口,失败时回退到基础接口
|
||||||
try:
|
try:
|
||||||
return await self._extract_frames_rust_advanced(video_path)
|
return await self._extract_frames_rust_advanced(video_path)
|
||||||
@@ -545,6 +569,11 @@ class VideoAnalyzer:
|
|||||||
Returns:
|
Returns:
|
||||||
Tuple[bool, str]: (是否成功, 分析结果或错误信息)
|
Tuple[bool, str]: (是否成功, 分析结果或错误信息)
|
||||||
"""
|
"""
|
||||||
|
if self.disabled or not RUST_VIDEO_AVAILABLE:
|
||||||
|
error_msg = "❌ 视频分析功能已禁用:Rust视频处理模块不可用"
|
||||||
|
logger.warning(error_msg)
|
||||||
|
return (False, error_msg)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
logger.info(f"开始分析视频: {os.path.basename(video_path)}")
|
logger.info(f"开始分析视频: {os.path.basename(video_path)}")
|
||||||
|
|
||||||
@@ -588,6 +617,9 @@ class VideoAnalyzer:
|
|||||||
Returns:
|
Returns:
|
||||||
Dict[str, str]: 包含分析结果的字典,格式为 {"summary": "分析结果"}
|
Dict[str, str]: 包含分析结果的字典,格式为 {"summary": "分析结果"}
|
||||||
"""
|
"""
|
||||||
|
if self.disabled or not RUST_VIDEO_AVAILABLE:
|
||||||
|
return {"summary": "❌ 视频分析功能已禁用:Rust视频处理模块不可用"}
|
||||||
|
|
||||||
video_hash = None
|
video_hash = None
|
||||||
video_event = None
|
video_event = None
|
||||||
|
|
||||||
@@ -717,6 +749,13 @@ class VideoAnalyzer:
|
|||||||
|
|
||||||
def get_processing_capabilities(self) -> Dict[str, any]:
|
def get_processing_capabilities(self) -> Dict[str, any]:
|
||||||
"""获取处理能力信息"""
|
"""获取处理能力信息"""
|
||||||
|
if not RUST_VIDEO_AVAILABLE:
|
||||||
|
return {
|
||||||
|
"error": "Rust视频处理模块不可用",
|
||||||
|
"available": False,
|
||||||
|
"reason": "rust_video模块未安装或加载失败"
|
||||||
|
}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
system_info = rust_video.get_system_info()
|
system_info = rust_video.get_system_info()
|
||||||
|
|
||||||
@@ -732,14 +771,15 @@ class VideoAnalyzer:
|
|||||||
"cpu_features": cpu_features,
|
"cpu_features": cpu_features,
|
||||||
"recommended_settings": self._get_recommended_settings(cpu_features),
|
"recommended_settings": self._get_recommended_settings(cpu_features),
|
||||||
"analysis_modes": ["auto", "batch", "sequential"],
|
"analysis_modes": ["auto", "batch", "sequential"],
|
||||||
"supported_formats": ['.mp4', '.avi', '.mov', '.mkv', '.flv', '.wmv', '.m4v', '.3gp', '.webm']
|
"supported_formats": ['.mp4', '.avi', '.mov', '.mkv', '.flv', '.wmv', '.m4v', '.3gp', '.webm'],
|
||||||
|
"available": True
|
||||||
}
|
}
|
||||||
|
|
||||||
return capabilities
|
return capabilities
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"获取处理能力信息失败: {e}")
|
logger.error(f"获取处理能力信息失败: {e}")
|
||||||
return {"error": str(e)}
|
return {"error": str(e), "available": False}
|
||||||
|
|
||||||
def _get_recommended_settings(self, cpu_features: Dict[str, bool]) -> Dict[str, any]:
|
def _get_recommended_settings(self, cpu_features: Dict[str, bool]) -> Dict[str, any]:
|
||||||
"""根据CPU特性推荐最佳设置"""
|
"""根据CPU特性推荐最佳设置"""
|
||||||
@@ -773,3 +813,32 @@ def get_video_analyzer() -> VideoAnalyzer:
|
|||||||
if _video_analyzer is None:
|
if _video_analyzer is None:
|
||||||
_video_analyzer = VideoAnalyzer()
|
_video_analyzer = VideoAnalyzer()
|
||||||
return _video_analyzer
|
return _video_analyzer
|
||||||
|
|
||||||
|
def is_video_analysis_available() -> bool:
|
||||||
|
"""检查视频分析功能是否可用
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: 如果Rust视频处理模块可用且功能未禁用则返回True
|
||||||
|
"""
|
||||||
|
return RUST_VIDEO_AVAILABLE
|
||||||
|
|
||||||
|
def get_video_analysis_status() -> Dict[str, any]:
|
||||||
|
"""获取视频分析功能的详细状态信息
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Dict[str, any]: 包含功能状态信息的字典
|
||||||
|
"""
|
||||||
|
status = {
|
||||||
|
"available": RUST_VIDEO_AVAILABLE,
|
||||||
|
"module_name": "rust_video",
|
||||||
|
"description": "Rust视频处理模块"
|
||||||
|
}
|
||||||
|
|
||||||
|
if not RUST_VIDEO_AVAILABLE:
|
||||||
|
status.update({
|
||||||
|
"error": "模块未安装或加载失败",
|
||||||
|
"solution": "请安装rust_video模块或检查编译环境",
|
||||||
|
"fallback_enabled": True
|
||||||
|
})
|
||||||
|
|
||||||
|
return status
|
||||||
|
|||||||
@@ -260,7 +260,7 @@ class LLMRequest:
|
|||||||
try:
|
try:
|
||||||
# 为 _execute_single_request 传递参数时,将 raise_when_empty 设为 False,
|
# 为 _execute_single_request 传递参数时,将 raise_when_empty 设为 False,
|
||||||
# 这样单个请求失败时不会立即抛出异常,而是由 gather 统一处理
|
# 这样单个请求失败时不会立即抛出异常,而是由 gather 统一处理
|
||||||
return await execute_concurrently(
|
content, (reasoning_content, model_name, tool_calls) = await execute_concurrently(
|
||||||
self._execute_single_request,
|
self._execute_single_request,
|
||||||
concurrency_count,
|
concurrency_count,
|
||||||
prompt,
|
prompt,
|
||||||
@@ -269,6 +269,7 @@ class LLMRequest:
|
|||||||
tools,
|
tools,
|
||||||
raise_when_empty=False,
|
raise_when_empty=False,
|
||||||
)
|
)
|
||||||
|
return content, (reasoning_content, model_name, tool_calls)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"所有 {concurrency_count} 个并发请求都失败了: {e}")
|
logger.error(f"所有 {concurrency_count} 个并发请求都失败了: {e}")
|
||||||
if raise_when_empty:
|
if raise_when_empty:
|
||||||
|
|||||||
Reference in New Issue
Block a user