【文本处理】AI短剧创作平台的剧情上下文构建与文本处理架构
一、项目概述
本文深入剖析AI短剧创作平台的文本处理架构,重点分析剧情上下文构建、角色场景管理、对白剧本处理等核心模块。该平台通过智能上下文感知技术,实现从剧本创作到视频生成的全流程文本处理。
文本处理核心能力:
|
模块 |
功能 |
技术特点 |
|---|---|---|
|
剧情上下文 |
自动构建剧集、角色、场景上下文 |
多维度数据聚合 |
|
对白处理 |
提取和传递角色对白内容 |
支持配音要求生成 |
|
风格适配 |
根据风格自动生成特定Prompt |
仙侠/玄幻/都市等多风格 |
|
镜头衔接 |
保持前后镜头叙事连贯性 |
智能上下文关联 |
二、文本处理架构设计
2.1 整体架构图
┌─────────────────────────────────────────────────────────────────┐
│ 文本处理架构 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ DramaContext │ │ EpisodeContext │ │
│ │ (剧集上下文) │ │ (集上下文) │ │
│ └────────┬────────┘ └────────┬────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────────────────────────────────┐ │
│ │ VideoGenerationContext │ │
│ │ (视频生成上下文构建器) │ │
│ └─────────────────────┬───────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────┐ │
│ │ Enhanced Prompt │ │
│ │ [世界观] + [角色] + [场景] + [对白] + [风格] │ │
│ └─────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
2.2 核心数据结构
export interface DramaContext {
drama_id: number
title: string
style: string
aspect_ratio: string
description: string
genre: string
characters: CharacterContext[]
scenes: SceneContext[]
worldBuilding: string
}
export interface CharacterContext {
id: number
name: string
age: string | null
gender: string | null
appearance: string | null
personality: string | null
description: string | null
image_url: string | null
}
export interface SceneContext {
id: number
location: string
time: string
description: string | null
image_url: string | null
}
三、剧情上下文构建机制
3.1 剧集上下文获取
export async function getDramaContext(drama_id: number): Promise<DramaContext | null> {
const [drama] = await db.select().from(schema.dramas)
.where(eq(schema.dramas.id, drama_id))
if (!drama) return null
const characters = await db.select().from(schema.characters)
.where(eq(schema.characters.drama_id, drama_id))
.orderBy(schema.characters.sort_order)
const scenes = await db.select().from(schema.scenes)
.where(eq(schema.scenes.drama_id, drama_id))
return {
drama_id: drama.id,
title: drama.title,
style: drama.style || 'realistic',
aspect_ratio: drama.aspect_ratio || '16:9',
description: drama.description || '',
genre: drama.genre || '',
characters: characters.map(c => ({
id: c.id,
name: c.name,
age: c.age,
gender: c.gender,
appearance: c.appearance,
personality: c.personality,
description: c.description,
image_url: c.image_url,
})),
scenes: scenes.map(s => ({
id: s.id,
location: s.location,
time: s.time,
description: s.description,
image_url: s.image_url,
})),
worldBuilding: drama.description || '',
}
}
数据聚合策略:
|
数据来源 |
查询逻辑 |
排序方式 |
|---|---|---|
|
剧集基础信息 |
单条记录查询 |
无 |
|
角色列表 |
按drama_id关联 |
sort_order升序 |
|
场景列表 |
按drama_id关联 |
默认顺序 |
3.2 上一集上下文获取
export async function getPreviousEpisode(episode_id: number): Promise<EpisodeContext | null> {
const [currentEpisode] = await db.select().from(schema.episodes)
.where(eq(schema.episodes.id, episode_id))
if (!currentEpisode) return null
const previousEpisode = await db.select().from(schema.episodes)
.where(and(
eq(schema.episodes.drama_id, currentEpisode.drama_id),
lt(schema.episodes.episode_number, currentEpisode.episode_number)
))
.orderBy(desc(schema.episodes.episode_number))
.limit(1)
if (!previousEpisode[0]) return null
const lastStoryboard = await db.select().from(schema.storyboards)
.where(eq(schema.storyboards.episode_id, previousEpisode[0].id))
.orderBy(desc(schema.storyboards.storyboard_number))
.limit(1)
return {
episode_id: previousEpisode[0].id,
episode_number: previousEpisode[0].episode_number,
title: previousEpisode[0].title,
content: previousEpisode[0].content,
script_content: previousEpisode[0].script_content,
duration: previousEpisode[0].duration || 0,
thumbnail: previousEpisode[0].thumbnail,
last_frame_url: lastStoryboard[0]?.last_frame_image || null,
}
}
设计亮点:
-
通过
episode_number字段实现集数排序 -
自动获取上一集最后一镜画面作为参考
-
支持剧情连续性校验
四、视频生成上下文构建
4.1 多层级上下文组装
export async function buildVideoGenerationContext(params: {
drama_id?: number
episode_id?: number
storyboard_id?: number
}): Promise<{
contextPrompt: string
reference_image_urls: string[]
style: string | null
dialogue: string | null
}> {
const contextPromptParts: string[] = []
const reference_image_urls: string[] = []
let style: string | null = null
let dialogue: string | null = null
// 1. 分镜级别上下文
if (params.storyboard_id) {
const [storyboard] = await db.select().from(schema.storyboards)
.where(eq(schema.storyboards.id, params.storyboard_id))
if (storyboard) {
// 获取对白内容
if (storyboard.dialogue) {
dialogue = storyboard.dialogue
contextPromptParts.push(`\n【对白内容】`)
contextPromptParts.push(`本镜头对白:${storyboard.dialogue}`)
}
// 收集参考图
if (storyboard.last_frame_image) {
reference_image_urls.push(storyboard.last_frame_image)
}
}
}
// 2. 上一镜衔接上下文
if (params.storyboard_id) {
const prevStoryboard = await getPreviousStoryboard(params.storyboard_id)
if (prevStoryboard) {
contextPromptParts.push(`【上一个镜头衔接】`)
contextPromptParts.push(`上一个镜头内容:${prevStoryboard.prompt}`)
if (prevStoryboard.last_frame_image) {
reference_image_urls.push(prevStoryboard.last_frame_image)
}
contextPromptParts.push(`\n【镜头连贯性要求】`)
contextPromptParts.push(`本镜头必须与上一个镜头保持连贯过渡...`)
}
}
// 3. 剧集级别上下文
if (params.episode_id) {
const episodeContext = await getEpisodeContext(params.episode_id)
if (episodeContext) {
style = episodeContext.drama?.style || null
// 角色描述
const characterDescriptions = episodeContext.drama?.characters.map(c => {
let desc = `- ${c.name}`
if (c.gender) desc += `(${c.gender})`
if (c.age) desc += `,年龄:${c.age}`
if (c.appearance) desc += `,外貌:${c.appearance}`
if (c.personality) desc += `,性格:${c.personality}`
return desc
}).join('\n')
contextPromptParts.push(`\n【角色设定】`)
contextPromptParts.push(characterDescriptions)
}
}
return {
contextPrompt: contextPromptParts.join('\n'),
reference_image_urls: [...new Set(reference_image_urls)].filter(Boolean),
style,
dialogue,
}
}
4.2 上下文层次结构
上下文构建层次:
├── 第1层:分镜级别
│ ├── 对白内容
│ └── 参考图片
├── 第2层:镜头衔接
│ ├── 上一镜内容
│ └── 连贯性要求
├── 第3层:剧集级别
│ ├── 角色设定
│ ├── 场景设定
│ └── 上一集剧情
└── 第4层:风格特定
└── 风格专属Prompt
五、风格特定Prompt生成
5.1 仙侠风格处理
function getStyleSpecificPrompt(style: string): string {
const xianxiaStyles = ['xianxia', 'xianxia_3d', 'xianxia_2d', 'xianxia_gufeng',
'xianxia_xiannv', 'xianxia_daoist', 'xianxia_demon', 'xianxia_jianxia']
if (xianxiaStyles.includes(style)) {
return `【风格特定要求:仙侠搞笑爽剧】
- 整体风格:3D渲染仙侠风格,飘逸长发,古风长袍,发光仙剑,玄幻光环特效
- 剧情基调:轻松搞笑,爽点密集,节奏明快
- 人物表现:夸张表情,幽默对话,反差萌设定
- 情节设计:打脸逆袭,扮猪吃虎,各种装逼场面
- 笑点安排:每30秒至少一个笑点,台词诙谐幽默
- BGM风格:欢快激昂的仙侠背景音乐,搞笑桥段用喜剧音效`
}
return ''
}
风格映射策略:
|
风格类型 |
处理策略 |
特殊要求 |
|---|---|---|
|
仙侠系列 |
添加仙侠搞笑爽剧特定要求 |
夸张表情、打脸逆袭、每30秒一个笑点 |
|
玄幻系列 |
待扩展 |
神秘能量、魔法符文 |
|
都市系列 |
待扩展 |
现代场景、时尚元素 |
|
真人实拍 |
待扩展 |
高清摄影、专业打光 |
六、AI服务配置管理
6.1 多Provider配置抽象
export interface AIConfig {
provider: string
base_url: string
api_key: string
model: string
extraParams?: Record<string, any>
}
export async function getActiveConfig(serviceType: ServiceType): Promise<AIConfig | null> {
const allRows = await db.select().from(schema.ai_service_configs)
.where(eq(schema.ai_service_configs.service_type, serviceType))
const rows = allRows.filter((r: any) => r.is_active)
.sort((a: any, b: any) => (b.priority || 0) - (a.priority || 0))
const active = rows[0]
if (!active) return null
const models = active.model ? JSON.parse(active.model) : []
return {
provider: active.provider || '',
base_url: active.base_url,
api_key: active.api_key,
model: models[0] || '',
extraParams: active.settings ? JSON.parse(active.settings) : undefined,
}
}
6.2 多Provider URL处理
export function getTextProviderBaseUrl(config: AIConfig) {
const provider = config.provider.toLowerCase()
if (provider === 'openai' || provider === 'openrouter' || provider === 'chatfire') {
return joinProviderUrl(config.base_url, '/v1', '')
}
if (provider === 'volcengine') {
return joinProviderUrl(config.base_url, '/api/v3', '')
}
if (provider === 'ali') {
return joinProviderUrl(config.base_url, '/api/v1', '')
}
return config.base_url
}
Provider URL映射:
|
Provider |
API前缀 |
说明 |
|---|---|---|
|
OpenAI / OpenRouter |
|
标准OpenAI API格式 |
|
火山引擎 |
|
火山引擎特有格式 |
|
阿里云百炼 |
|
阿里云API格式 |
七、上下文增强Prompt结构
7.1 最终Prompt组装
const { contextPrompt, reference_image_urls, style, dialogue } =
await buildVideoGenerationContext({
drama_id: params.dramaId,
episode_id: params.episodeId,
storyboard_id: params.storyboardId,
})
let enhancedPrompt = params.prompt
if (contextPrompt) {
enhancedPrompt = `【当前镜头】\n${params.prompt}\n\n${contextPrompt}`
}
if (dialogue) {
enhancedPrompt = `${enhancedPrompt}\n\n【配音要求】\n严格按照以下对白内容进行配音:${dialogue}`
}
7.2 Prompt结构解析
增强后Prompt结构:
┌──────────────────────────────────────────────────────────────┐
│ 【当前镜头】 │
│ {用户原始prompt} │
├──────────────────────────────────────────────────────────────┤
│ 【上一个镜头衔接】 │
│ 上一个镜头内容:... │
│ 【镜头连贯性要求】 │
│ 本镜头必须与上一个镜头保持连贯过渡... │
├──────────────────────────────────────────────────────────────┤
│ 【世界观设定】 │
│ 剧集名称:... │
│ 艺术风格:... │
│ 题材类型:... │
│ 故事背景:... │
├──────────────────────────────────────────────────────────────┤
│ 【角色设定】 │
│ - 角色1(性别),年龄:...,外貌:...,性格:... │
│ - 角色2(性别),年龄:...,外貌:...,性格:... │
├──────────────────────────────────────────────────────────────┤
│ 【场景设定】 │
│ - 场景1(时间)描述... │
│ - 场景2(时间)描述... │
├──────────────────────────────────────────────────────────────┤
│ 【上一集剧情衔接】 │
│ 上一集标题:... │
│ 上一集剧情摘要:... │
├──────────────────────────────────────────────────────────────┤
│ 【风格特定要求】 │
│ 根据风格自动生成的特定要求... │
├──────────────────────────────────────────────────────────────┤
│ 【配音要求】 │
│ 严格按照以下对白内容进行配音:{dialogue} │
└──────────────────────────────────────────────────────────────┘
八、技术亮点总结
|
特性 |
实现方式 |
技术价值 |
|---|---|---|
|
多层上下文 |
分镜→剧集→世界观三级聚合 |
确保叙事连贯性 |
|
风格适配 |
风格特定Prompt生成器 |
保持艺术风格统一 |
|
对白处理 |
独立的dialogue字段提取 |
支持配音要求传递 |
|
参考图收集 |
自动聚合前后帧参考图 |
提升角色一致性 |
|
多Provider支持 |
配置化Provider管理 |
灵活切换AI服务 |
九、应用场景
-
剧本创作:自动构建剧情上下文,辅助AI续写剧本
-
分镜生成:基于上下文生成符合风格的分镜描述
-
视频生成:为视频生成提供完整的上下文信息
-
配音指导:提取对白内容,指导AI配音
十、总结
本文深入剖析了AI短剧创作平台的文本处理架构,核心设计包括:
-
上下文层次结构:分镜级→剧集级→世界观级的三层上下文构建
-
智能衔接机制:自动获取上一集、上一镜的上下文信息
-
风格特定处理:根据艺术风格生成针对性的Prompt
-
对白提取与传递:支持角色对白的单独处理和配音指导
该架构通过多层次上下文聚合,确保了从剧本创作到视频生成的全流程文本一致性和叙事连贯性,是AI内容生成平台的典型文本处理实践。
核心文件参考:
-
剧情上下文模块:
/backend/src/services/drama-context.ts -
AI服务配置:
/backend/src/services/ai.ts -
视频生成服务:
/backend/src/services/video-generation.ts
火山引擎视频云技术社区,是面向 AI 音视频开发者的技术交流平台。这里汇聚源自抖音、豆包等亿级 DAU 产品的 RTC、直播、点播、AI 媒体处理、音视频互动技术,提供接入指南、最佳实践、性能调优、场景案例、Demo 代码、开源项目、白皮书和 API 文档。社区汇聚官方工程师与一线开发者,为 AI 视频通话、数字人、AI 视频处理等应用的开发与落地提供技术支持。
更多推荐
所有评论(0)