大模型在视频创作工具中的应用:从脚本生成到自动剪辑的AI工具链
大模型在视频创作工具中的应用从脚本生成到自动剪辑的AI工具链一、背景与问题定义视频创作的门槛从未像今天这样低——手机能拍 4K剪辑软件几乎免费。但拍出来和拍好之间仍隔着巨大的鸿沟脚本怎么写、分镜怎么规划、配音怎么配、字幕怎么加。这些环节对普通创作者来说每一环都是专业技能的壁垒。大模型的出现改变了这个局面。LLM 能写脚本、TTS 能做配音、ASR 能转字幕、视觉模型能理解画面——如果把这些能力编排成一条创作工具链普通人只需要提供我想做一个关于 XX 的视频的主题就能获得脚本→分镜→配音→自动剪辑→字幕的全流程辅助。本文复盘一条 AI 视频创作工具链的后端架构设计涵盖脚本生成、TTS 集成、自动剪辑时间轴生成、ASR 字幕生成和微服务编排。二、整体工具链架构脚本生成与分镜规划3.1 脚本生成的 Prompt 工程脚本生成是工具链的第一步也是最关键的一步。使用 Qwen-Max 模型Prompt 设计为三阶段阶段一生成结构化大纲你是一位专业的短视频脚本策划师。用户想做一个关于{topic}的视频 时长约 {duration} 秒风格为 {style}。 请生成一个结构化的视频大纲 1. 开场钩子前3秒抓住注意力 2. 主要内容段落3-5个要点 3. 结尾总结行动号召 格式要求返回 JSON阶段二展开为完整脚本基于以下大纲展开为完整的视频脚本。 每个段落需要包含 - 旁白文字用于TTS配音 - 画面描述用于分镜和素材匹配 - 预估时长秒 {大纲JSON} 返回格式JSON数组3.2 分镜规划的实现Service public class ScriptGeneratorService { private final LlmClient llmClient; public VideoScript generateScript(CreationRequest request) { // 阶段一大纲 String outlinePrompt buildOutlinePrompt(request); String outlineJson llmClient.chat(outlinePrompt); ScriptOutline outline JSON.parseObject(outlineJson, ScriptOutline.class); // 阶段二完整脚本含分镜 String scriptPrompt buildScriptPrompt(outline); String scriptJson llmClient.chat(scriptPrompt); ListScriptSegment segments JSON.parseArray(scriptJson, ScriptSegment.class); // 校验总时长校验 int totalDuration segments.stream() .mapToInt(ScriptSegment::getDurationSeconds) .sum(); if (Math.abs(totalDuration - request.getTargetDuration()) 10) { // 时长偏差超过10秒重新调整 return adjustScriptDuration(segments, request.getTargetDuration()); } return new VideoScript(outline, segments); } private String buildScriptPrompt(ScriptOutline outline) { return 基于以下大纲展开为完整的视频脚本。 每个段落需要包含 - narration: 旁白文字用于TTS配音口语化 - sceneDescription: 画面描述用于分镜尽量具体描述场景、动作、构图 - durationSeconds: 预估时长整数单位秒 大纲 %s 返回格式JSON数组 [{narration, sceneDescription, durationSeconds}] .formatted(JSON.toJSONString(outline)); } }三、TTS 配音集成与自动剪辑4.1 TTS 配音批处理配音使用火山引擎 TTS 服务音色主播小泽按脚本段落逐一生成音频Service public class TTSService { private final VolcengineTtsClient ttsClient; private final ExecutorService executor Executors.newFixedThreadPool(8); public ListAudioSegment generateAudios(ListScriptSegment segments) { ListCompletableFutureAudioSegment futures new ArrayList(); for (int i 0; i segments.size(); i) { final int index i; ScriptSegment seg segments.get(i); CompletableFutureAudioSegment future CompletableFuture.supplyAsync(() - { byte[] audioData ttsClient.synthesize( TtsRequest.builder() .text(seg.getNarration()) .voice(zh_female_voyage_emo_large) .speed(1.0) .volume(1.0) .build()); // 计算实际音频时长 double actualDuration getAudioDuration(audioData); return new AudioSegment(index, audioData, actualDuration); }, executor); futures.add(future); } return futures.stream() .map(CompletableFuture::join) .sorted(Comparator.comparingInt(AudioSegment::index)) .collect(Collectors.toList()); } }4.2 自动剪辑时间轴生成自动剪辑的本质是将脚本段落、配音音频、画面素材按时间轴组装。时间轴是一系列片段Clip的序列每个 Clip 包含起止时间、素材引用和转场效果。Service public class AutoEditService { public EditTimeline generateTimeline(ListScriptSegment segments, ListAudioSegment audios, ListMaterial materials) { EditTimeline timeline new EditTimeline(); double currentTime 0.0; for (int i 0; i segments.size(); i) { ScriptSegment seg segments.get(i); AudioSegment audio audios.get(i); // 素材匹配根据画面描述检索匹配的素材 Material matchedMaterial materialMatcher.match( seg.getSceneDescription(), materials); double clipDuration audio.getActualDuration(); Clip clip Clip.builder() .index(i) .startTime(currentTime) .endTime(currentTime clipDuration) .materialId(matchedMaterial.getId()) .materialTrimStart(matchedMaterial.getSuggestedTrimStart()) .audioId(audio.getAudioFileId()) .transition((i segments.size() - 1) ? Transition.FADE : Transition.NONE) .build(); timeline.addClip(clip); currentTime clipDuration; } // 添加片尾 timeline.addClip(Clip.builder() .index(segments.size()) .startTime(currentTime) .endTime(currentTime 3.0) .type(ClipType.ENDING) .build()); return timeline; } }4.3 FFmpeg 视频合成时间轴生成后通过 FFmpeg 的 concat demuxer 将素材拼接为完整视频public class FfmpegCompositor { public void composite(EditTimeline timeline, String outputPath) { // 生成 concat 文件列表 StringBuilder concatFile new StringBuilder(); for (Clip clip : timeline.getClips()) { concatFile.append(String.format( file %s\n, clip.getRenderedClipPath())); } Path concatListPath Files.createTempFile(concat_, .txt); Files.writeString(concatListPath, concatFile.toString()); // FFmpeg 拼接 混音 String cmd String.format( ffmpeg -f concat -safe 0 -i %s -i %s -filter_complex [1:a]volume0.8[bgm];[0:a][bgm]amixinputs2:durationfirst -c:v libx264 -preset fast -crf 23 -c:a aac -b:a 128k -movflags faststart %s, concatListPath, timeline.getBackgroundMusicPath(), outputPath); executeFfmpeg(cmd); } }四、ASR 字幕生成字幕生成在视频合成后进行。使用 Whisper-Large-v3 模型中文识别准确率达到 96% 以上import whisper import json class SubtitleGenerator: def __init__(self, model_size: str large-v3): self.model whisper.load_model(model_size) def generate(self, video_path: str, output_srt: str) - list[dict]: result self.model.transcribe( video_path, languagezh, tasktranscribe, verboseFalse, word_timestampsTrue # 启用词级时间戳 ) # 生成 SRT 格式字幕 with open(output_srt, w, encodingutf-8) as f: for i, segment in enumerate(result[segments], 1): start self._format_timestamp(segment[start]) end self._format_timestamp(segment[end]) text segment[text].strip() f.write(f{i}\n{start} -- {end}\n{text}\n\n) return result[segments] def _format_timestamp(self, seconds: float) - str: hours int(seconds // 3600) minutes int((seconds % 3600) // 60) secs int(seconds % 60) millis int((seconds % 1) * 1000) return f{hours:02d}:{minutes:02d}:{secs:02d},{millis:03d}五、总结AI 视频创作工具链的本质是将专业创作流程中的每个步骤——脚本、分镜、配音、剪辑、字幕——分别用 AI 模型替代或辅助并通过微服务架构编排成一条完整的流水线。工程上的关键设计选择LLM 脚本生成采用两阶段大纲→完整脚本以控制质量和结构TTS 配音按段落并行生成以减少整体延迟8 核并行将 60 秒脚本的配音时间从 15 秒降到 3 秒FFmpeg concat 拼接而非程序化逐帧合成简单可靠ASR 使用 Whisper 的词级时间戳实现精确的字幕对齐。后续方向引入视频生成模型如 Sora、可灵能力让 AI 直接生成视频素材而不仅是检索匹配利用用户修改脚本的行为数据做 RLHF 微调让 LLM 逐渐写出更符合创作者口味的脚本以及构建多模态反馈闭环——根据视频的播放数据和用户互动数据反向优化脚本生成的 Prompt 策略。