json rpc commander 封装

This commit is contained in:
root
2025-07-11 21:27:17 +08:00
parent 2a16067367
commit 7b50c6e28e
37 changed files with 3518 additions and 2596 deletions

View File

@@ -34,7 +34,7 @@ from .types import (
from .detectors import PySceneDetectDetector
from .validators import BasicVideoValidator
from .service import VideoSplitterService
from .cli import CommandLineInterface
from .cli import VideoSplitterCommander
__version__ = "1.0.0"
__author__ = "Video Splitter Team"
@@ -55,7 +55,7 @@ __all__ = [
"PySceneDetectDetector",
"BasicVideoValidator",
"VideoSplitterService",
"CommandLineInterface",
"VideoSplitterCommander",
]
# 便捷函数

View File

@@ -3,147 +3,99 @@
视频拆分服务命令行接口
"""
import sys
import json
import logging
from typing import Optional, Dict, Any
from typing import Dict, Any
from dataclasses import asdict
from .types import DetectionConfig, DetectorType, ValidationError, DependencyError
from .types import DetectionConfig, DetectorType
from .service import VideoSplitterService
from python_core.utils.commander import JSONRPCCommander
# 导入必需依赖
from python_core.utils.command_utils import (
CommandLineParser, JSONRPCHandler, create_command_service_base
)
logger = logging.getLogger(__name__)
class VideoSplitterCommander(JSONRPCCommander):
"""视频拆分服务命令行接口"""
class CommandLineInterface:
"""命令行接口"""
def __init__(self):
self.service = None
self.rpc_handler = None
def setup_service(self, output_base: Optional[str] = None) -> None:
"""设置服务"""
try:
self.service = VideoSplitterService(output_base_dir=output_base)
except DependencyError as e:
logger.error(f"Service setup failed: {e}")
sys.exit(1)
def setup_rpc_handler(self) -> None:
"""设置RPC处理器"""
try:
service_config = create_command_service_base(
service_name="video_splitter_enhanced",
optional_dependencies={
"jsonrpc": {
"module_name": "python_core.utils.jsonrpc",
"import_items": ["create_response_handler"],
}
}
)
if "jsonrpc" in service_config.get("dependencies", {}):
create_response_handler = service_config["dependencies"]["jsonrpc"]["create_response_handler"]
self.rpc_handler = create_response_handler()
except Exception as e:
logger.warning(f"RPC setup failed: {e}")
# 不设置RPC处理器使用普通JSON输出
def parse_arguments(self) -> tuple:
"""解析命令行参数"""
if len(sys.argv) < 3:
print("Usage: python -m python_core.services.video_splitter <command> <video_path> [options...]")
sys.exit(1)
command = sys.argv[1]
video_path = sys.argv[2]
# 解析配置
if UTILS_AVAILABLE:
arg_definitions = {
"threshold": {"type": float, "default": 30.0},
"detector": {"type": str, "default": "content", "choices": ["content", "threshold"]},
"min-scene-length": {"type": float, "default": 1.0},
"output-base": {"type": str, "default": None}
super().__init__("video_splitter")
def _register_commands(self) -> None:
"""注册命令"""
# 注册analyze命令
self.register_command(
name="analyze",
description="分析视频场景",
required_args=["video_path"],
optional_args={
"threshold": {"type": float, "default": 30.0, "description": "检测阈值"},
"detector": {"type": str, "default": "content", "choices": ["content", "threshold"], "description": "检测器类型"},
"min-scene-length": {"type": float, "default": 1.0, "description": "最小场景长度(秒)"},
"output-base": {"type": str, "default": None, "description": "输出基础目录"}
}
try:
parsed_args = CommandLineParser.parse_command_args(sys.argv[3:], arg_definitions)
config = DetectionConfig(
threshold=parsed_args["threshold"],
detector_type=DetectorType(parsed_args["detector"]),
min_scene_length=parsed_args["min_scene_length"]
)
return command, video_path, config, parsed_args.get("output_base")
except (ValueError, ValidationError) as e:
logger.error(f"Argument error: {e}")
sys.exit(1)
else:
# 简化版参数解析
config = DetectionConfig()
return command, video_path, config, None
def handle_response(self, result: Dict[str, Any], error_code: str) -> None:
"""处理响应"""
if UTILS_AVAILABLE and self.rpc_handler:
JSONRPCHandler.handle_command_response(self.rpc_handler, result, error_code)
else:
print(json.dumps(result, indent=2, ensure_ascii=False))
def run(self) -> None:
"""运行命令行接口"""
# 解析参数
command, video_path, config, output_base = self.parse_arguments()
)
# 注册detect_scenes命令
self.register_command(
name="detect_scenes",
description="检测视频场景(仅返回场景信息)",
required_args=["video_path"],
optional_args={
"threshold": {"type": float, "default": 30.0, "description": "检测阈值"},
"detector": {"type": str, "default": "content", "choices": ["content", "threshold"], "description": "检测器类型"},
"min-scene-length": {"type": float, "default": 1.0, "description": "最小场景长度(秒)"},
"output-base": {"type": str, "default": None, "description": "输出基础目录"}
}
)
def _setup_service(self, output_base: str = None) -> None:
"""设置服务"""
if self.service is None:
self.service = VideoSplitterService(output_base_dir=output_base)
def execute_command(self, command: str, args: Dict[str, Any]) -> Any:
"""执行命令"""
# 设置服务
self.setup_service(output_base)
self.setup_rpc_handler()
# 执行命令
try:
if command == "analyze":
result = self.service.analyze_video(video_path, config)
self.handle_response(result.to_dict(), "ANALYSIS_FAILED")
elif command == "detect_scenes":
result = self.service.analyze_video(video_path, config)
# 只返回场景信息
scenes_result = {
"success": result.success,
"video_path": result.video_path,
"total_scenes": result.total_scenes,
"scenes": [asdict(scene) for scene in result.scenes],
"detection_settings": asdict(config),
"detection_time": result.analysis_time
}
if not result.success:
scenes_result["error"] = result.error
self.handle_response(scenes_result, "DETECTION_FAILED")
else:
error_msg = f"Unknown command: {command}. Available: analyze, detect_scenes"
if self.rpc_handler:
self.rpc_handler.error("INVALID_COMMAND", error_msg)
else:
logger.error(error_msg)
sys.exit(1)
except Exception as e:
logger.error(f"Command execution failed: {e}")
if self.rpc_handler:
self.rpc_handler.error("INTERNAL_ERROR", str(e))
else:
sys.exit(1)
self._setup_service(args.get("output_base"))
# 创建配置
config = DetectionConfig(
threshold=args.get("threshold", 30.0),
detector_type=DetectorType(args.get("detector", "content")),
min_scene_length=args.get("min_scene_length", 1.0)
)
video_path = args["video_path"]
if command == "analyze":
# 完整的视频分析
result = self.service.analyze_video(video_path, config)
return result.to_dict()
elif command == "detect_scenes":
# 仅检测场景
result = self.service.analyze_video(video_path, config)
# 只返回场景信息
scenes_result = {
"success": result.success,
"video_path": result.video_path,
"total_scenes": result.total_scenes,
"scenes": [asdict(scene) for scene in result.scenes],
"detection_settings": asdict(config),
"detection_time": result.analysis_time
}
if not result.success:
scenes_result["error"] = result.error
return scenes_result
else:
raise ValueError(f"Unknown command: {command}")
def main():
"""主函数"""
cli = CommandLineInterface()
cli.run()
commander = VideoSplitterCommander()
commander.run()
if __name__ == "__main__":
main()

View File

@@ -3,39 +3,24 @@
视频场景检测器实现
"""
import logging
from contextlib import contextmanager
from typing import List
from .types import SceneInfo, DetectionConfig, DetectorType, DependencyError, ValidationError
from scenedetect import VideoManager, SceneManager
from scenedetect.detectors import ContentDetector, ThresholdDetector
# 导入必需依赖
from python_core.utils.command_utils import DependencyChecker
from .types import SceneInfo, DetectionConfig, DetectorType
from python_core.utils.logger import logger
class PySceneDetectDetector:
"""PySceneDetect场景检测器实现"""
def __init__(self):
self._check_dependencies()
def _check_dependencies(self) -> None:
"""检查依赖 - 快速失败,不降级"""
available, items = DependencyChecker.check_optional_dependency(
module_name="scenedetect",
import_items=["VideoManager", "SceneManager", "detectors.ContentDetector", "detectors.ThresholdDetector"],
success_message="PySceneDetect is available",
error_message="PySceneDetect not available"
)
if not available:
raise DependencyError("PySceneDetect")
self._scenedetect_items = items
logger.info("PySceneDetect detector initialized")
@contextmanager
def _video_manager(self, video_path: str):
"""视频管理器上下文管理器"""
VideoManager = self._scenedetect_items["VideoManager"]
video_manager = VideoManager([video_path])
try:
video_manager.start()
@@ -46,10 +31,6 @@ class PySceneDetectDetector:
def detect_scenes(self, video_path: str, config: DetectionConfig) -> List[SceneInfo]:
"""检测场景"""
logger.info(f"Detecting scenes: {video_path}, threshold: {config.threshold}")
SceneManager = self._scenedetect_items["SceneManager"]
ContentDetector = self._scenedetect_items["ContentDetector"]
ThresholdDetector = self._scenedetect_items["ThresholdDetector"]
with self._video_manager(video_path) as video_manager:
scene_manager = SceneManager()

View File

@@ -3,18 +3,16 @@
视频拆分服务核心实现
"""
import logging
from pathlib import Path
from typing import Optional
from .types import SceneDetector, VideoValidator, AnalysisResult, DetectionConfig
from .detectors import PySceneDetectDetector
from .validators import BasicVideoValidator
# 导入必需依赖
from python_core.utils.command_utils import PerformanceUtils
from python_core.utils.logger import logger
logger = logging.getLogger(__name__)
class VideoSplitterService:
"""高质量的视频拆分服务"""