8G 显存本地部署 AI 漫剧流水线:分镜提示词版本管理、批量归档与角色提示词隔离实战教程

本文介绍面向8G显存本地部署的AI漫剧生产提示词管理系统,支持角色提示词隔离存储、分镜提示词版本快照、自动拼接(角色+分镜+运镜模板)、批量有效性校验、JSON轻量存储及ComfyUI流水线无缝对接。系统纯CPU运行,不占显存,提供完整Python脚本,解决提示词混乱、版本丢失、角色画风漂移等工程痛点,保障红果短剧系列画风一致性。

摘要

在红果短剧 AI 漫剧量产过程中,提示词混乱、版本丢失、不同角色提示词互相污染是非常普遍的工程痛点。同一角色多批次渲染时,提示词微调之后没有归档记录,下次复现同款画风需要反复试错;多角色、多剧本混跑时提示词参数串扰,直接造成角色画风漂移、人设崩坏。本文面向 8G 显存本地部署的 AI 漫剧生产链路,搭建一套轻量化本地提示词管理系统,支持分镜提示词入库、版本快照、角色提示词独立隔离、批量导出导入、提示词有效性筛选,全部数据本地 JSON 存储,无需数据库,附带完整 Python 管理脚本、批量校验工具,和 ComfyUI 批量渲染流水线无缝对接,稳定支撑红果短剧长期系列漫剧的画风一致性生产。

具体教程资源请看这一篇文章:8G 显卡本地部署 AI 漫剧:红果短剧成片自动预审、画面合规自检流水线实战教程-CSDN博客

1、系统设计思路与存储规范

整套系统采用纯 JSON 文件轻量化存储,不需要 MySQL、SQLite 等重型数据库,直接放在流水线工作目录下,方便备份、复制、迁移。目录规划如下:

prompt_lib/
├── character/            # 角色独立提示词库(隔离区)
│   ├── 女主_林晚.json
│   ├── 男主_陈默.json
│   └── 配角_反派.json
├── shot_template/        # 分镜模板库(运镜、光影、画风模板)
│   ├── 慢推镜_室内柔和光.json
│   └── 快切_夜景冷调.json
├── script_project/       # 短剧项目归档,一个项目一个文件
│   └── 红果短剧_雨夜追踪_ep01.json
└── snapshot/             # 版本快照,每次渲染前自动备份
    └── snapshot_20261022_1530.json

隔离核心规则:角色基础人设、固定五官描述、画风基准放在角色独立 json,分镜动态台词、场景、运镜放在项目分镜文件,渲染时程序自动拼接【角色固定提示词 + 当前分镜动态提示词 + 模板光影运镜词】,负面提示词统一绑定角色,避免混用。

8G 显存适配说明:这套提示词管理模块纯 CPU 运算,不占用 CUDA 显存,和视频推理任务完全互不抢占显存资源,可以常驻后台配合渲染脚本同步运行。

2、数据结构定义脚本

定义角色、分镜、模板的数据模型,统一格式,避免不同批次提示词结构混乱,ComfyUI 调度脚本可以稳定读取。

import json
from pathlib import Path
from datetime import datetime

BASE_PATH = Path("./prompt_lib")
CHAR_PATH = BASE_PATH / "character"
PROJECT_PATH = BASE_PATH / "script_project"
SNAPSHOT_PATH = BASE_PATH / "snapshot"
TEMPLATE_PATH = BASE_PATH / "shot_template"

# 初始化目录
def init_lib_dir():
    for p in [BASE_PATH, CHAR_PATH, PROJECT_PATH, SNAPSHOT_PATH, TEMPLATE_PATH]:
        p.mkdir(parents=True, exist_ok=True)
    print("提示词库目录初始化完成")

# 角色数据模板
def get_empty_char_template(char_name, char_id):
    return {
        "char_id": char_id,
        "char_name": char_name,
        "base_positive": "1girl, delicate facial features, fixed face, consistent face, same character, comic style",
        "base_negative": "face distortion, extra fingers, deformed limbs, style change, flash, watermark, text",
        "style_weight": 0.78,
        "ip_adapter_weight": 0.75,
        "ref_feature_path": f"./char_ref/{char_id}_feature.pt",
        "tag_list": ["少女", "黑长发", "浅杏色外套"]
    }

# 分镜项目模板
def get_empty_project(proj_name, drama_id):
    return {
        "proj_name": proj_name,
        "drama_id": drama_id,
        "create_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
        "shot_list": []
    }

# 单条分镜模板
def get_empty_shot(shot_id, char_id, scene_text, template_name):
    return {
        "shot_id": shot_id,
        "char_id": char_id,
        "scene_text": scene_text,
        "dynamic_positive": "",
        "template_name": template_name,
        "duration": 6,
        "note": ""
    }

if __name__ == "__main__":
    init_lib_dir()

3、角色提示词增删改查、隔离存储脚本

每个角色单独一个 json 文件,修改角色人设不会影响其他角色,实现提示词隔离。

def save_character(char_data):
    char_file = CHAR_PATH / f"{char_data['char_name']}_{char_data['char_id']}.json"
    with open(char_file, "w", encoding="utf-8") as f:
        json.dump(char_data, f, ensure_ascii=False, indent=2)
    print(f"角色【{char_data['char_name']}】保存成功")

def load_character(char_id):
    for f in CHAR_PATH.glob("*.json"):
        data = json.loads(f.read_text(encoding="utf-8"))
        if data.get("char_id") == char_id:
            return data
    print(f"未找到 char_id={char_id} 的角色")
    return None

def list_all_char():
    res = []
    for f in CHAR_PATH.glob("*.json"):
        d = json.loads(f.read_text(encoding="utf-8"))
        res.append({"char_id":d["char_id"], "char_name":d["char_name"]})
    return res

if __name__ == "__main__":
    # 新建一个角色示例
    new_char = get_empty_char_template("林晚", "c001")
    new_char["base_positive"] = "少女林晚,黑色长直发,清澈眼睛,淡杏色风衣,漫剧画风,面部稳定"
    new_char["base_negative"] = "五官崩坏,手指畸形,画风突变,换脸,闪烁,水印,杂乱文字"
    save_character(new_char)
    print(list_all_char())

4、分镜项目管理:新建项目、批量导入剧本、自动拼接提示词

核心函数:自动合并角色固定提示词 + 分镜动态提示词 + 运镜模板词,输出最终送入 ComfyUI 的正负提示词,渲染脚本直接读取。

def save_project(proj_data):
    proj_file = PROJECT_PATH / f"{proj_data['proj_name']}.json"
    with open(proj_file, "w", encoding="utf-8") as f:
        json.dump(proj_data, f, ensure_ascii=False, indent=2)
    return proj_file

def load_project(proj_name):
    proj_file = PROJECT_PATH / f"{proj_name}.json"
    return json.loads(proj_file.read_text(encoding="utf-8"))

def merge_prompt(char_data, shot_data, template_data):
    """拼接最终正负提示词"""
    final_positive = ",".join([
        char_data["base_positive"],
        template_data["pos"],
        shot_data["dynamic_positive"],
        shot_data["scene_text"]
    ])
    final_negative = ",".join([
        char_data["base_negative"],
        template_data["neg"]
    ])
    return final_positive, final_negative

def batch_import_script_to_project(proj_name, char_id, script_lines, template_name):
    proj = get_empty_project(proj_name, f"drama_{proj_name}")
    char_info = load_character(char_id)
    shot_id = 1
    for line in script_lines:
        shot = get_empty_shot(shot_id, char_id, line, template_name)
        proj["shot_list"].append(shot)
        shot_id += 1
    save_project(proj)
    print(f"剧本导入项目 {proj_name},共{len(script_lines)}个分镜")
    return proj

if __name__ == "__main__":
    # 剧本批量导入示例
    script_lines = [
        "林晚推开老旧铁门,警惕看向走廊深处",
        "林晚低声:是谁一直在跟着我?",
        "镜头缓慢推进,林晚握紧口袋里面的纸条"
    ]
    batch_import_script_to_project("雨夜追踪_ep01", "c001", script_lines, "慢推镜_室内柔和光")

5、渲染前自动版本快照备份脚本

每次启动批量渲染之前,自动给当前项目、角色提示词打快照,一旦渲染效果翻车,可以一键回退到上一版提示词,解决调参之后找不到之前可用提示词版本的问题。

def create_snapshot(proj_name):
    time_str = datetime.now().strftime("%Y%m%d_%H%M%S")
    snap_data = {
        "snap_time": time_str,
        "proj_name": proj_name,
        "project_data": load_project(proj_name)
    }
    snap_file = SNAPSHOT_PATH / f"snapshot_{time_str}_{proj_name}.json"
    with open(snap_file, "w", encoding="utf-8") as f:
        json.dump(snap_data, f, ensure_ascii=False, indent=2)
    print(f"快照已生成:{snap_file.name}")
    return snap_file

def restore_snapshot(snap_file_path):
    snap_data = json.loads(Path(snap_file_path).read_text(encoding="utf-8"))
    save_project(snap_data["project_data"])
    print(f"项目已回退至快照:{snap_data['snap_time']}")

if __name__ == "__main__":
    create_snapshot("雨夜追踪_ep01")

6、提示词有效性批量校验脚本(过滤无效、冲突标签)

批量扫描项目所有分镜提示词,检查重复标签、矛盾标签、过长提示词,提前过滤容易造成画面崩坏的冲突描述,减少无效渲染浪费显卡算力。

def prompt_check(pos_text, neg_text):
    conflict_tags = ["bright,dark", "young,old", "male,female"]
    warn_list = []
    pos_tags = [t.strip() for t in pos_text.split(",") if t.strip()]
    neg_tags = [t.strip() for t in neg_text.split(",") if t.strip()]
    # 重复标签检测
    if len(pos_tags) != len(set(pos_tags)):
        warn_list.append("正向提示词存在重复标签")
    if len(pos_text) > 1200:
        warn_list.append("正向提示词过长,容易触发模型忽略尾部标签")
    # 简单冲突检测
    for c in conflict_tags:
        a,b = c.split(",")
        if a in pos_tags and b in pos_tags:
            warn_list.append(f"存在冲突标签 {a} / {b}")
    return warn_list

def batch_check_project_prompt(proj_name, template_lib):
    proj = load_project(proj_name)
    warn_total = 0
    for shot in proj["shot_list"]:
        char = load_character(shot["char_id"])
        tpl = template_lib[shot["template_name"]]
        pos, neg = merge_prompt(char, shot, tpl)
        warns = prompt_check(pos, neg)
        if warns:
            print(f"分镜{shot['shot_id']}告警:{warns}")
            warn_total += 1
    print(f"项目校验完成,总告警数:{warn_total}")
    return warn_total

7、和原有 ComfyUI 批量渲染流水线对接改造

修改之前的渲染调度脚本,不再手动写死提示词,直接从提示词库读取合并后的正负提示词,做到渲染脚本和提示词解耦。

import requests

COMFYUI_URL = "http://127.0.0.1:8188"

def queue_workflow(prompt_json):
    resp = requests.post(f"{COMFYUI_URL}/prompt", json={"prompt": prompt_json})
    return resp.json()

def render_project_by_lib(proj_name, template_lib):
    proj = load_project(proj_name)
    # 渲染前自动快照
    create_snapshot(proj_name)
    for shot in proj["shot_list"]:
        char = load_character(shot["char_id"])
        tpl = template_lib[shot["template_name"]]
        final_pos, final_neg = merge_prompt(char, shot, tpl)
        print(f"渲染镜头{shot['shot_id']},提示词加载完成")
        # 读取工作流模板,替换正负提示词节点
        workflow = json.loads(Path("./workflow.json").read_text(encoding="utf-8"))
        workflow["6"]["inputs"]["text"] = final_pos
        workflow["7"]["inputs"]["text"] = final_neg
        queue_workflow(workflow)
        # 显存回收
        import gc, torch
        gc.collect()
        torch.cuda.empty_cache()

if __name__ == "__main__":
    # 预加载运镜模板库
    tpl_lib = {
        "慢推镜_室内柔和光": {
            "pos":"slow push shot, soft indoor lighting, shallow depth of field, comic panel",
            "neg":"shaky camera, flash, harsh light"
        }
    }
    render_project_by_lib("雨夜追踪_ep01", tpl_lib)

8、批量导出、导入提示词库指令(备份迁移)

项目完成之后,可以把整套角色库、分镜项目打包导出,换一台电脑本地部署的时候直接导入,画风可以完全复现,适合多机分布式跑漫剧。

def export_all_lib(save_file="./prompt_lib_backup.json"):
    out = {
        "char_list": [json.loads(f.read_text(encoding="utf-8")) for f in CHAR_PATH.glob("*.json")],
        "proj_list": [json.loads(f.read_text(encoding="utf-8")) for f in PROJECT_PATH.glob("*.json")]
    }
    with open(save_file, "w", encoding="utf-8") as f:
        json.dump(out, f, ensure_ascii=False, indent=2)
    print("提示词库备份导出完成")

def import_lib(backup_file):
    data = json.loads(Path(backup_file).read_text(encoding="utf-8"))
    for c in data["char_list"]:
        save_character(c)
    for p in data["proj_list"]:
        save_project(p)
    print("备份包导入完成")

9、落地踩坑与调优说明

  1. 角色提示词隔离的边界:固定长相、人设、画风放在角色文件;场景、台词、镜头运动只放在分镜,不要把动态描述写入角色库,否则所有镜头都会强制叠加冲突场景词。
  2. 提示词长度控制:单条正向提示词建议控制在 1200 字符以内,超过之后视频模型会截断尾部标签,画风不可控,上面的校验脚本会提前拦截。
  3. 快照策略:只在正式批量渲染前自动快照,调试预览渲染不生成快照,避免快照文件夹无限膨胀占用磁盘。
  4. 多角色同框方案:分镜里面绑定多个 char_id,程序依次读取多个角色的基础提示词拼接,每个角色仍然保持独立的 IPAdapter 特征文件,互不干扰。
  5. 模板复用:把高频使用的夜景、日光、特写、横移镜头做成模板,后续新项目直接选用,不用反复手写光影运镜提示词,降低重复工作量。

10、配套扩展方向

这套提示词管理系统可以继续扩展标签分类、画风评分记录,记录每一组提示词渲染之后的成片评分,做提示词质量筛选;还可以对接本地大模型,基于角色人设自动扩写分镜提示词,进一步降低人工写词成本。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值