跳到主内容
快讯直播
AI智模界
教程

AI 生成漫剧:从剧本到成片的完整流程

这条流水线能做出什么

走完下面的步骤,你会得到一条 3~5 分钟的漫剧短片:画面是 AI 生成的漫画风格分镜,每个镜头有缓慢推拉或平移,人物有配音,屏幕下方有同步字幕,导出为 1920×1080、25 帧的 MP4,可以直接上传到视频平台。

整套流程不依赖某一家工具。文本、图像、语音、视频这四类能力,你用哪家服务都行,只要按下面的接口约定把中间产物落到本地文件夹即可。

先约定工程目录,后面所有命令都基于它:

```text

manju/

├── script/

│ ├── story.md # 故事梗概和台词

│ └── storyboard.yaml # 结构化分镜表

├── assets/

│ ├── characters/ # 角色参考图

│ └── shots/ # 分镜静帧 s01.png s02.png ...

├── audio/

│ ├── lines/ # 单句配音 s01.m4a ...

│ └── bgm.mp3

├── subs/

│ └── final.srt

├── build/ # 中间产物

└── out/

└── final.mp4

```

前置条件清单

  • 一台能跑脚本的电脑,系统不限;显存不是硬门槛,出图交给云端服务也可以。
  • Python 3.9 以上,会用 pip install 装包。
  • ffmpeg 与 ffprobe,命令行能直接调用(ffmpeg -version 有输出即可)。
  • 四类账号各一个:文本生成、图像生成、语音合成、图生视频。接口地址和参数以各家官方文档当前版本为准。
  • 一个剪辑软件作为兜底,用来手动微调字幕位置和补几个转场。
  • 一份背景音乐,注意使用授权范围。

时间上,一条 3 分钟、约 30 个镜头的短片,写剧本和分镜占掉将近一半时间,出图和配音是等待为主,剪辑合成占两成。

第 1 步:把故事写成"可拍摄"的剧本

漫剧的剧本不需要文学性,需要的是每句话都能对应一个画面。用三列表格写:镜号、画面描述、台词。

先在 script/story.md 里写清楚三件事:

1. 一句话主线:谁,想做什么,被什么挡住,结果如何。

2. 角色表:每个角色的固定外貌特征,写到"换个人画也能认出是同一个"的程度。

3. 台词表:每句台词控制在 25 字以内,一句话一个镜头。

不要写"她心里很乱"这类无法画出来的描述,改成"她把手机扣在桌上,屏幕还亮着"。这是整条流水线里最省时间的一条经验。

第 2 步:把剧本转成分镜表

分镜表是后续所有自动化的数据源,用 YAML 写,人读得懂,脚本也好读。

```yaml

script/storyboard.yaml

style: "日系赛璐璐上色,干净线条,柔和自然光,画面中不出现任何文字"

characters:

  • id: lin

name: 林小满

look: "17 岁女生,齐肩黑发,左侧别一枚蓝色发卡,米白色针织衫"

  • id: chen

name: 陈经理

look: "40 岁男性,短寸头,深灰西装,细框眼镜"

shots:

  • id: s01

scene: "傍晚的地铁站台,暖橙色顶灯,背景人群虚化"

cast: [lin]

action: "林小满低头看手机,眉头微皱,中景,略微俯视"

line: "又加班到这个时候。"

seconds: 4

  • id: s02

scene: "空荡的办公室,只有一盏工位灯亮着"

cast: [lin, chen]

action: "陈经理把一叠文件放到桌上,林小满站在对面,过肩视角"

line: "这份明天早上要。"

seconds: 5

```

字段含义:scene 是环境,cast 引用角色 id,action 是动作和机位,line 是台词,seconds 是预计时长。style 是全局风格串,会拼到每个镜头里,保证画风统一。

第 3 步:锁定角色一致性

跨镜头人物变形是这类项目里返工最多的环节。做法是把角色外貌写成一个固定字符串,每次出图都原样拼进去,再配合一张角色参考图。

```python

build/prompt.py

import yaml

with open("script/storyboard.yaml", encoding="utf-8") as f:

sb = yaml.safe_load(f)

chars = {c["id"]: c for c in sb["characters"]}

def build_prompt(shot):

parts = [shot["scene"]]

for cid in shot.get("cast", []):

c = chars[cid]

parts.append(f'{c["name"]},{c["look"]}')

parts.append(shot["action"])

parts.append(sb["style"])

return ",".join(parts)

if __name__ == "__main__":

for s in sb["shots"]:

print(s["id"], "->", build_prompt(s))

```

跑一下 python build/prompt.py,检查每个提示词里角色描述是否完整。

更稳的做法是给主要角色单独训练一个小模型(LoRA),或者用参考图条件控制。是否需要、怎么用,以你所用工具的官方文档为准。固定随机种子只能提高复现率,不能保证跨模型一致。

第 4 步:批量出分镜图

写一个循环脚本:读分镜表,逐个镜头调用图像生成接口,把结果存成 assets/shots/s01.png 这样的命名。

```python

build/gen_shots.py

import time, pathlib, yaml

from prompt import build_prompt # 上一步的文件

sb = yaml.safe_load(open("script/storyboard.yaml", encoding="utf-8"))

outdir = pathlib.Path("assets/shots")

outdir.mkdir(parents=True, exist_ok=True)

def generate(prompt, ref_image=None, size="1920x1080"):

"""替换成你所用图像服务的调用。返回图片二进制内容。"""

raise NotImplementedError

for shot in sb["shots"]:

target = outdir / f'{shot["id"]}.png'

if target.exists():

continue # 断点续跑,别重复烧额度

prompt = build_prompt(shot)

try:

data = generate(prompt)

target.write_bytes(data)

print("ok", shot["id"])

except Exception as e:

print("fail", shot["id"], e)

time.sleep(2) # 给接口留点间隔

```

三个要点:

  • 断点续跑。脚本要能跳过已经存在的文件,出到一半中断时不用从头来。
  • 比例统一。所有镜头都用 16:9、1920×1080,避免后期画面忽大忽小。
  • 失败重试。报错重试两三次,仍失败就记录下来,换成邻居镜头的构图重出。

出完图先人工过一遍,把人物崩坏、多手指、构图雷同的镜头挑出来重出。这一步偷懒,后面配音和剪辑会加倍还回来。

第 5 步:配音与时间轴

逐句配音,一句一个文件,文件名和镜号一致:audio/lines/s01.m4a。合成参数里语速放在正常偏慢的位置,句尾留一点静音,听起来才不像播报。

拿到音频后用 ffprobe 量出真实时长,不要用分镜表里预估的 seconds,因为人声实际长度常常差出一两秒。

```python

build/timeline.py

import subprocess, json, pathlib, yaml

def dur(p):

out = subprocess.run(

["ffprobe", "-v", "error", "-show_entries", "format=duration",

"-of", "json", str(p)],

capture_output=True, text=True, check=True).stdout

return float(json.loads(out)["format"]["duration"])

def ts(t):

h, r = divmod(t, 3600)

m, s = divmod(r, 60)

return f"{int(h):02d}:{int(m):02d}:{s:06.3f}".replace(".", ",")

sb = yaml.safe_load(open("script/storyboard.yaml", encoding="utf-8"))

lead_in, gap = 0.6, 0.8 # 开头留白、句间留白,单位秒

lines, t = [], lead_in

for shot in sb["shots"]:

p = pathlib.Path("audio/lines") / f'{shot["id"]}.m4a'

if not p.exists():

print("缺少配音:", p)

continue

d = dur(p)

lines.append((t, t + d, shot["line"]))

t += d + gap

def srt_time(x):

h, r = divmod(x, 3600)

m, s = divmod(r, 60)

ms = int((s - int(s)) * 1000)

return f"{int(h):02d}:{int(m):02d}:{int(s):02d},{ms:03d}"

with open("subs/final.srt", "w", encoding="utf-8") as f:

for i, (a, b, text) in enumerate(lines, 1):

f.write(f"{i}\n{srt_time(a)} --> {srt_time(b)}\n{text}\n\n")

print("总时长约", round(t, 1), "秒")

```

这份 SRT 既是字幕,也是剪辑时间轴:每个镜头的画面长度就等于对应那句配音的时长加留白。

第 6 步:让静图动起来

两条路。图生视频服务直接产出几秒的短片段,效果自然,成本和时间更高;本地用 ffmpeg 做推拉平移,速度很快,适合对白密集的镜头。

推拉平移的命令(5 秒、25 帧):

```bash

ffmpeg -y -loop 1 -i assets/shots/s01.png \

-vf "scale=2400:-2,zoompan=z='min(zoom+0.0008,1.15)':d=125:s=1920x1080:fps=25,format=yuv420p" \

-t 5 -c:v libx264 -pix_fmt yuv420p build/s01.mp4

```

先放大到 2400 宽再裁到 1920×1080,是为了让平移过程中不会露出黑边。d=125 是帧数,改成 每秒帧数 × 秒数 即可。左右平移把 zoompan 换成 x 方向的表达式即可实现。

人物说台词的镜头,用极缓慢的推进;环境镜头用平移。全片不要出现方向、速度都一样的一串镜头,否则看着像幻灯片。

第 7 步:合成成片

先把所有镜头片段按顺序拼起来:

```bash

cd build

printf "file '%s'\n" s*.mp4 > list.txt

ffmpeg -y -f concat -safe 0 -i list.txt -c copy rough.mp4

```

再做音轨:把每句配音按时间轴摆进去。简单做法是生成对应长度的静音,和配音交替拼接:

```bash

ffmpeg -y -f lavfi -i anullsrc=r=44100:cl=mono -t 0.6 -c:a aac build/silence.m4a

```

按"静音 → s01 → 静音 → s02 → …"的顺序写进音频列表,用 concat 拼接得到 voice.m4a,然后和背景音乐混音:

```bash

ffmpeg -y -i build/voice.m4a -i audio/bgm.mp3 \

-filter_complex "[1:a]volume=0.15,aloop=loop=-1:size=2e9[bg];[0:a][bg]amix=inputs=2:duration=first:dropout_transition=0[a]" \

-map "[a]" -c:a aac build/mix.m4a

```

背景音乐音量压到人声的两三成,漫剧的对白密度高,音乐抢了就没法听。

接着把字幕烧进画面,并合上音轨:

```bash

ffmpeg -y -i build/rough.mp4 -i build/mix.m4a \

-vf "subtitles=subs/final.srt:force_style='FontSize=22,Outline=2,MarginV=40'" \

-map 0:v -map 1:a -c:v libx264 -crf 20 -preset medium \

-c:a aac -b:a 192k -shortest out/final.mp4

```

如果字幕显示成方块,是字体缺失,在 subtitles 过滤器里指定中文字体文件和字体名即可。

第 8 步:验收清单

导出后完整看两遍。第一遍关掉声音看画面,检查镜头切换和字幕;第二遍只听声音,检查有没有爆音、断句、突然变响。重点核对:

  • 人物在所有镜头里是否长得像同一个人。
  • 字幕有没有超出画框、有没有和人物脸部重叠。
  • 音画是否对得上,尤其是有明显动作的镜头。
  • 总时长和平台要求是否匹配,超出就删镜头而不是加速。

常见坑与排错

人物每个镜头都不一样。 多半是角色描述串在不同镜头里被改写了。把描述放进 YAML 只写一次,脚本统一拼接,不要手打。

配音和画面对不上。 用预估时长排时间轴导致的。坚持用 ffprobe 里实测的时长,SRT 和画面长度都从同一份时间轴生成。

画面抖动或边缘发黑。 推拉幅度过大,或原图没有留出裁剪余量。先把图放大到目标宽度的 1.2 倍以上再动,幅度控制在 10% 以内。

音轨拼接处有咔哒声。 采样率不一致。把所有音频统一转成 44100Hz、单声道或立体声同一种,再拼。

接口报错、任务排队很久。 图生视频类任务通常是异步的,提交后拿到任务号再轮询查结果,别用同步请求硬等。并发数、轮询间隔、配额规则以各家官方文档当前版本为准。

每段重跑都要重烧钱。 全部中间产物落盘,脚本做存在性判断。改一句台词只重跑那一个镜头。

画面里出现乱码文字。 生成时在提示词里明确"画面中不出现任何文字",把字留给字幕层。

下一步建议

跑通第一条之后,按这个顺序加深:

1. 把分镜表加上 transition 字段,脚本里自动套用不同转场,减少手工剪辑。

2. 积累角色参考图和提示词模板,形成自己的素材库,新项目直接复用。

3. 把整条链路包成一个命令,比如 python run.py --episode 03,从分镜表一路跑到成片。

4. 多集连载时,把角色表、风格串抽成公共配置文件,各集只写 shots

做到第 3 步,一集 3 分钟的漫剧,从写好分镜表到出片可以压缩到半天以内。

AI 生成本文由 AI 基于公开信息自动生成,仅供参考。