☰
AI短剧生成平台全流程拆解:从剧本生成到视频合成部署
2026/10/1 23:45:05 网站建设 项目流程

简介:AI短剧生成平台源码包,围绕一句创意描述自动构筑完整短剧生产链路。输入一句台词或故事雏形,系统即可完成剧本改写、角色与场景提取、分镜拆解、配音合成及视频导出,显著降低AI视频创作门槛。资源共九十四份文件,以TypeScript源码为骨架,辅以Vue前端组件、Markdown说明文档、JSON配置、Docker部署清单等,压缩包仅六百三十四KB,体量小巧但模块完整。核心模块包括后端服务、前端管理界面、语音分配器、脚本改写器、分镜拆分器,并支持AI生成角色形象与场景背景、TTS配音、基于文生图与图生视频的镜头生成,以及FFmpeg合成剪辑。已有三百零五人学习,适合短视频创作者、独立开发者与AI应用学习者参考,可据此快速搭建自己的短剧生成工作流,也是学习多模态生成与自动化视频制作的实用范例。

1. 一句话到成片:这个AI短剧生成平台到底做了什么

做AI短视频内容的朋友应该都有同感:脚本、配音、画面、剪辑,每一样都是时间黑洞。我自己之前手动做过一条2分钟的AI漫剧,光调角色一致性就花了三个晚上,最后出来的视频自己都没眼看。所以当我看到这个AI短剧生成平台,输入一句话就能在本地把剧本、角色、场景、分镜、配音、视频全链路跑通时,第一个反应是:这玩意儿到底靠不靠谱。

实际拆完源码和部署流程后,我的结论是:它把AI短视频生成平台的完整流水线做成了可复现的工程化项目,不是Demo,是能跑通全流程的源码包。对于做短剧矩阵的内容团队、想接AI视频生成的开发者、以及正在选型AI视频工具的运营来说,这份资源值回票价。后面我会从剧本抽取、角色生成、分镜拼装、配音合成到部署踩坑,一条线拆给你看。

2. 剧本与要素抽取:一句话变成结构化台本

2.1 提示词模板与结构化输出:先定JSON schema再写Prompt

整个平台的第一步是把用户输入的一句话扩展成完整剧本。这里最关键的工程决策是:不要用自然语言对话式的输出,而是要限制LLM返回严格结构化JSON。我第一次跑的时候,提示词里没约束输出格式,结果模型给了我一篇带小标题的散文,分镜模块根本没法解析,后面全崩了。

先看核心代码,这决定了剧本生成的质量上限:

import json from openai import OpenAI client = OpenAI(api_key=API_KEY, base_url=API_BASE) def generate_script(idea: str) -> dict: prompt = f""" 你是短剧编剧。根据用户创意,产出一个3分钟短剧的完整台本。 必须输出JSON,不要输出任何额外文字。JSON结构如下: {{ "title": "短剧标题", "logline": "一句话梗概", "characters": [ {{"name": "角色名", "gender": "男/女", "age": 25, "appearance": "外形描述", "personality": "性格"}} ], "scenes": [ {{"scene_id": 1, "location": "场景地点", "time": "日/夜", "lines": [ {{"character": "角色名", "text": "台词", "emotion": "情绪提示", "action": "动作描述"}} ]}} ] }} 用户创意:{idea} """ resp = client.chat.completions.create( model="gpt-4o", messages=[{"role": "user", "content": prompt}], temperature=0.4, max_tokens=4096, response_format={"type": "json_object"} ) return json.loads(resp.choices[0].message.content)

这段代码的逻辑很直白:先把剧本的Schema用JSON示例完整地写在提示词里,再让模型填充。response_format强制输出JSON,temperature控制在0.4,我一般不建议超过0.6,短剧剧本要的是稳定性,不是发散性。

max_tokens=4096是经验值,3分钟的短剧大概20到30句台词,加上角色和场景描述,4000个token基本够用。如果你输入的故事线特别复杂,可以放宽到8192;但要注意,很多国内大模型API的默认最大输出是4096,调大了有可能报错。

2.2 角色与场景抽取:实体去重和全局一致性

LLM输出的原始JSON不能直接用,有两个脏数据问题在工程上必须处理。第一个是角色名不一致,同一个角色在剧本里可能被写上"外卖员""小陈""陈师傅"三种叫法;第二个是场景描述冗余,一个场景有12句台词,每句台词里都重复一遍"下午三点的老旧小区门口"。

下面是角色合并的常规做法:

def merge_characters(script: dict) -> dict: char_map = {} for scene in script["scenes"]: for line in scene["lines"]: role = line["character"] # 用别名表做归一化,规则比模型更可控 alias = normalize_role(role) if alias not in char_map: char_map[alias] = { "name": alias, "lines_count": 0, "scenes": [] } char_map[alias]["lines_count"] += 1 if scene["scene_id"] not in char_map[alias]["scenes"]: char_map[alias]["scenes"].append(scene["scene_id"]) script["characters"] = [ {**char_map[k], "scenes": sorted(char_map[k]["scenes"])} for k in char_map ] return script

normalize_role内部就是一张别名映射表,人工维护成本很低。角色出现次数和所在场景列表这两个字段很重要,后面生成角色形象和分镜时都要用。特别是角色出现在哪几个场景,直接决定了要给这个角色生成多少张不同机位的图。

场景抽取我习惯按"地点+时间段"来合并场景,比如"小区门口-白天"和"小区门口-傍晚"是两个不同镜头语境的场景。合并结果存入场景列表,每个场景分配一个全局唯一的scene_id,后面配音、分镜、合成全部依赖这个ID做关联,我在这个ID上的教训是用字符串拼接,结果排序时"scene_10"跑到了"scene_2"前面,全片画面顺序乱了。

3. 角色形象与分镜生成:从文本到画面的关键取舍

3.1 角色一致性:固定seed和参考图是底线

模板里**关键词"AI生成角色形象"**对应的就是这个模块。做过AI漫剧的人都知道,最痛苦的不是画得丑,而是同一个角色上一帧长这样,下一帧换了张脸。平台的方案是:提取角色描述中的"外形描述",交给文生图模型,同时用固定seed和参考图来约束人物一致性。

核心逻辑看代码:

import io import base64 import requests def generate_character_image(role: dict, reference_image_path: str = None): prompt = f"""{role['appearance']},全体照,高清,细节丰富, 电影级打光,半身构图,人物居中""" negative_prompt = "变形,手指畸形,多余肢体,模糊,低分辨率,水印" payload = { "prompt": prompt, "negative_prompt": negative_prompt, "steps": 30, "cfg_scale": 7.0, "width": 512, "height": 768, "seed": role["seed"], # 固定seed,角色每次生成都是同一张脸 "batch_size": 4 } if reference_image_path: with open(reference_image_path, "rb") as f: img_b64 = base64.b64encode(f.read()).decode() payload["init_image"] = img_b64 payload["strength"] = 0.4 # strength越低,越贴近原图 resp = requests.post(SD_API_URL + "/sdapi/v1/txt2img", json=payload) return resp.json()["images"]

关键在于每个角色生成时把seed固定下来,同时把上一次生成的图片作为init_image传进去,strength设在0.3到0.5之间。strength太低画面跟前一张几乎一样,没有姿态变化;太高又容易跑脸。这个参数我没少折腾,最终确定0.4在画风和动作自由度之间最平衡。

还有一个容易被忽略的细节:角色描述里要带上"半身构图",因为短剧的对话镜头绝大多数是近景和半身,全身图放到16:9的画面里人脸占比太小,观众根本看不出是哪个人物。512x768的尺寸也别乱改,这是给视频拼接留的余量,后面合成时还要统一裁剪。

3.2 分镜生成:台词时长决定镜头节奏

分镜模块是整个平台里最接近"导演"的地方。处理逻辑是:把每一句台词估算成秒数,再按秒数决定镜头的总长度。常见的做法是:中文台词按每字0.3秒估算,加上0.6秒的情绪停顿,这就是这个分镜的基础时长。

这一段代码很实用:

def build_storyboard(scene: dict, char_images: dict) -> list: shots = [] for idx, line in enumerate(scene["lines"]): text = line["text"] # 中文文本按字符估算,含标点约0.3秒/字 duration = round(len(text) * 0.3 + 0.6, 1) if idx == len(scene["lines"]) - 1: duration += 0.8 # 场景末句多加停留时间 shot = { "shot_id": f"{scene['scene_id']}-{idx}", "character": line["character"], "text": line["text"], "emotion": line["emotion"], "duration": duration, "image_path": char_images[line["character"]] } shots.append(shot) return shots

duration的计算别看简单,它是后面音画同步的基准。TTS生成的音频实际时长和估算值会有偏差,因此真正合成时要以渲染出的音频文件的真实时长为准,这里只是分镜的第一步估算。

emotion字段我建议直接用"开心""愤怒""惊讶"这种极简词,不要用"内心涌现出一阵复杂的情绪"这类描述。文生图和TTS对这种复杂情绪词的理解是黑匣子,翻车概率极大。短剧镜头语言本来就要直给,情绪标签越具体,下游模块越不容易跑偏。

4. 配音合成与视频成片:TTS参数与音画对齐

4.1 TTS配音:语速、音调、停顿三个参数决定像不像真人

配音环节经常被当成"生成个音频就行",实际上参数调不好,出来的就是AI朗读腔。平台里TTS模块的做法是:按角色性别和性格选不同的音色,语速控制在0.95到1.1之间,音调一般直接复制平台默认,只有角色是小孩或者老人时才动。

实际调用代码片段:

import edge_tts import asyncio async def generate_voice_line(shot: dict, role_name: str, voice: str, output_path: str): text = shot["text"] rate = "+10%" if shot["emotion"] == "开心" else "-5%" if shot["emotion"] == "难过" else "+0%" communicate = edge_tts.Communicate(text, voice, rate=rate) await communicate.save(output_path)

edge_tts优势是免费且音色列表齐全,缺点是网络不好时容易超时重试,所以项目源码里一般会搭配一个失败重试装饰器。rate参数里"+10%"这个值我是踩过坑的,刚开始用"+50%"希望让整段显得活泼,结果语速快到像开倍速,配合画面时观众根本来不及看清字幕。

选音色的经验是:男角色选zh-CN-YunjianNeural这种低沉音色,女角色选zh-CN-XiaoxiaoNeural,情绪激烈的场景换成zh-CN-YunxiNeural。不要给所有角色配同一个音色,AI短视频里最出戏的就是两个人对话听起来是同一个人在自言自语。多角色短剧,配音文件命名一定要带shot_id,合成模块是按这个ID去匹配的。

4.2 视频合成:moviepy里必须处理的三个对齐问题

视频合成用moviepy就够了,不需要上Premiere。这里最核心的是把图片、台词音频、字幕三者按时间轴对齐。我一开始直接set_duration(shot_duration),结果画面和声音对不上,原因就是TTS的实际音频长度和估算时长不一致。正确的做法是先解析音频文件拿到真实时长,再决定画面时长。

from moviepy.editor import ImageClip, AudioFileClip, CompositeVideoClip from mutagen.mp3 import MP3 def assemble_scene(scene_shots: list, output_path: str): clips = [] cursor = 0 for shot in scene_shots: audio_path = shot["audio_path"] duration = MP3(audio_path).info.length # 以真实音频时长为准 clip = ( ImageClip(shot["image_path"]) .set_duration(duration) .set_audio(AudioFileClip(audio_path)) .set_start(cursor) ) clips.append(clip) cursor += duration scene_video = CompositeVideoClip(clips, size=(1024, 576)) scene_video.write_videofile(output_path, fps=24)

size=(1024, 576)是短发竖屏素材横屏展示的折中方案。你要做抖音那种竖屏短剧,尺寸要改成(576, 1024),但注意生成的角色图是512x768,直接拉伸会变形,得在合成时先resize再居中裁剪。

字幕模块没写在上面的代码里,原因是很多版本会把字幕和画面绑定在一层,调试起来来回返工。我一般推荐单独生成一个SRT文件,让剪辑阶段或者平台内置播放器来加载。SRT生成规则就是按一模一样的cursor游标逻辑,每句台词字幕独立成段,时间格式是HH:MM:SS,mmm --> HH:MM:SS,mmm。这个文件虽然简单,但字幕时间戳和音频对不上是短视频平台最常见的违和感来源。

5. 部署与排查:从源码包到跑通全流程的五个深坑

这份资源带了安装部署流程,但源码包依赖的组件比较多,LLM接口、图片服务、TTS服务、Python环境,每个环节都可能出问题。以下五条是我实际跑过程中遇到过的,按"现象-原因-解决"记录。

5.1 现象:torch.cuda.is_available()返回False

部署完跑图片生成模块,提示CUDA不可用,但nvidia-smi明明能看到显卡。

原因:PyTorch的CUDA版本和显卡驱动不匹配。常见的情况是源码包里锁定的torch版本默认是CPU版,或者CUDA编译版本与驱动不兼容。

解决:先确认显卡驱动支持的CUDA版本,再安装对应版本的PyTorch。我的环境是CUDA 11.8,执行的是pip install torch==2.1.0+cu118 torchvision==0.16.0+cu118 -f https://download.pytorch.org/whl/torch_stable.html,装完以后在命令行里跑一次python -c "import torch; print(torch.cuda.is_available())",输出True再继续。

5.2 现象:调用LLM接口时requests超时

剧本生成模块卡在API调用上,等了十几秒直接抛超时异常。

原因:默认timeout值设置偏短,加上国内直连国外模型服务的网络延迟不稳定,尤其是长提示词场景下模型推理时间本身就长。

解决:把timeout从默认的10秒改成60秒,同时在OpenAI客户端初始化时设置max_retries=3。如果你们用的是国内大模型服务商,就把base_url换成服务商官方地址,不要沿用默认地址,这个地址改不对,前面的剧本生成百分之百跑不通。

5.3 现象:合成视频里的字幕全部是方框乱码

视频能合成,但字幕显示成"???"或者方框。

原因:moviepy的TextClip依赖ImageMagick和字体文件,Linux环境下默认没有中文字体,英文和数字能正常渲染,中文直接从字体库中缺失。

解决:安装fonts-wqy-microhei(文泉驿微米黑),然后设置环境变量IMAGEMAGICK_BINARY指向全局bin路径。我踩完这个坑后直接把字体文件msyh.ttc复制到了项目根目录,在代码里显式font="./msyh.ttc"声明,彻底摆脱系统字体依赖。

5.4 现象:图片生成到一半显存溢出OOM

一次性批量生成角色图时,进程直接被系统杀掉。

原因:batch_size设置过大,显存不够用。前面我代码里写了batch_size=4,在消费级显卡上4张一步出图很容易爆显存。

解决:显存小于12GB的机器把batch_size改到1或2,然后关掉不需要的显卡缓存。更稳妥的做法是循环单张生成,把每次出图结果直接落盘,不要让多张图驻留在显存中。

5.5 现象:长剧本的LLM输出总是被截断

台词到一半突然断掉,JSON解析失败,报"Expecting value"错误。

原因:max_tokens不够用。3分钟短剧的完整台词加角色描述,实际token消耗比预估高,尤其当用户输入的是长场景故事,生成的内容经常超过4096的上限。

解决:把max_tokens往上调到8192,同时在做剧本解析时加一层JSON截断修复逻辑,常见的做法是定位最后一个完整的}括号,丢弃后续不完整片段。这个兜底逻辑必须有,你永远不知道模型哪天会抽风在JSON后面补一句"以上就是本短剧的完整剧本"。

6. 进阶用法:提示词模板库和成片验收清单

整套流程跑通以后,我建议你把精力花在角色一致性验收和提示词模板固化上。这两个事情不做好,平台跑出来的每条视频质量波动很大。

角色一致性验证:成片出来后,逐帧抽查角色面部。我的做法是每个角色挑3个不同场景的截图做对比,如果两张图放一起能明显看出不是同一个人,就去调那个角色的reference_image_path和strength。角色是第一优先级,场景和光线都可以往后放。

提示词模板管理也很关键。平台源码里剧本生成的提示词是写死的,我习惯把它改成从外部JSON读取,把"你是短剧编剧"这种定位描述、JSON Schema、额外的风格要求分字段配置。这样换题材时只改配置不动代码,比如做甜宠剧时加上"台词要细腻暧昧",做悬疑剧时加"每场戏结尾留钩子",平台的核心能力没变,但产出内容的针对性完全不同。

验收项检查方式通过标准
角色一致性多帧截图对比同一角色至少3个场景可辨认为同一人
音画同步逐句比对台词时长与字幕字幕出现和朗读结束误差不超过0.5秒
转场完整性连续播放全片无明显黑屏、跳帧、静音段
字幕准确率对照剧本检查错别字不超过总字数的1%

这套验收清单帮我省下大量返工时间。以前成片要全片看完才发现角色在第40秒就换脸了,现在每出完一条视频就按表过一遍,5分钟能确认是否可用。从那以后,我每次跑AI视频生成流水线,无论多急,都强制走一遍这个验收流程,动作已经形成肌肉记忆了。这个平台的核心价值就在于把AI短剧生成全流程的源码和部署方案打包好,剩下的变数全靠你在角色的seed和提示词模板上花心思。希望这些记录能帮你在绕弯时少走几步。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询