# PySceneDetect 视频拆分服务 JSON-RPC 接口

## 🎯 概述

PySceneDetect视频拆分服务现在支持JSON-RPC协议，提供标准化的API接口，便于与其他系统集成。

## 📡 JSON-RPC 协议

### 输出格式
所有命令的输出都遵循JSON-RPC 2.0规范：

#### 成功响应
```json
{
  "jsonrpc": "2.0",
  "id": null,
  "result": {
    // 具体的结果数据
  }
}
```

#### 错误响应
```json
{
  "jsonrpc": "2.0",
  "id": null,
  "error": {
    "code": "ERROR_CODE",
    "message": "错误描述"
  }
}
```

## 🔧 可用命令

### 1. analyze - 视频分析

#### 命令格式
```bash
python python_core/services/video_splitter.py analyze <video_path> [--threshold <value>]
```

#### 参数
- `video_path`: 视频文件路径
- `--threshold`: 检测阈值 (默认: 30.0)

#### 成功响应示例
```json
{
  "jsonrpc": "2.0",
  "id": null,
  "result": {
    "success": true,
    "video_path": "/path/to/video.mp4",
    "total_scenes": 3,
    "total_duration": 10.04,
    "average_scene_duration": 3.35,
    "scenes": [
      {
        "scene_number": 1,
        "start_time": 0.0,
        "end_time": 4.04,
        "duration": 4.04,
        "start_frame": 0,
        "end_frame": 97
      },
      {
        "scene_number": 2,
        "start_time": 4.04,
        "end_time": 8.04,
        "duration": 4.0,
        "start_frame": 97,
        "end_frame": 193
      },
      {
        "scene_number": 3,
        "start_time": 8.04,
        "end_time": 10.04,
        "duration": 2.0,
        "start_frame": 193,
        "end_frame": 241
      }
    ]
  }
}
```

#### 错误响应示例
```json
{
  "jsonrpc": "2.0",
  "id": null,
  "error": {
    "code": "ANALYSIS_FAILED",
    "message": "Video file not found: /path/to/video.mp4"
  }
}
```

### 2. detect_scenes - 场景检测

#### 命令格式
```bash
python python_core/services/video_splitter.py detect_scenes <video_path> [--threshold <value>] [--detector <type>]
```

#### 参数
- `video_path`: 视频文件路径
- `--threshold`: 检测阈值 (默认: 30.0)
- `--detector`: 检测器类型 ("content" 或 "threshold", 默认: "content")

#### 成功响应示例
```json
{
  "jsonrpc": "2.0",
  "id": null,
  "result": {
    "success": true,
    "video_path": "/path/to/video.mp4",
    "total_scenes": 3,
    "scenes": [
      {
        "scene_number": 1,
        "start_time": 0.0,
        "end_time": 4.04,
        "duration": 4.04,
        "start_frame": 0,
        "end_frame": 97
      }
    ],
    "detection_settings": {
      "threshold": 30.0,
      "detector_type": "content"
    }
  }
}
```

### 3. split - 视频拆分

#### 命令格式
```bash
python python_core/services/video_splitter.py split <video_path> [options...]
```

#### 参数
- `video_path`: 视频文件路径
- `--threshold`: 检测阈值 (默认: 30.0)
- `--detector`: 检测器类型 (默认: "content")
- `--output-dir`: 输出目录
- `--output-base`: 输出基础目录

#### 成功响应示例
```json
{
  "jsonrpc": "2.0",
  "id": null,
  "result": {
    "success": true,
    "message": "Successfully split video into 3 scenes",
    "input_video": "/path/to/video.mp4",
    "output_directory": "/tmp/video_splits/video_20250711_201530",
    "scenes": [
      {
        "scene_number": 1,
        "start_time": 0.0,
        "end_time": 4.04,
        "duration": 4.04,
        "start_frame": 0,
        "end_frame": 97
      }
    ],
    "output_files": [
      "/tmp/video_splits/video_20250711_201530/video-Scene-001.mp4",
      "/tmp/video_splits/video_20250711_201530/video-Scene-002.mp4",
      "/tmp/video_splits/video_20250711_201530/video-Scene-003.mp4"
    ],
    "total_scenes": 3,
    "total_duration": 10.04,
    "processing_time": 3.02
  }
}
```

#### 错误响应示例
```json
{
  "jsonrpc": "2.0",
  "id": null,
  "error": {
    "code": "SPLIT_FAILED",
    "message": "FFmpeg failed with return code: 1"
  }
}
```

## 🔍 错误代码

| 错误代码 | 描述 | 可能原因 |
|---------|------|----------|
| `ANALYSIS_FAILED` | 视频分析失败 | 文件不存在、格式不支持 |
| `SPLIT_FAILED` | 视频拆分失败 | FFmpeg错误、磁盘空间不足 |
| `INVALID_COMMAND` | 无效命令 | 命令名称错误 |
| `INTERNAL_ERROR` | 内部错误 | 程序异常、依赖缺失 |

## 💻 编程接口使用

### Python 示例
```python
import subprocess
import json

def call_video_splitter(command, video_path, **kwargs):
    """调用视频拆分服务"""
    cmd = [
        "python", "python_core/services/video_splitter.py",
        command, video_path
    ]
    
    # 添加参数
    for key, value in kwargs.items():
        cmd.extend([f"--{key.replace('_', '-')}", str(value)])
    
    result = subprocess.run(cmd, capture_output=True, text=True)
    
    if result.returncode == 0:
        # 解析JSON-RPC响应
        if result.stdout.startswith("JSONRPC:"):
            json_str = result.stdout[8:]
            return json.loads(json_str)
        else:
            return json.loads(result.stdout)
    else:
        raise Exception(f"Command failed: {result.stderr}")

# 使用示例
try:
    # 分析视频
    response = call_video_splitter("analyze", "video.mp4", threshold=30.0)
    if "result" in response:
        result = response["result"]
        print(f"检测到 {result['total_scenes']} 个场景")
    
    # 拆分视频
    response = call_video_splitter("split", "video.mp4", threshold=30.0)
    if "result" in response:
        result = response["result"]
        if result["success"]:
            print(f"拆分成功: {len(result['output_files'])} 个文件")
        else:
            print(f"拆分失败: {result['message']}")
            
except Exception as e:
    print(f"调用失败: {e}")
```

### Node.js 示例
```javascript
const { spawn } = require('child_process');

function callVideoSplitter(command, videoPath, options = {}) {
    return new Promise((resolve, reject) => {
        const args = [
            'python_core/services/video_splitter.py',
            command,
            videoPath
        ];
        
        // 添加参数
        for (const [key, value] of Object.entries(options)) {
            args.push(`--${key.replace(/_/g, '-')}`, String(value));
        }
        
        const process = spawn('python3', args);
        let stdout = '';
        let stderr = '';
        
        process.stdout.on('data', (data) => {
            stdout += data.toString();
        });
        
        process.stderr.on('data', (data) => {
            stderr += data.toString();
        });
        
        process.on('close', (code) => {
            if (code === 0) {
                try {
                    // 解析JSON-RPC响应
                    let jsonStr = stdout.trim();
                    if (jsonStr.startsWith('JSONRPC:')) {
                        jsonStr = jsonStr.substring(8);
                    }
                    const response = JSON.parse(jsonStr);
                    resolve(response);
                } catch (error) {
                    reject(new Error(`JSON parse error: ${error.message}`));
                }
            } else {
                reject(new Error(`Command failed: ${stderr}`));
            }
        });
    });
}

// 使用示例
async function example() {
    try {
        // 分析视频
        const analyzeResponse = await callVideoSplitter('analyze', 'video.mp4', {
            threshold: 30.0
        });
        
        if (analyzeResponse.result) {
            console.log(`检测到 ${analyzeResponse.result.total_scenes} 个场景`);
        }
        
        // 拆分视频
        const splitResponse = await callVideoSplitter('split', 'video.mp4', {
            threshold: 30.0,
            'output-dir': './output'
        });
        
        if (splitResponse.result && splitResponse.result.success) {
            console.log(`拆分成功: ${splitResponse.result.output_files.length} 个文件`);
        }
        
    } catch (error) {
        console.error('调用失败:', error.message);
    }
}
```

## 🔧 集成建议

### 1. 错误处理
```python
def safe_call_video_splitter(command, video_path, **kwargs):
    try:
        response = call_video_splitter(command, video_path, **kwargs)
        
        if "error" in response:
            # JSON-RPC错误
            error = response["error"]
            raise Exception(f"[{error['code']}] {error['message']}")
        
        if "result" in response:
            result = response["result"]
            if isinstance(result, dict) and not result.get("success", True):
                # 业务逻辑错误
                raise Exception(f"Operation failed: {result.get('error', 'Unknown error')}")
            
            return result
        
        return response
        
    except json.JSONDecodeError as e:
        raise Exception(f"Invalid JSON response: {e}")
    except subprocess.CalledProcessError as e:
        raise Exception(f"Process error: {e}")
```

### 2. 异步处理
```python
import asyncio
import concurrent.futures

async def async_video_splitter(command, video_path, **kwargs):
    """异步调用视频拆分服务"""
    loop = asyncio.get_event_loop()
    
    with concurrent.futures.ThreadPoolExecutor() as executor:
        future = executor.submit(call_video_splitter, command, video_path, **kwargs)
        return await loop.run_in_executor(None, lambda: future.result())

# 使用示例
async def process_videos(video_list):
    tasks = []
    for video_path in video_list:
        task = async_video_splitter("analyze", video_path)
        tasks.append(task)
    
    results = await asyncio.gather(*tasks)
    return results
```

### 3. 批量处理
```python
def batch_process_videos(video_list, command="analyze", **kwargs):
    """批量处理视频"""
    results = []
    
    for video_path in video_list:
        try:
            result = call_video_splitter(command, video_path, **kwargs)
            results.append({
                "video_path": video_path,
                "success": True,
                "result": result
            })
        except Exception as e:
            results.append({
                "video_path": video_path,
                "success": False,
                "error": str(e)
            })
    
    return results
```

## 🎉 总结

PySceneDetect视频拆分服务的JSON-RPC接口提供了：

- ✅ **标准化协议**: 遵循JSON-RPC 2.0规范
- ✅ **完整功能**: 支持分析、检测、拆分三种操作
- ✅ **详细响应**: 包含完整的场景信息和处理结果
- ✅ **错误处理**: 标准化的错误代码和消息
- ✅ **易于集成**: 支持多种编程语言调用

现在可以轻松地将视频拆分功能集成到任何系统中！

---

*JSON-RPC接口 - 让视频拆分服务更易集成！*
