16 KiB
16 KiB
多命令集成设计方案
🎯 设计目标
将所有服务的命令集成到一个统一的CLI中,提供一致的用户体验和管理界面。
🏗️ 架构设计
方案1: 主CLI + 子命令组
mixvideo
├── media # 媒体管理命令组
│ ├── upload
│ ├── batch-upload
│ ├── list
│ └── status
├── scene # 场景检测命令组
│ ├── detect
│ ├── batch-detect
│ ├── compare
│ └── analyze
├── template # 模板管理命令组
│ ├── import
│ ├── export
│ ├── list
│ └── validate
└── system # 系统管理命令组
├── status
├── config
├── storage
└── logs
方案2: 扁平化命令
mixvideo
├── media-upload
├── media-batch-upload
├── scene-detect
├── scene-batch-detect
├── template-import
├── template-export
├── system-status
└── system-config
方案3: 混合方案(推荐)
mixvideo
├── upload # 常用命令提升到顶层
├── batch-upload
├── detect
├── batch-detect
├── media # 完整的媒体管理命令组
├── scene # 完整的场景检测命令组
├── template # 模板管理命令组
└── system # 系统管理命令组
📁 文件结构设计
python_core/
├── cli/ # 统一CLI模块
│ ├── __init__.py
│ ├── main.py # 主CLI入口
│ ├── commands/ # 命令组织
│ │ ├── __init__.py
│ │ ├── media.py # 媒体管理命令组
│ │ ├── scene.py # 场景检测命令组
│ │ ├── template.py # 模板管理命令组
│ │ └── system.py # 系统管理命令组
│ └── utils/ # CLI工具
│ ├── __init__.py
│ ├── common.py # 通用CLI工具
│ └── decorators.py # CLI装饰器
├── services/ # 现有服务保持不变
└── __main__.py # 项目入口
🔧 实现方案
1. 主CLI框架
# python_core/cli/main.py
import typer
from rich.console import Console
from typing import Optional
from .commands import media, scene, template, system
from python_core.utils.progress import ProgressJSONRPCCommander
console = Console()
class MixVideoCommander(ProgressJSONRPCCommander):
"""MixVideo 统一命令行接口"""
def __init__(self):
super().__init__("mixvideo")
self.app = typer.Typer(
name="mixvideo",
help="""
🎬 MixVideo - 智能视频处理平台
功能完整的视频处理和管理工具套件:
• 📤 媒体管理 - 上传、处理、组织视频文件
• 🎯 场景检测 - 智能识别视频场景变化
• 📋 模板管理 - 视频模板导入导出
• ⚙️ 系统管理 - 配置、状态、存储管理
快速开始:
mixvideo upload video.mp4 # 上传视频
mixvideo detect video.mp4 # 检测场景
mixvideo system status # 查看状态
""",
rich_markup_mode="rich",
no_args_is_help=True
)
self._setup_commands()
def _register_commands(self):
"""注册命令(继承要求)"""
pass
def _is_progressive_command(self, command: str) -> bool:
"""判断是否需要进度报告"""
return command.startswith(("batch-", "import-", "export-", "analyze-"))
def _execute_with_progress(self, command: str, args: dict):
"""执行带进度的命令"""
pass
def _execute_simple_command(self, command: str, args: dict):
"""执行简单命令"""
pass
def _setup_commands(self):
"""设置命令结构"""
# 添加子命令组
self.app.add_typer(media.app, name="media", help="📤 媒体管理")
self.app.add_typer(scene.app, name="scene", help="🎯 场景检测")
self.app.add_typer(template.app, name="template", help="📋 模板管理")
self.app.add_typer(system.app, name="system", help="⚙️ 系统管理")
# 添加常用命令到顶层(快捷方式)
self._add_shortcuts()
def _add_shortcuts(self):
"""添加常用命令的快捷方式"""
@self.app.command()
def upload(
video_path: Path = typer.Argument(..., help="📹 视频文件路径"),
tags: Optional[str] = typer.Option(None, "--tags", "-t", help="🏷️ 标签")
):
"""📤 快速上传视频(media upload 的快捷方式)"""
# 调用媒体管理的上传命令
return media.upload_video(video_path, tags)
@self.app.command()
def detect(
video_path: Path = typer.Argument(..., help="📹 视频文件路径"),
threshold: float = typer.Option(30.0, help="🎚️ 检测阈值")
):
"""🎯 快速场景检测(scene detect 的快捷方式)"""
# 调用场景检测的检测命令
return scene.detect_scenes(video_path, threshold)
@self.app.command()
def status():
"""📊 快速状态查看(system status 的快捷方式)"""
# 调用系统状态命令
return system.show_status()
def run(self):
"""运行CLI"""
self.app()
def main():
"""主入口函数"""
commander = MixVideoCommander()
commander.run()
2. 媒体管理命令组
# python_core/cli/commands/media.py
import typer
from pathlib import Path
from typing import Optional
from rich.console import Console
from python_core.services.media_manager import MediaManagerService
from ..utils.common import create_progress_task, parse_tags
console = Console()
app = typer.Typer(help="📤 媒体管理命令")
# 全局服务实例
media_service = MediaManagerService()
@app.command()
def upload(
video_path: Path = typer.Argument(..., help="📹 视频文件路径", exists=True),
tags: Optional[str] = typer.Option(None, "--tags", "-t", help="🏷️ 标签列表"),
filename: Optional[str] = typer.Option(None, "--filename", "-f", help="📝 自定义文件名")
):
"""📤 上传单个视频文件"""
return upload_video(video_path, tags, filename)
@app.command()
def batch_upload(
directory: Path = typer.Argument(..., help="📁 视频目录", exists=True),
tags: Optional[str] = typer.Option(None, "--tags", "-t", help="🏷️ 标签列表"),
recursive: bool = typer.Option(False, "--recursive", "-r", help="🔄 递归扫描")
):
"""📦 批量上传视频文件"""
tag_list = parse_tags(tags)
with create_progress_task("批量上传") as task:
result = media_service.batch_upload(directory, tag_list, recursive)
task.finish(f"上传完成: {result['successful']}/{result['total']} 成功")
return result
@app.command()
def list_videos(
limit: int = typer.Option(10, "--limit", "-l", help="📊 显示数量"),
tags: Optional[str] = typer.Option(None, "--tags", "-t", help="🏷️ 标签过滤")
):
"""📋 列出视频文件"""
# 实现列表逻辑
pass
@app.command()
def delete(
video_id: str = typer.Argument(..., help="🗑️ 视频ID"),
confirm: bool = typer.Option(False, "--yes", "-y", help="✅ 确认删除")
):
"""🗑️ 删除视频文件"""
if not confirm:
confirm = typer.confirm("确定要删除这个视频吗?")
if confirm:
# 实现删除逻辑
console.print("✅ 视频已删除")
else:
console.print("❌ 取消删除")
# 共享函数
def upload_video(video_path: Path, tags: str = None, filename: str = None):
"""上传视频的共享实现"""
tag_list = parse_tags(tags)
console.print(f"🚀 开始上传: [bold blue]{video_path}[/bold blue]")
result = media_service.upload_video(video_path, tag_list, filename)
console.print("✅ [bold green]上传完成[/bold green]")
return result
3. 场景检测命令组
# python_core/cli/commands/scene.py
import typer
from pathlib import Path
from typing import Optional
from rich.console import Console
from python_core.services.scene_detection import SceneDetectionService
from ..utils.common import create_progress_task
console = Console()
app = typer.Typer(help="🎯 场景检测命令")
# 全局服务实例
scene_service = SceneDetectionService()
@app.command()
def detect(
video_path: Path = typer.Argument(..., help="📹 视频文件路径", exists=True),
threshold: float = typer.Option(30.0, help="🎚️ 检测阈值"),
output: Optional[Path] = typer.Option(None, "--output", "-o", help="📄 输出文件")
):
"""🎯 检测单个视频的场景"""
return detect_scenes(video_path, threshold, output)
@app.command()
def batch_detect(
directory: Path = typer.Argument(..., help="📁 视频目录", exists=True),
threshold: float = typer.Option(30.0, help="🎚️ 检测阈值"),
output: Optional[Path] = typer.Option(None, "--output", "-o", help="📄 输出文件")
):
"""📦 批量检测场景"""
with create_progress_task("批量检测") as task:
result = scene_service.batch_detect(directory, threshold)
task.finish(f"检测完成: {result['processed']} 个文件")
return result
@app.command()
def compare(
video_path: Path = typer.Argument(..., help="📹 视频文件路径", exists=True),
thresholds: str = typer.Option("20,30,40", help="🎚️ 阈值列表")
):
"""🔬 比较不同检测器效果"""
with create_progress_task("检测器比较") as task:
result = scene_service.compare_detectors(video_path, thresholds)
task.finish("比较完成")
return result
# 共享函数
def detect_scenes(video_path: Path, threshold: float = 30.0, output: Path = None):
"""场景检测的共享实现"""
console.print(f"🎯 开始检测: [bold blue]{video_path}[/bold blue]")
result = scene_service.detect_single(video_path, threshold)
if output:
scene_service.save_result(result, output)
console.print(f"📄 结果已保存: {output}")
console.print("✅ [bold green]检测完成[/bold green]")
return result
4. 系统管理命令组
# python_core/cli/commands/system.py
import typer
from rich.console import Console
from rich.table import Table
from rich.panel import Panel
from python_core.storage import get_storage
from python_core.config import settings
console = Console()
app = typer.Typer(help="⚙️ 系统管理命令")
@app.command()
def status():
"""📊 显示系统状态"""
return show_status()
@app.command()
def config(
show: bool = typer.Option(False, "--show", help="📋 显示配置"),
set_key: Optional[str] = typer.Option(None, "--set", help="⚙️ 设置配置项"),
value: Optional[str] = typer.Option(None, "--value", help="💾 配置值")
):
"""⚙️ 配置管理"""
if show:
show_config()
elif set_key and value:
set_config(set_key, value)
else:
console.print("❌ 请指定 --show 或 --set 和 --value")
@app.command()
def storage(
action: str = typer.Argument(..., help="📦 操作类型 (info/clean/migrate)"),
target: Optional[str] = typer.Option(None, help="🎯 目标存储类型")
):
"""📦 存储管理"""
if action == "info":
show_storage_info()
elif action == "clean":
clean_storage()
elif action == "migrate":
migrate_storage(target)
else:
console.print("❌ 未知操作类型")
@app.command()
def logs(
lines: int = typer.Option(50, "--lines", "-n", help="📄 显示行数"),
follow: bool = typer.Option(False, "--follow", "-f", help="🔄 实时跟踪")
):
"""📄 查看日志"""
# 实现日志查看逻辑
pass
# 共享函数
def show_status():
"""显示系统状态的共享实现"""
console.print("📊 MixVideo 系统状态")
# 创建状态表格
table = Table(title="系统组件状态")
table.add_column("组件", style="cyan")
table.add_column("状态", style="green")
table.add_column("详情", style="yellow")
# 检查各组件状态
storage = get_storage()
collections = storage.get_collections()
table.add_row("存储系统", "✅ 正常", f"{len(collections)} 个集合")
table.add_row("媒体管理", "✅ 就绪", "服务正常")
table.add_row("场景检测", "✅ 就绪", "服务正常")
table.add_row("模板管理", "✅ 就绪", "服务正常")
console.print(table)
# 系统信息面板
info_panel = Panel(
"[bold blue]MixVideo 运行正常[/bold blue]\n"
"所有核心组件状态良好,系统准备就绪。",
title="📊 系统摘要",
border_style="green"
)
console.print(info_panel)
def show_config():
"""显示配置信息"""
# 实现配置显示逻辑
pass
def set_config(key: str, value: str):
"""设置配置项"""
# 实现配置设置逻辑
pass
5. 通用工具
# python_core/cli/utils/common.py
from contextlib import contextmanager
from typing import List, Optional
from rich.console import Console
console = Console()
def parse_tags(tags_str: Optional[str]) -> List[str]:
"""解析标签字符串"""
if not tags_str:
return []
return [tag.strip() for tag in tags_str.split(",") if tag.strip()]
@contextmanager
def create_progress_task(name: str):
"""创建进度任务的上下文管理器"""
class MockTask:
def __init__(self, name):
self.name = name
console.print(f"🚀 开始{name}...")
def update(self, message: str):
console.print(f"📊 {message}")
def finish(self, message: str):
console.print(f"✅ {message}")
yield MockTask(name)
def confirm_action(message: str, default: bool = False) -> bool:
"""确认操作"""
import typer
return typer.confirm(message, default=default)
def show_error(message: str):
"""显示错误信息"""
console.print(f"❌ [red]{message}[/red]")
def show_success(message: str):
"""显示成功信息"""
console.print(f"✅ [green]{message}[/green]")
def show_warning(message: str):
"""显示警告信息"""
console.print(f"⚠️ [yellow]{message}[/yellow]")
6. 项目入口
# python_core/__main__.py
"""
MixVideo 项目主入口
支持: python -m python_core
"""
from .cli.main import main
if __name__ == "__main__":
main()
🎯 使用示例
命令组方式
# 媒体管理
mixvideo media upload video.mp4 --tags "demo,test"
mixvideo media batch-upload /videos --recursive
mixvideo media list --limit 20
# 场景检测
mixvideo scene detect video.mp4 --threshold 25
mixvideo scene batch-detect /videos --output results.json
mixvideo scene compare video.mp4 --thresholds "20,30,40"
# 模板管理
mixvideo template import /templates --batch
mixvideo template export template_id --output template.json
# 系统管理
mixvideo system status
mixvideo system config --show
mixvideo system storage info
快捷命令方式
# 常用命令的快捷方式
mixvideo upload video.mp4 --tags "demo"
mixvideo detect video.mp4 --threshold 30
mixvideo status
帮助系统
# 查看主帮助
mixvideo --help
# 查看命令组帮助
mixvideo media --help
mixvideo scene --help
# 查看具体命令帮助
mixvideo media upload --help
mixvideo scene detect --help
🎉 方案优势
1. 统一体验
- 🎯 一个入口点,所有功能
- 📋 一致的命令风格和参数
- 🎨 统一的输出格式和样式
2. 灵活使用
- ⚡ 快捷命令满足日常需求
- 🔧 完整命令组满足专业需求
- 📚 清晰的帮助系统
3. 易于扩展
- 🔌 新服务易于集成
- 📦 模块化的命令组织
- 🔄 向后兼容的设计
4. 开发友好
- 🧩 清晰的代码组织
- 🔧 共享的工具函数
- 📝 统一的开发规范
这个设计方案提供了完整的多命令集成解决方案,既保持了各服务的独立性,又提供了统一的用户体验!