Zhuyuan Operations ce32073d07 D205 面板功能大升级+本地漫剧管线+经验自动机制+飞书资料归档
- 面板: 会话持久化(oc_sess.json)/余额实时/文件栏(搜索+MD+拖拽)/朗读(edge-tts)/工具过程实时显示/漫剧画布
- 面板: 经验自动检索注入+存经验按钮(experience.py)
- 管线: local_motion本地运镜/IMAGE-FIRST-GUIDE/LOCAL-PIPELINE-V1
- 经验: EED-EXPER-014 面板工程+管线+飞书扒取全记录
- 资料: 飞书《清欢AIGC伪真人短剧全流程》归档
2026-08-03 22:55:02 +08:00

266 lines
9.2 KiB
Python
Executable File
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.

#!/usr/bin/env python3
"""
pipeline.py — 苍耳管线 · 统一生产入口
整合所有工具为一条命令链路:剧本→分镜→路由→出图→放大→拼接→配乐→成片
用法:
python pipeline.py storyboard <剧本> -e 1 # ① 剧本→分镜
python pipeline.py route <分镜.json> # ② 路由分配
python pipeline.py render <分镜.json> # ③ 批量出图
python pipeline.py upscale <图片文件夹> # ④ 高清放大
python pipeline.py compose <文件夹> -o EP01.mp4 # ⑤ 剪辑拼接
python pipeline.py assets <项目目录> # ⑥ 资产生成
# 一键全自动需要API密钥
python pipeline.py go <剧本> -e 1 # ⑦ 全自动一条龙
"""
import sys, os, json, argparse, subprocess
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
def cmd_storyboard(args):
"""① 剧本→分镜"""
sys.argv = ['run_storyboard.py', args.script, '-e', str(args.episode)]
if args.pro:
sys.argv.append('--pro')
if args.dry_run:
sys.argv.append('--dry-run')
if args.output:
sys.argv.extend(['-o', args.output])
from tools.run_storyboard import main
main()
def cmd_route(args):
"""② 路由分配"""
sys.argv = ['route_shots.py', args.storyboard]
if args.dry_run:
sys.argv.append('--dry-run')
if args.summary:
sys.argv.append('--summary')
if args.output:
sys.argv.extend(['-o', args.output])
from tools.route_shots import main
main()
def cmd_render(args):
"""③ 分镜→出图桥接"""
sys.argv = ['storyboard_to_workflow.py', args.storyboard]
if args.output_dir:
sys.argv.extend(['-o', args.output_dir])
if args.style:
sys.argv.extend(['--style', args.style])
if args.generate_sh:
sys.argv.append('--generate-sh')
if args.workflow:
sys.argv.extend(['--workflow', args.workflow])
from tools.storyboard_to_workflow import main
main()
def cmd_upscale(args):
"""④ 高清放大"""
from tools.storyboard_to_workflow import main as sb_main
print('🔍 高清放大: 可使用 ComfyUI 蓝图 Image Upscale(Z-image-Turbo).json')
print(f' 打开 ComfyUI → 加载蓝图 → Image Upscale')
print(f' 输入图片: {args.input_dir}')
print()
print(' 或运行已生成的工作流JSON (如果有):')
print(f' ls {args.input_dir}/workflows/')
def cmd_compose(args):
"""⑤ 剪辑拼接"""
sys.argv = ['video_composer.py', args.folder, '-o', args.output]
if args.title:
sys.argv.extend(['--title', args.title])
if args.credits:
sys.argv.extend(['--credits', args.credits])
if args.subtitle:
sys.argv.extend(['--subtitle', args.subtitle])
if args.crossfade:
sys.argv.extend(['--crossfade', str(args.crossfade)])
from tools.video_composer import main
main()
def cmd_assets(args):
"""⑥ 资产生成"""
sys.argv = ['generate_assets_local.py', args.project_dir]
if args.list:
sys.argv.append('--list')
if args.dry_run:
sys.argv.append('--dry-run')
if args.comfy_url:
sys.argv.extend(['--comfy-url', args.comfy_url])
from tools.generate_assets_local import main
main()
def cmd_go(args):
"""⑦ 一键全自动(剧本→成片)"""
script_path = args.script
episode = args.episode
print(f'🚀 苍耳管线 · 全自动模式')
print(f'📖 剧本: {script_path}')
print(f'🎬 集号: EP{episode:02d}')
print()
# 检查文件
if not os.path.isfile(script_path):
print(f'❌ 找不到剧本: {script_path}')
sys.exit(1)
# Step 1: 剧本→分镜
print('' * 40)
print('① 剧本→分镜')
print('' * 40)
sys.argv = ['run_storyboard.py', script_path, '-e', str(episode)]
if args.pro:
sys.argv.append('--pro')
from tools.run_storyboard import main as sb_main
try:
sb_main()
except SystemExit:
pass
# 找生成的分镜JSON
script_dir = os.path.dirname(os.path.abspath(script_path))
script_base = os.path.splitext(os.path.basename(script_path))[0]
sb_json = None
for f in os.listdir(script_dir):
if f.startswith('STORYBOARD') and f.endswith('.json'):
sb_json = os.path.join(script_dir, f)
if not sb_json:
print('❌ 找不到生成的分镜JSON')
sys.exit(1)
print(f'\n✅ 分镜: {sb_json}')
# Step 2: 路由分配
print()
print('' * 40)
print('② 逐镜路由分配')
print('' * 40)
sys.argv = ['route_shots.py', sb_json]
from tools.route_shots import main as rt_main
try:
rt_main()
except SystemExit:
pass
# Step 3: 生成出图工作流
print()
print('' * 40)
print('③ 生成出图工作流')
print('' * 40)
sys.argv = ['storyboard_to_workflow.py', sb_json]
if args.style:
sys.argv.extend(['--style', args.style])
sys.argv.append('--generate-sh')
from tools.storyboard_to_workflow import main as sw_main
try:
sw_main()
except SystemExit:
pass
print()
print('' * 40)
print('🎯 完成! 后续步骤:')
print('' * 40)
print(f' 📄 分镜: {sb_json}')
print(f' 📋 路由: 已写入分镜JSON')
print(f' 🎨 出图: 启动ComfyUI后运行渲染脚本')
print(f' ✂️ 剪辑: python pipeline.py compose <输出目录> -o EP{episode:02d}.mp4')
def main():
parser = argparse.ArgumentParser(description='苍耳管线 · 统一生产入口')
parser.add_argument('command', nargs='?', default='help',
help='命令: storyboard|route|render|upscale|compose|assets|go')
parser.add_argument('args', nargs='*', help='命令参数')
# 先解析command
known_commands = ['storyboard', 'route', 'render', 'upscale', 'compose', 'assets', 'go', 'help']
if len(sys.argv) < 2 or sys.argv[1] not in known_commands:
print(__doc__)
return
cmd = sys.argv[1]
if cmd == 'help':
print(__doc__)
return
# 移除第一个参数(command)让子命令的argparse自己解析
# 但我们需要根据command来设置子解析器
if cmd == 'storyboard':
p = argparse.ArgumentParser()
p.add_argument('script', help='剧本文件路径')
p.add_argument('-e', '--episode', type=int, default=1, help='集号')
p.add_argument('--pro', action='store_true', help='使用Pro模型')
p.add_argument('-o', '--output', help='输出路径')
p.add_argument('--dry-run', action='store_true', help='模拟运行')
args = p.parse_args(sys.argv[2:])
cmd_storyboard(args)
elif cmd == 'route':
p = argparse.ArgumentParser()
p.add_argument('storyboard', help='分镜JSON路径')
p.add_argument('-o', '--output', help='输出路径')
p.add_argument('--dry-run', action='store_true', help='模拟运行')
p.add_argument('--summary', action='store_true', help='只统计')
args = p.parse_args(sys.argv[2:])
cmd_route(args)
elif cmd == 'render':
p = argparse.ArgumentParser()
p.add_argument('storyboard', help='分镜JSON路径')
p.add_argument('-o', '--output-dir', help='输出目录')
p.add_argument('--style', default='', help='全局风格')
p.add_argument('--generate-sh', action='store_true', help='生成shell脚本')
p.add_argument('--workflow', help='基础工作流模板')
args = p.parse_args(sys.argv[2:])
cmd_render(args)
elif cmd == 'upscale':
p = argparse.ArgumentParser()
p.add_argument('input_dir', help='图片文件夹')
args = p.parse_args(sys.argv[2:])
cmd_upscale(args)
elif cmd == 'compose':
p = argparse.ArgumentParser()
p.add_argument('folder', help='视频片段文件夹')
p.add_argument('-o', '--output', default='output.mp4', help='输出文件')
p.add_argument('--title', help='片头文字')
p.add_argument('--credits', help='片尾文字')
p.add_argument('--subtitle', help='字幕文件')
p.add_argument('--crossfade', type=int, default=0, help='交叉淡入淡出')
args = p.parse_args(sys.argv[2:])
cmd_compose(args)
elif cmd == 'assets':
p = argparse.ArgumentParser()
p.add_argument('project_dir', help='项目目录')
p.add_argument('--comfy-url', help='ComfyUI API地址')
p.add_argument('--list', action='store_true', help='只列出')
p.add_argument('--dry-run', action='store_true', help='模拟运行')
args = p.parse_args(sys.argv[2:])
cmd_assets(args)
elif cmd == 'go':
p = argparse.ArgumentParser()
p.add_argument('script', help='剧本文件路径')
p.add_argument('-e', '--episode', type=int, default=1, help='集号')
p.add_argument('--pro', action='store_true', help='使用Pro模型')
p.add_argument('--style', default='', help='全局风格')
args = p.parse_args(sys.argv[2:])
cmd_go(args)
if __name__ == '__main__':
main()