尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

AI短剧自动化2.5:用Python与FFmpeg构建短视频批量生产流水线

AI短剧自动化2.5:用Python与FFmpeg构建短视频批量生产流水线 各位读者朋友今天想分享一套可以落地的 AI 短剧自动化方案。短剧创作并不是“写一个故事然后一键出片”那么简单中间至少包含剧本结构、场景拆分、配音、画面素材、剪辑合成和字幕压制等环节。本文梳理的“2.5”版本不是某个商业产品的正式版本号而是对我们自己搭起来的一套自动化流水线成熟度的一种约定1.0 只能做固定模板拼接2.0 开始引入大模型和 AI 生图2.5 则重点解决结构化分镜、素材缓存、单镜重试和粗剪输出能力。无论你是短视频运营、个人创作者还是想探索 AIGC 工程化的开发者都可以按这条链路快速跑通第一版。本文会先讲清楚整体架构再给出详细的 Python 与 FFmpeg 实现思路包含一个本地 Mock 模式下的可运行 Demo。即使你暂时没有可用的模型服务也能先了解全流程接入真实模型服务时只需要替换 Provider 层的接口即可。1. 背景与核心概念1.1 为什么短剧需要自动化短剧的本质是“高密度、强情绪、快节奏”的内容。传统短剧制作链路很长从选题、剧本、分镜脚本、拍摄、演员、服化道到后期配音和剪辑每一步都需要大量人力。即使一条内容只有 1 到 2 分钟拍摄和制作团队也可能要忙一到两天。AI 短剧自动化希望解决的是“创意验证效率”问题先用大模型快速生成故事、分集和台词再用 TTS 合成配音用文生图或者文生视频工具生成画面最后通过 FFmpeg 做拼接和字幕压制形成一条“半自动内容生产线”。需要注意的是自动化不意味着完全无人。以目前的 AIGC 能力来说自动生成的结果仍然需要人工在关键节点做判断例如故事是否踩中用户情绪、台词是否通顺、画面是否适合展示、配音是否有明显机械感。因此更推荐把自动化流程设计成“每一阶段都有中间结果保存人到某个节点抽检仍然可以一键续跑”。1.2 AI 短剧自动化的核心问题很多刚开始接触的人会以为只要把故事丢给大模型再让 AI 视频工具生成一段视频就完事了。但在工程上还要解决下面几个核心问题文本生成结果不稳定。大模型可能写出剧情不连贯的短剧脚本。场景拆分困难。短剧不等于一段长视频它需要分镜、分场景、按节奏推进。音频与画面很难自动对齐。如果每段旁白过长或过短最终拼接的视频观感会非常差。素材格式不统一。有的模型生成竖屏图片有的生成横屏视频如果不做归一化处理拼接时容易黑边、拉伸或裁切。生成成本高。大模型、TTS、文生图服务都是按调用量计费如果流程设计不好一次失败可能要重新消耗全部资源。所以我们需要一套“可控的中间格式”。最好的办法是不把每个 AI 服务强耦合到主流程中而是先让大模型输出一个结构化分镜 JSON再让每个模块消费 JSON并把生成结果保存到固定目录。这样即使某一环节失败也能从对应步骤重试而不是从头再来。1.3 本文的读者与学习收获这篇文章主要面向三类读者有一定 Python 基础想搭建 AIGC 视频生成工具的开发者。做短剧运营、内容出海或短视频批量生产的从业者。对 AI 自动化流程感兴趣希望了解“从创意到成片”工程化落地的技术同学。读完本文后你可以掌握以下内容理解 AI 短剧自动化的完整模块划分。学会设计统一的分镜 JSON 数据结构。编写一套基于大模型的剧本和场景生成器。接上 TTS 服务与文生图服务并了解抽象 Provider 的好处。使用 FFmpeg 将单镜头素材合成为成片。了解质量审计、缓存、版权合规等工程化细节。2. 整体架构与流程设计2.1 从故事到成片的总链路首先我把整条流程拆成下面这样story.txt | v 1. 剧本生成 - script.md | v 2. 分镜拆解 - scenes.json | v 3. 配音生成 - audio/scene_001.wav | v 4. 画面素材生成 - images/scene_001.png | v 5. 单镜合成 - segments/scene_001.mp4 | v 6. 拼接压制 - draft/final_draft.mp4在这个链路里scenes.json是整个流程的“中枢”。前面的大模型负责把故事变成结构化分镜后面的 TTS、AI 绘图、FFmpeg 合成模块都只依赖scenes.json和对应的素材文件。这种设计有一个明显好处模块之间完全解耦。比如今天你想换一家文生视频服务只需要改动“画面素材生成”模块今天你想把配音引擎换掉也只需要改动“配音生成”模块不影响其他流程。2.2 模块职责划分为了更好地管理代码我将系统拆成下面几个模块故事输入模块接收用户提供的短篇故事、灵感或标题并做简单清洗。剧本生成模块调用大模型将故事扩展成短剧的分场脚本。分镜解析模块从脚本文本中提取场景标题、画面描述、旁白台词等输出Scene对象列表。TTS 配音模块根据每句旁白或台词生成音频文件。画面素材模块根据画面描述调用文生图或文生视频服务。FFmpeg 合成模块将图片、音频、字幕合成为统一编码的视频片段。最终成片模块将多个片段拼接成一条完整竖屏短视频。在代码层次上我会把“会变化的部分”全部封装成接口。真正跑通时你接入什么模型服务、什么图片服务都由 Provider 层决定。文章后面给出的具体 Provider 示例里会有一个“Mock Provider”。它的作用是在没有网络模型服务的情况下也能先验证流水线跑通。2.3 为什么中间结果必须落盘很多初学自动化流程的人容易忽略“中间结果落盘”。但在短剧生产场景里中间结果落盘几乎是必须的。第一大模型生成结果不稳定。如果 Prompt 写的不好可能偶尔输出残缺 JSON。如果把脚本结果只放在内存里一旦解析失败就要重新消耗一次大模型调用。更合理的做法是每次成功生成后都把原始内容保存到文件里让后续解析模块从文件读取。第二调试成本高。短剧生成中不同素材之间的对齐问题很常见。如果每个模块都输出到文件那么你可以直接用播放器打开音频看看画面是否匹配非常方便。第三方便人工审核。有些团队希望在自动生成后插入“人工审片环节”。如果中间结果不是文件人工审核就很难接入流程。3. 环境准备与项目结构3.1 基础环境约定本文示例以常见开发环境为主具体版本需要根据你的项目实际情况调整。一般来说需要准备Python 3.9 或更高版本。FFmpeg 命令行工具并确保ffmpeg、ffprobe已加入系统 PATH。能正常访问 Python 官方源或镜像源以安装依赖。可选一个大模型服务的 API Key一个 TTS 服务的 API Key。可选一个文生图或文生视频服务的 API Key。如果你暂时没有 API Key也请不要担心。示例会提供 Mock Provider本地跑通时不需要真实调用外部模型。3.2 Python 依赖创建虚拟环境后建议先安装下面两个依赖pip install requests Pillowrequests用于调用各类 HTTP APIPillow用于本地生成占位图。如果你希望代码看起来更清爽也可以再安装python-dotenv来读取.env文件本文示例为了减少依赖直接使用环境变量和 JSON 配置。3.3 项目目录结构我建议按下面这种方式组织代码ai_short_drama/ ├── config.json ├── main.py ├── pipeline.py ├── ffmpeg_utils.py ├── modules/ │ ├── __init__.py │ ├── models.py │ ├── script_generator.py │ ├── scene_parser.py │ ├── tts_provider.py │ ├── image_provider.py │ └── mock_provider.py └── outputs/如果只是学习阶段你也可以把全部代码写到一个main.py里。但从工程角度来说模块独立会让后续扩展更加轻松。文章后面展示的代码为了清晰会按“文件职责”拆开介绍核心流程可以合到pipeline.py中运行。4. 完整实战案例组装一条短剧自动生产线4.1 定义统一的分镜数据结构我们需要先定义一个统一的数据结构。所有模块之间都通过这个结构传递信息。# 文件路径modules/models.py from dataclasses import dataclass, field, asdict from typing import Optional import json dataclass class Scene: scene_id: str title: str narration: str visual_prompt: str audio_path: Optional[str] None image_path: Optional[str] None video_path: Optional[str] None duration: float 0.0 def to_dict(self): return asdict(self) def to_json(self): return json.dumps(self.to_dict(), ensure_asciiFalse, indent2)这里有几个字段需要解释scene_id场景编号用于素材命名和排序。title场景名称比如“深夜食堂内景”“巷口下雨”。narration该场景对应的旁白、独白或对话内容。visual_prompt画面提示词后面交给文生图或者视频生成模型使用。audio_pathTTS 生成后的音频文件路径。image_path图片文件路径。duration音频时长用于后续剪辑对齐。使用 dataclass 的好处是代码简洁转 JSON 也很方便。真实项目里你可以加入更多字段比如镜头运动方式、景别、字幕文本等。4.2 大模型剧本生成模块剧本生成模块负责把用户提供的故事梗概扩展成短剧剧情。这里有一个很大的坑如果直接让模型自由发挥它可能写出“长篇小说式”的段落不适合短剧。因此Prompt 必须明确限制输出格式。下面是一个通用的大模型调用骨架。不同服务提供商的接口不完全相同这里以 OpenAI 兼容的/chat/completions接口为例你需要替换成自己实际使用的服务和地址。# 文件路径modules/script_generator.py import os import requests def call_llm(system_prompt: str, user_prompt: str, model: str gpt-4o-mini, temperature: float 0.7) - str: 通用 LLM 调用函数这里以 OpenAI 兼容接口为例。 base_url 和 api_key 从环境变量读取。 base_url os.getenv(LLM_BASE_URL, https://api.openai.com/v1) api_key os.getenv(LLM_API_KEY, ) resp requests.post( f{base_url}/chat/completions, headers{ Authorization: fBearer {api_key}, Content-Type: application/json, }, json{ model: model, messages: [ {role: system, content: system_prompt}, {role: user, content: user_prompt}, ], temperature: temperature, }, timeout120, ) resp.raise_for_status() data resp.json() return data[choices][0][message][content]实际使用时你可能会遇到响应超时、模型不支持某些参数、返回内容包含多余 Markdown 等问题。这里先不展开后续常见问题会补充处理方案。接下来编写generate_short_drama_script。为了降低解析门槛我的 Prompt 会要求模型输出 Markdown 场景结构而不是复杂的嵌套 JSON。因为模型在长文本生成中直接输出严格 JSON 容易在中途断掉Markdown 更容易稳定生成解析也更简单。SYSTEM_PROMPT 你是一名短剧编剧。你擅长把用户提供的故事创意改写为适合竖屏短视频播放的短剧脚本。 要求 1. 分 3 到 5 个场景。 2. 每个场景包含标题、画面描述、旁白或台词。 3. 旁白台词要口语化有情绪长度控制在 40-80 字。 4. 画面描述要具体方便后续文生图模型参考。 5. 不要出现敏感、违规、侵权内容。 输出格式为 Markdown ## 场景1标题 画面场景画面描述 旁白具体旁白台词 def generate_short_drama_script(story_outline: str) - str: user_content f故事创意{story_outline}\n请输出短剧脚本。 return call_llm(SYSTEM_PROMPT, user_content)你可能会问为什么不在这一步直接输出SceneJSON因为在真实场景里后端 TTS 服务、图片服务的字段规则经常变化我们宁可保留“高可读的脚本文本”再通过专门的解析层转换成Scene对象。这样即使大模型偶尔漏字段我们还能人工修改 Markdown 后重新解析不需要重新调用模型。4.3 分镜解析模块分镜解析模块读取脚本文本把它变成Scene列表。解析逻辑要尽量宽容兼容模型可能出现的多余标题和空格。# 文件路径modules/scene_parser.py import re from modules.models import Scene def parse_script_to_scenes(script_text: str) - list[Scene]: scenes [] # 以“## ”开始的行作为场景分隔 blocks re.split(r\n##\s, script_text) for block in blocks: if 画面 not in block or 旁白 not in block: continue lines block.strip().splitlines() title lines[0].strip() if lines else 未命名场景 visual_prompt narration for line in lines[1:]: if line.startswith(画面): visual_prompt re.sub(r^画面[:]\s*, , line.strip()) elif line.startswith(旁白): narration re.sub(r^旁白[:]\s*, , line.strip()) if visual_prompt and narration: scene_id fscene_{len(scenes) 1:03d} scenes.append( Scene( scene_idscene_id, titletitle, narrationnarration, visual_promptvisual_prompt, ) ) return scenes这段解析代码不依赖任何第三方库就是一个简单的字符串处理。解析完成后建议马上把scenes.json保存到输出目录。后续所有人了解当前流程状态直接看这个 JSON 就可以了。import json def save_scenes(scenes, output_path): with open(output_path, w, encodingutf-8) as f: json.dump([s.to_dict() for s in scenes], f, ensure_asciiFalse, indent2)4.4 TTS 配音模块配音是短剧质量的关键。很多短视频平台用户对“机器朗读感”特别敏感所以 TTS 服务的选择和参数调整很重要。下面定义 TTS Provider 的接口# 文件路径modules/tts_provider.py import subprocess def get_audio_duration(audio_path: str) - float: 通过 ffprobe 获取音频时长。 cmd [ ffprobe, -v, error, -show_entries, formatduration, -of, defaultnoprint_wrappers1:nokey1, audio_path, ] result subprocess.run(cmd, capture_outputTrue, textTrue) if result.returncode ! 0: raise RuntimeError(f获取音频时长失败{result.stderr}) return float(result.stdout.strip()) def tts_to_file(text: str, output_path: str) - float: 调用 TTS 服务将文本合成为语音文件。 这里仅作为接口骨架请根据具体服务商调整实现。 raise NotImplementedError(请接入你的 TTS 服务)如果你有了真实 TTS 接口可以实现tts_to_file在函数中调用服务下载音频文件并返回时长。如果没有真实服务可以先把下面的 Mock 实现放到 Provider 中。为了避免最终流程因为缺少真实 TTS 而中断我在mock_provider里使用 FFmpeg 生成一段测试音频。这段音频不是真人声音只是为了验证后续的剪辑流程。# 文件路径modules/mock_provider.py import subprocess import random def mock_tts_to_file(text: str, output_path: str) - float: 本地 Mock TTS 用 FFmpeg 生成一段不同频率的单音频模拟配音片段。 # 旁白越长模拟音频越长 duration min(max(len(text) / 12.0, 1.2), 6.0) # 不同场景使用不同频率便于后期区分 freq random.randint(300, 700) cmd [ ffmpeg, -y, -f, lavfi, -i, fsinefrequency{freq}:duration{duration}, -q:a, 9, output_path, ] subprocess.run(cmd, checkTrue, capture_outputTrue) return get_audio_duration(output_path)这里解释一下这段 Mock 的作用当你把某一句旁白输入进来它会生成一段带固定频率的音频频率随机时长和文本长度成正比。这样跑通流程时你能清楚地看到每个场景都得到了一个独立音轨也能测试后面的图片与音频合成逻辑。4.5 画面素材生成模块画面素材有多种方案文生图根据visual_prompt生成一张竖屏图片然后通过 FFmpeg 与音频合成静态视频。文生视频直接生成 3 到 5 秒的动态视频片段。图生视频先根据角色描述生成角色图再让角色动起来。在 2.5 阶段我更推荐先做好“图片 音频 轻微运镜”的模式。这种方法成本低、可控性强处理速度也比直接生成视频快很多。后续算力充足时可以把图片模块替换成文生视频模块。接口定义如下# 文件路径modules/image_provider.py from PIL import Image, ImageDraw def real_generate_image(prompt: str, output_path: str): 调用文生图服务生成图片。 实际接入时你需要将 prompt 发送给图像生成服务 然后下载返回图片到 output_path。 raise NotImplementedError(请接入你的图像生成服务) def mock_generate_image(prompt: str, output_path: str): 本地 Mock生成一张 1080x1920 的随机纯色图片。 便于在没有绘图 API 的情况下先跑通流程。 import hashlib seed int(hashlib.md5(prompt.encode(utf-8)).hexdigest(), 16) r (seed 16) 0xFF g (seed 8) 0xFF b seed 0xFF img Image.new(RGB, (1080, 1920), (r, g, b)) # 简单加一点文字区域区分实际不参与生成逻辑 draw ImageDraw.Draw(img) draw.rectangle([0, 1600, 1080, 1920], fill(0, 0, 0)) draw.text((50, 1650), prompt[:12], fill(255, 255, 255)) img.save(output_path)这里的 Mock 实现根据prompt的 MD5 值生成一个稳定颜色保证同一个画面描述每次生成的占位图颜色一致。真实项目中请替换成文生图或者文生视频服务。4.6 使用 FFmpeg 合成单镜片段当图片和音轨都准备好后就可以合成一个个场景片段。这个环节最常见的坑是音频和视频编码不兼容导致在浏览器或手机上无法播放。因此FFmpeg 命令必须显式指定-pix_fmt yuv420p。# 文件路径ffmpeg_utils.py import subprocess def compose_segment(image_path: str, audio_path: str, output_video_path: str, width: int 1080, height: int 1920): 将一张静态图和一个音频文件合成竖屏 MP4 视频片段。 cmd [ ffmpeg, -y, -loop, 1, -i, image_path, -i, audio_path, -c:v, libx264, -tune, stillimage, -c:a, aac, -b:a, 192k, -pix_fmt, yuv420p, -shortest, -vf, fscale{width}:{height}:force_original_aspect_ratiodecrease,pad{width}:{height}:(ow-iw)/2:(oh-ih)/2, output_video_path, ] subprocess.run(cmd, checkTrue, capture_outputTrue)命令参数的含义如下-loop 1将静态图片无限循环为视频流。-c:v libx264使用 H.264 视频编码。-tune stillimage针对静态图片场景做编码优化。-c:a aac音频编码为 AAC。-pix_fmt yuv420p采用 YUV 4:2:0 采样兼容网页和手机播放。-shortest视频流和音频流中较短的结束视频就结束。-vf保证图片按竖屏比例居中裁剪或留边不会变形。如果你以后使用真实 AI 视频生成服务得到的是动态视频片段那么就不需要-loop 1而是直接把视频片段和音频合流。4.7 最终合成成片当所有单镜片段生成后批量拼接是一个很实用的能力。FFmpeg 的 concat demuxer 可以无损拼接多个编码参数一致的 MP4 文件。需要注意如果每个片段的编码参数不一致例如分辨率不同则不能直接使用-c copy需要重新编码。下面是一个稳妥示例先把所有片段文件写入一个列表再统一转码拼接def build_final_video(segment_paths: list[str], output_path: str): list_file output_path .txt with open(list_file, w, encodingutf-8) as f: for seg in segment_paths: f.write(ffile {seg}\n) cmd [ ffmpeg, -y, -f, concat, -safe, 0, -i, list_file, -c, copy, output_path, ] subprocess.run(cmd, checkTrue, capture_outputTrue)如果发现拼接后的视频没有声音或者画面花屏多半是不同片段的编码参数不一致。解决办法是把-c copy改成重新编码ffmpeg -f concat -safe 0 -i list.txt -c:v libx264 -c:a aac -pix_fmt yuv420p final.mp44.8 一键调度主流程下面这段代码把上面的模块串起来。它包含两个 Provider真实 Provider 和 Mock Provider。运行前如果配置里没有 API Key程序自动使用 Mock Provider这样你本地也能看到完整流程如何运转。# 文件路径pipeline.py import os import json import shutil from pathlib import Path from modules.models import Scene from modules.scene_parser import parse_script_to_scenes from ffmpeg_utils import compose_segment, build_final_video from modules.mock_provider import mock_tts_to_file, mock_generate_image class ShortDramaPipeline: def __init__(self, output_root: str ./outputs): self.output_root Path(output_root) self.scenes_dir self.output_root / scenes self.audio_dir self.output_root / audio self.images_dir self.output_root / images self.segments_dir self.output_root / segments self.draft_dir self.output_root / draft for d in [self.scenes_dir, self.audio_dir, self.images_dir, self.segments_dir, self.draft_dir]: d.mkdir(parentsTrue, exist_okTrue) def run(self, story_outline: str): print(1. 生成剧本) # 真实项目中此处应调用大模型生成脚本 script_text self._mock_script(story_outline) (self.scenes_dir / script.md).write_text(script_text, encodingutf-8) print(2. 解析分镜) scenes parse_script_to_scenes(script_text) if not scenes: raise RuntimeError(没有解析到有效场景) print(f3. 生成 {len(scenes)} 个场景素材) for scene in scenes: print(f - {scene.scene_id}: {scene.title}) # 3.1 配音 audio_path str(self.audio_dir / f{scene.scene_id}.wav) scene.duration mock_tts_to_file(scene.narration, audio_path) scene.audio_path audio_path # 3.2 画面 image_path str(self.images_dir / f{scene.scene_id}.png) mock_generate_image(scene.visual_prompt, image_path) scene.image_path image_path # 3.3 合成分镜片段 segment_path str(self.segments_dir / f{scene.scene_id}.mp4) compose_segment(image_path, audio_path, segment_path) scene.video_path segment_path print(4. 保存分镜 JSON) scenes_data [s.to_dict() for s in scenes] with open(self.scenes_dir / scenes.json, w, encodingutf-8) as f: json.dump(scenes_data, f, ensure_asciiFalse, indent2) print(5. 拼接成片) final_path str(self.draft_dir / final_draft.mp4) build_final_video([s.video_path for s in scenes if s.video_path], final_path) print(f完成成片位于{final_path}) return final_path def _mock_script(self, story_outline: str) - str: 在没有模型 Key 时先生成一个固定的测试剧本。 return f## 场景1深夜食堂 画面昏暗的小饭馆里一名厨师正在炒饭灶火明亮 旁白凌晨一点城市安静下来这家小食堂才刚刚开始热闹。 ## 场景2一碗蛋炒饭 画面厨师把鸡蛋打入米饭中快速翻炒锅气升腾 旁白来这里的人多半不是为了填饱肚子而是为了找一点熟悉的记忆。 ## 场景3陌生客人的秘密 画面年轻客人低头吃着蛋炒饭眼泪落进碗里 旁白他说这碗饭让他想起十年前妈妈的味道。 ## 场景4天亮以后 画面厨房灯光熄灭厨师站在门口目送客人远去 旁白天亮以后故事继续这家深夜食堂又迎来新的过客。 然后写一个main.py支持从命令行读取故事创意。# 文件路径main.py import argparse from pipeline import ShortDramaPipeline def main(): parser argparse.ArgumentParser(descriptionAI 短剧自动化 2.5) parser.add_argument(--story, default一个深夜食堂的暖心故事) parser.add_argument(--output, default./outputs) args parser.parse_args() pipeline ShortDramaPipeline(output_rootargs.output) result pipeline.run(args.story) print(result) if __name__ __main__: main()这个主流程虽然比较初级但它已经完整覆盖了“故事到成片”的链路。建议你先把这段代码跑通再逐步替换成真实的大模型和 TTS 服务。5. 运行验证与结果说明5.1 本地 Mock 快速体验安装依赖后在项目根目录执行python main.py --story 一个落魄厨师在深夜为陌生人做了一碗蛋炒饭如果一切正常你会在outputs/目录下看到类似这样的文件outputs/ ├── audio/ │ ├── scene_001.wav │ ├── scene_002.wav │ ├── scene_003.wav │ └── scene_004.wav ├── images/ │ ├── scene_001.png │ ├── scene_002.png │ ├── scene_003.png │ └── scene_004.png ├── segments/ │ ├── scene_001.mp4 │ ├── scene_002.mp4 │ ├── scene_003.mp4 │ └── scene_004.mp4 ├── draft/ │ └── final_draft.mp4 └── scenes/ ├── scenes.json └── script.md你可以用播放器打开final_draft.mp4。Mock 模式下画面是纯色或简单黑色条幅声音是单音频率主要用来验证流程是否通顺。真正上线时这些 Mock 素材会被真实图片、AI 配音和背景音乐替代。5.2 接入真实模型服务的顺序当你准备接入真实服务时不要一次性把所有模块都替换。我建议按下面的顺序来先替换剧本生成模块让大模型生成更有吸引力的剧情。再替换scene_parser.py适配模型输出格式。然后替换 TTS Provider选择一个自然度更高的中文音色。最后替换图片 Provider接入文生图或文生视频服务。运行一次完整流程检查音频与画面是否仍然能对齐。每替换一个环节都要重新查看scenes.json和中间产物避免错误被传递到最终视频。6. 常见报错与排查思路下面梳理了 AI 短剧自动化落地中的高频问题遇到报错时可以按表格对照排查。问题现象常见原因解决思路大模型返回内容不是想要的 MarkdownPrompt 不够明确或者模型版本不稳定在 Prompt 中加入输出示例并在后处理中增加兜底解析调用大模型接口超时网络问题或模型服务负载过高增加超时重试降低单次输出长度必要时分段生成脚本解析不到旁白模型输出格式用了“台词”“对白”等词在 Prompt 中严格要求“旁白”开头并放开解析规则TTS 合成后没有声音音频下载失败或 ffmpeg 命令错误先用命令单独测试 TTS 输出文件确认文件可播放视频生成画面比例不对图片不是竖屏比例统一使用scale和pad滤镜处理成 1080x1920FFmpeg 拼接时报错concat 列表里的文件编码不一致改用重新编码方式或者统一所有 segment 的编码参数最终视频人脸或字幕侵权使用了未授权的 AI 生成人物或素材审核素材来源避免使用真实人物肖像和未授权素材台词和画面情绪不匹配文本生成阶段没有约束剧情节奏优化 Prompt让每个场景的情绪变化更明显必要时人工调整旁白如果你遇到“Mock 模式下音频生成失败”需要优先检查 FFmpeg 是否成功安装并执行ffmpeg -version如果命令不存在请先到 FFmpeg 官网下载对应系统版本或者使用系统包管理器安装并确保安装目录已加入 PATH。7. 工程化落地与最佳实践7.1 Prompt 工程是质量上限短剧自动化的质量上限很大程度来自 Prompt。不要只写“帮我生成一个短剧”而是要说明短剧的受众、情绪节奏、篇幅限制和输出格式。建议在剧本生成 Prompt 中加入这些要素目标平台与观看场景。例如“竖屏短视频前 2 秒必须抓住用户注意力”。故事主题与情绪走向。例如“温暖治愈、反转结尾”。每个场景的篇幅限制。台词风格。例如“口语化、有代入感不要书面语”。输出格式示例。最好在 Prompt 中直接给出一段示例 Markdown。我还建议你把不同用途的 Prompt 单独保存成模板文件例如prompts/script_generator.md、prompts/scene_image.md。这样当模型效果下降时你可以快速对比不同 Prompt 版本而不是在代码里反复改字符串。7.2 素材缓存与幂等设计在自动化流程里幂等和缓存非常重要。假设某个场景在第 3 步生成了音频但第 4 步因为图片服务超时而失败。如果重跑整个 Pipeline就会再次消耗一次 TTS 费用。更好的设计是每个素材文件名都包含场景 ID下一次运行前先检查素材文件是否已存在。如果存在就直接跳过该步骤。def generate_audio_with_cache(scene: Scene, audio_dir: Path) - str: audio_path audio_dir / f{scene.scene_id}.wav if audio_path.exists(): scene.audio_path str(audio_path) return str(audio_path) # 只有不存在时才调用 TTS duration mock_tts_to_file(scene.narration, str(audio_path)) scene.duration duration scene.audio_path str(audio_path) return str(audio_path)这个思路可以扩展到文生图和视频片段。每生成一个中间产物都保存对应的manifest.json记录生成该素材使用的 Prompt、模型、参数和时间。这样可以在后续追查问题。7.3 质量校验与人工审片自动化系统必须设置质量门槛否则很容易产出大量低质内容。建议在以下节点加入校验文本层校验旁白长度过滤明显重复、低俗、违规的敏感词。音频层检查时长是否在合理范围内试听音色是否自然。图片层检查图片是否明显损坏、分辨率是否满足要求、有无大量黑边或变形。终片层人工抽检确认节奏、配音、字幕和背景音乐没有明显冲突。即使全流程高度自动化也可以保留一个人工审片的 web 页面让审核人员逐一确认。这样能避免 AI 生成内容出现问题后才被动处理。7.4 版权与合规注意事项AI 短剧自动化必须严格遵守平台规范和相关法律法规。这里需要特别强调几点不要使用未经授权的影视剧片段。不要使用真人肖像去生成虚假对话或换脸内容。不要生成涉及低俗、暴力、歧视、诱导未成年人的内容。如果平台要求标识“AI 生成内容”应当在发布时如实标识。背景音乐和音效要使用有授权的曲库避免音乐版权风险。内容安全始终是第一底线。很多自动化流程只关注“能不能跑通”却忽略了内容审核。作为技术实现者应该至少加入一道关键词敏感内容过滤与人工抽检机制而不是把所有内容都直接发布到公开平台。7.5 成本控制与批量扩展短剧生成成本分布在文本模型、TTS 和图片模型上。控制成本有几个常用手段尽量先生成一个候选文案人工确认后再生成后续素材而不是一次性生成 10 条再挑选。分镜图片可以先用低分辨率生成进入终审后再重新生成高清版本。不同场景可以共用背景素材减少重复图片生成。相同的旁白文本不要重复调用 TTS加入本地缓存。当一条 Pipeline 跑通后你可以批量输入多个故事创意并利用消息队列并发处理。但并发度不要一开始就拉满避免 API 限流导致大批量失败。更推荐的做法是先用一个简单的循环逐条执行观察单条成功率和成本再逐步增加并发。8. 总结与后续学习方向从故事到成片AI 短剧自动化的核心不是“一键生成”而是把创作过程拆成可控制、可重试、可缓存的后台任务。本文实现的 2.5 版本完整跑通了“故事输入、剧本生成、分镜解析、配音、画面素材、FFmpeg 合成、最终成片”的流程。你可以直接拿这套代码替换成自己的模型服务逐步形成属于你的内容生产工具。下一步值得继续研究的方向有三个多场景人物一致性。让同一个角色在不同分镜中保持外貌稳定这通常需要参考图、LoRA 或角色模型能力。音频与画面更强同步。例如根据台词停顿自动切割字幕做到逐句字幕精准对齐。短剧节奏优化。探索自动生成“前 2 秒强钩子”的能力让 AI 不只生成脚本还能根据完播率反馈调整剧情。这套体系越往下做越
返回列表