AI 漫剧短剧的生产瓶颈,从来不是“能不能生成一帧画面”,而是角色能不能跨镜头保持一致、分镜能不能按剧本稳定产出、效果能不能量化评估。这三件事合起来,就是“训练”要解决的问题。本文从训练数据准备、角色一致性、分镜生成、效果评估四个环节拆解工程实践。
角色一致性训练的核心是同一角色的多角度、多表情、多姿态样本。数据集质量直接决定 LoRA 效果。
推荐目录结构:
dataset/
character_xiaohui/
01_front.png
02_side.png
03_back.png
04_smile.png
05_angry.png
06_cry.png
...
metadata.jsonmetadata.json 记录每张图的标注信息:
import json
from pathlib import Path
def build_metadata(char_dir: Path, trigger: str,
base_tags: list[str]) -> Path:
items = []
for img in sorted(char_dir.glob("*.png")):
items.append({
"file_name": img.name,
"text": f"{trigger}, " + ", ".join(base_tags),
})
meta = {"trigger_word": trigger, "items": items}
path = char_dir / "metadata.json"
path.write_text(json.dumps(meta, ensure_ascii=False, indent=2),
encoding="utf-8")
return path
build_metadata(
Path("dataset/character_xiaohui"),
trigger="xiaohui_char",
base_tags=["flat cartoon", "thick outline", "low saturation",
"sticker style", "clean edges"],
)触发词 xiaohui_char 是这个角色在提示词中的唯一标识。训练后,只要提示词里带上它,模型就会向该角色收敛。
数据合规要求:所有训练图必须是原创或已获授权,不得使用他人作品、明星肖像、品牌元素。数据集来源要留档。
以 Stable Diffusion LoRA 为例,核心参数如下:
from dataclasses import dataclass
@dataclass
class LoRAConfig:
base_model: str = "runwayml/stable-diffusion-v1-5"
resolution: int = 512
train_batch_size: int = 1
gradient_accumulation: int = 4
learning_rate: float = 1e-4
lr_scheduler: str = "cosine"
max_train_steps: int = 1500
rank: int = 32
network_alpha: int = 16
mixed_precision: str = "fp16"
save_every: int = 250
seed: int = 42
@property
def effective_batch(self) -> int:
return self.train_batch_size * self.gradient_accumulation几个经验值:
训练完成后,推理时加载 LoRA:
def build_prompt(trigger: str, action: str, style: str) -> str:
return (f"{trigger}, {style}, action: {action}, "
"clean edges, no text, no watermark")
def negative_prompt() -> str:
return ("text, watermark, logo, real person, complex background, "
"deformed, low quality, extra fingers")漫剧短剧的分镜必须是结构化的,否则无法编排。用 Pydantic 约束模型输出。
import os, json
from openai import OpenAI
from pydantic import BaseModel, Field
client = OpenAI(
api_key=os.getenv("OPENAI_API_KEY"),
base_url=os.getenv("OPENAI_BASE_URL"),
)
class Shot(BaseModel):
idx: int
scene: str = Field(max_length=120)
camera: str = Field(max_length=60)
action: str = Field(max_length=120)
dialogue: str = Field(default="", max_length=80)
duration: float = Field(ge=1, le=8)
class Episode(BaseModel):
title: str
characters: list[str]
shots: list[Shot] = Field(min_length=4, max_length=12)
SYSTEM = """你是漫剧分镜师。根据主题生成 6 个镜头,每镜 3-5 秒。
只输出 JSON:{title, characters, shots:[{idx,scene,camera,action,dialogue,duration}]}。
禁止侵权、违法、暴力、色情内容。角色必须来自给定角色表。"""
def gen_episode(topic: str, character_names: list[str]) -> Episode:
resp = client.chat.completions.create(
model=os.getenv("OPENAI_MODEL", "gpt-4o-mini"),
messages=[
{"role": "system", "content": SYSTEM},
{"role": "user",
"content": f"主题:{topic}\n角色表:{', '.join(character_names)}"},
],
response_format={"type": "json_object"},
temperature=0.8,
)
return Episode.model_validate_json(resp.choices[0].message.content)每个镜头的 scene 和 action 会拼接角色触发词,生成最终提示词,保证跨镜头角色一致。
训练完不能只看“感觉像不像”。需要可量化指标。
import numpy as np
from PIL import Image
from pathlib import Path
def image_embedding(path: Path, size: int = 64) -> np.ndarray:
img = Image.open(path).convert("RGB").resize((size, size))
arr = np.asarray(img, dtype=np.float32) / 255.0
return arr.flatten()
def cosine(a: np.ndarray, b: np.ndarray) -> float:
denom = np.linalg.norm(a) * np.linalg.norm(b)
return float(a @ b / denom) if denom else 0.0
def consistency_score(ref: Path, samples: list[Path]) -> dict:
ref_vec = image_embedding(ref)
scores = [cosine(ref_vec, image_embedding(s)) for s in samples]
return {
"mean": round(float(np.mean(scores)), 4),
"min": round(float(np.min(scores)), 4),
"pass": float(np.min(scores)) >= 0.75,
}这个指标只是粗筛,不能替代人工判断。它的作用是快速发现角色漂移严重的批次,减少人工工作量。
分镜质量还需要检查:
def validate_episode(ep: Episode, target_duration: tuple[float, float],
banned: set[str]) -> list[str]:
issues = []
total = sum(s.duration for s in ep.shots)
if not (target_duration[0] <= total <= target_duration[1]):
issues.append(f"总时长 {total}s 不在目标区间")
for s in ep.shots:
if any(w in s.dialogue for w in banned):
issues.append(f"镜头 {s.idx} 对白含禁用词")
if any(w in s.action for w in banned):
issues.append(f"镜头 {s.idx} 动作含禁用词")
return issues维度 | 做法 | 缺失后果 |
|---|---|---|
数据授权 | 训练图来源留档 | 侵权纠纷 |
版本管理 | LoRA、数据集、配置全部版本化 | 无法复现 |
一致性 | 触发词 + LoRA + 固定种子 | 角色漂移 |
评估 | 自动指标 + 人工终审 | 质量失控 |
留痕 | trace、模型、提示词指纹 | 问题无法追溯 |
合规 | 审核 + AI 标注 + 授权确认 | 平台处罚 |
训练数据不混用不同来源,多角色训练时每个角色独立 LoRA,避免触发词互相污染。日志中的用户输入和个人信息必须脱敏。
AI 漫剧短剧的训练工程,核心是四件事:
代码可以简单,但数据授权、版本管理、评估门禁和合规审查不能省。先把单角色的 LoRA 跑通,再做多角色、多集、批量生产。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。