133 lines
4.1 KiB
Python
133 lines
4.1 KiB
Python
|
|
#!/usr/bin/env python3
|
||
|
|
# -*- coding: utf-8 -*-
|
||
|
|
|
||
|
|
"""
|
||
|
|
视频脚本生成引擎 (示例模板)
|
||
|
|
将此文件移动到 engines/ 目录即可启用
|
||
|
|
"""
|
||
|
|
|
||
|
|
from typing import Dict, Any
|
||
|
|
from ..base import BaseAIGCEngine, EngineResult
|
||
|
|
|
||
|
|
|
||
|
|
class VideoScriptEngine(BaseAIGCEngine):
|
||
|
|
"""
|
||
|
|
视频脚本生成引擎
|
||
|
|
|
||
|
|
根据景点信息生成短视频分镜脚本
|
||
|
|
"""
|
||
|
|
|
||
|
|
engine_id = "video_script"
|
||
|
|
engine_name = "视频脚本生成"
|
||
|
|
version = "1.0.0"
|
||
|
|
description = "根据景点信息生成短视频分镜脚本"
|
||
|
|
|
||
|
|
def get_param_schema(self) -> Dict[str, Any]:
|
||
|
|
return {
|
||
|
|
"scenic_spot_id": {
|
||
|
|
"type": "int",
|
||
|
|
"required": True,
|
||
|
|
"desc": "景区 ID",
|
||
|
|
},
|
||
|
|
"duration": {
|
||
|
|
"type": "int",
|
||
|
|
"required": True,
|
||
|
|
"desc": "视频时长 (秒)",
|
||
|
|
},
|
||
|
|
"style": {
|
||
|
|
"type": "str",
|
||
|
|
"required": False,
|
||
|
|
"default": "vlog",
|
||
|
|
"enum": ["vlog", "documentary", "promo", "tutorial"],
|
||
|
|
"desc": "视频风格",
|
||
|
|
},
|
||
|
|
"target_platform": {
|
||
|
|
"type": "str",
|
||
|
|
"required": False,
|
||
|
|
"default": "xiaohongshu",
|
||
|
|
"enum": ["xiaohongshu", "douyin", "bilibili"],
|
||
|
|
"desc": "目标平台",
|
||
|
|
},
|
||
|
|
}
|
||
|
|
|
||
|
|
def estimate_duration(self, params: Dict[str, Any]) -> int:
|
||
|
|
duration = params.get('duration', 60)
|
||
|
|
return 20 + (duration // 10) # 基础时间 + 每10秒视频约1秒生成时间
|
||
|
|
|
||
|
|
async def execute(self, params: Dict[str, Any]) -> EngineResult:
|
||
|
|
task_id = params.get('_task_id', 'unknown')
|
||
|
|
|
||
|
|
try:
|
||
|
|
self.set_progress(task_id, 10)
|
||
|
|
|
||
|
|
# 1. 获取景区信息
|
||
|
|
scenic_spot_id = params['scenic_spot_id']
|
||
|
|
spot = await self.db.scenic_spot.find_by_id(scenic_spot_id)
|
||
|
|
|
||
|
|
if not spot:
|
||
|
|
return EngineResult(
|
||
|
|
success=False,
|
||
|
|
error=f"景区不存在: {scenic_spot_id}",
|
||
|
|
error_code="SPOT_NOT_FOUND"
|
||
|
|
)
|
||
|
|
|
||
|
|
self.set_progress(task_id, 20)
|
||
|
|
|
||
|
|
# 2. 构建提示词
|
||
|
|
duration = params['duration']
|
||
|
|
style = params.get('style', 'vlog')
|
||
|
|
platform = params.get('target_platform', 'xiaohongshu')
|
||
|
|
|
||
|
|
system_prompt, user_prompt = self.prompt.build_full(
|
||
|
|
"video_script",
|
||
|
|
spot_name=spot.get('name', ''),
|
||
|
|
spot_description=spot.get('description', ''),
|
||
|
|
duration=duration,
|
||
|
|
style=style,
|
||
|
|
platform=platform
|
||
|
|
)
|
||
|
|
|
||
|
|
self.set_progress(task_id, 40)
|
||
|
|
|
||
|
|
# 3. 调用 LLM
|
||
|
|
result = await self.llm.generate(
|
||
|
|
prompt=user_prompt,
|
||
|
|
system_prompt=system_prompt
|
||
|
|
)
|
||
|
|
|
||
|
|
self.set_progress(task_id, 80)
|
||
|
|
|
||
|
|
# 4. 解析结果
|
||
|
|
script = self.parse_json(result)
|
||
|
|
|
||
|
|
if not script:
|
||
|
|
return EngineResult(
|
||
|
|
success=False,
|
||
|
|
error="脚本解析失败",
|
||
|
|
error_code="PARSE_ERROR"
|
||
|
|
)
|
||
|
|
|
||
|
|
self.set_progress(task_id, 100)
|
||
|
|
|
||
|
|
return EngineResult(
|
||
|
|
success=True,
|
||
|
|
data={
|
||
|
|
"script": script,
|
||
|
|
"scene_count": len(script.get('scenes', [])),
|
||
|
|
"total_duration": duration,
|
||
|
|
},
|
||
|
|
metadata={
|
||
|
|
"scenic_spot_id": scenic_spot_id,
|
||
|
|
"style": style,
|
||
|
|
"platform": platform,
|
||
|
|
}
|
||
|
|
)
|
||
|
|
|
||
|
|
except Exception as e:
|
||
|
|
self.log(f"视频脚本生成失败: {e}", level='error')
|
||
|
|
return EngineResult(
|
||
|
|
success=False,
|
||
|
|
error=str(e),
|
||
|
|
error_code="EXECUTION_ERROR"
|
||
|
|
)
|