mxivideo/docs/video-splitter-jsonrpc.md

427 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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接口 - 让视频拆分服务更易集成!*