本文将告诉大家如何基于多模态大模型、语音合成能力和 FFMpeg 实现自动将 PPT 文档转换为带专业讲解的演讲视频,项目代码拉取后即可直接运行。我现在给的提示词炼丹效果是针对于教育垂直领域,整个代码完全开源,欢迎二次创作
本文内容由人类主导 AI 辅助编写
平时做技术分享或者课程录制的时候,经常需要对着 PPT 录制讲解视频,每次重录都要花费大量时间。于是我做了这个小工具,只需要导入 PPT 文件,就能自动生成连贯的演讲视频,全程不需要人工干预,效果如下:
效果演示视频: http://cdn.lindexi.site/courseware_speech_20260507211402.mp4
软件运行界面:

整个工具的核心逻辑分为三步:
本文代码放在 github 和 gitee 上,可以使用如下命令行拉取代码。我整个代码仓库比较庞大,使用以下命令行可以进行部分拉取,拉取速度比较快
先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到本文的代码
git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin 7ff72da8af31ddf01ba28ada7ee9adeef4abcc13以上使用的是国内的 gitee 的源,如果 gitee 不能访问,请替换为 github 的源。请在命令行继续输入以下代码,将 gitee 源换成 github 源进行拉取代码。如果依然拉取不到代码,可以发邮件向我要代码
git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
git pull origin 7ff72da8af31ddf01ba28ada7ee9adeef4abcc13拉取代码之后,进入 WPFDemo/JawjeleceeYairlubelhearrene 文件夹,打开 sln 解决方案即可直接编译运行。运行前需要提前准备好以下信息:
自己注册账号是有免费额度的,实在不想注册的话,再私聊找我借账号吧
整个工具采用 MVVM 架构,核心逻辑封装在 CoursewareSpeechVideoGenerator 服务类中,下面拆分各个模块的实现细节。
首先需要使用 OpenXML 解析 PPT 文件,提取每一页的文本内容,同时生成每一页的缩略图截图,封装到 CoursewareMaterialInfo 模型中,包含整个 PPT 的所有页面信息,代码如下:
public class CoursewareMaterialInfo
{
/// <summary>
/// PPT所有页面的材料信息
/// </summary>
public List<CoursewareSlideMaterialInfo> SlideMaterialInfoList { get; set; } = [];
}
public class CoursewareSlideMaterialInfo
{
/// <summary>
/// 当前页面的文本内容
/// </summary>
public string ContentText { get; set; } = string.Empty;
/// <summary>
/// 当前页面的截图文件路径
/// </summary>
public string SlideThumbnailFilePath { get; set; } = string.Empty;
}这里使用 OpenXML 提取文本,然后使用 COM 方式调用本机的 Office 组件进行 PPT 页面截图。细节逻辑还请自行阅读代码
讲稿生成是整个工具的核心,为了保证生成的讲稿上下文连贯,每次调用大模型的时候,不仅传入当前页的文本和截图,还会传入整份 PPT 的全部文本和前面已经生成的所有讲稿内容,让大模型能够理解上下文,避免重复讲解,代码如下:
var openAiClient = new OpenAIClient(new ApiKeyCredential(options.OpenAiApiKey), new OpenAIClientOptions
{
Endpoint = options.OpenAiEndpoint,
NetworkTimeout = TimeSpan.FromHours(1)
});
var chatClient = openAiClient.GetChatClient(options.OpenAiModel).AsIChatClient();
// 逐页生成讲稿
for (var i = 0; i < coursewareMaterialInfo.SlideMaterialInfoList.Count; i++)
{
var slideMaterialInfo = coursewareMaterialInfo.SlideMaterialInfoList[i];
var slideIndex = i + 1;
var plainScriptText = await GenerateSlideScriptAsync(
chatClient,
allCoursewareText, // 整份PPT的全部文本
slideIndex,
slideMaterialInfo.ContentText, // 当前页文本
previousScriptsBuilder.ToString(), // 前面已经生成的讲稿
slideMaterialInfo.SlideThumbnailFilePath, // 当前页截图
cancellationToken);
slideInfoList.Add(new CoursewareSpeechSlideInfo(plainScriptText, slideMaterialInfo));
previousScriptsBuilder.AppendLine(plainScriptText);
}这里用了 Microsoft.Extensions.AI 抽象的 IChatClient 接口,所以只要是兼容 OpenAI API 格式的多模态模型都可以直接对接,不需要修改核心逻辑,比如对接豆包 ARK 服务的时候只需要替换对应的 Endpoint 和模型 ID 即可。为什么我这里没有选用 DeepSeek 呢?这是因为现在(2026年5月)的 DeppSeek 还没有多模态支持
具体的生成讲稿 GenerateSlideScriptAsync 逻辑核心就是拼接文本信息,以及将截图给到多模态的大模型,要求它输出讲稿内容。这部分涉及到了提示词炼丹,提示词内容比较长,我就不放在博客里面,大家可以拉取我的代码,了解细节内容
生成的讲稿内容示例如下:

[上下文: 语气亲切活泼,带有课堂互动感,符合小学语文教师授课风格]
现在我们正式进入第1课时的学习,首先开启的是“激发兴趣,导入新课”环节。[停顿: 0.8秒]
大家看页面中间的“儿歌欣赏”字样,旁边还有一个小喇叭的图标,我们先来听一首和今天学习主题相关的趣味儿歌哦。[停顿: 1秒]
听完儿歌老师要考考大家,这是一首关于什么的儿歌呀?没错,答案就是我们今天的主题腊八粥,你看页面上蓝色标注的答案,你答对了吗?[停顿: 1秒]
接下来老师再问大家第二个问题,腊八粥是哪个节日会吃的传统美食呢?[停顿: 1.2秒]
太棒了,大家都记得,就是腊八节,每年农历腊月初八腊八节这天,喝一碗热乎香甜的腊八粥,是很多地方流传已久的习俗哦。[停顿: 0.8秒]
不知道大家还记不记得之前学过的老舍先生的《北京的春节》?那篇课文里是怎样介绍腊八粥的呢?[停顿: 1秒]
对哦,在《北京的春节》的第1自然段里,老舍先生就专门介绍了腊八粥用到的丰富食材,写得特别让人嘴馋。[停顿: 0.8秒]
除了我们刚刚提到的这些内容,你对腊八粥还有更多的了解吗?大家可以先在心里想一想,接下来我们就一起走近作家沈从文,看看他笔下的腊八粥又有着怎样的动人故事。以上这些 [] 包括起来的内容,将在下一步语音合成逻辑进行处理
讲稿生成完成之后,调用火山引擎的 OpenSpeech 服务逐页生成音频,这里封装了统一的合成配置,可以自定义发音人、语速、语调等参数:
var authentication = OpenSpeechAuthentication.CreateWithApiKey(options.OpenSpeechApiKey, options.ResourceId);
var synthesisOptions = new CoursewareSpeechSynthesisOptions(authentication, options.Speaker);
// 逐页合成音频
foreach (var slideInfo in speechInfo.SlideInfoList)
{
var audioFile = await OpenSpeechSynthesizer.SynthesizeAsync(
slideInfo.ScriptText,
synthesisOptions,
cancellationToken);
slideInfo.AudioFilePath = audioFile.FullName;
}火山引擎的 OpenSpeech 提供了多种专业的发音人可选,生成的音频自然流畅,几乎听不出来是合成的语音。在合成语音的时候,需要先执行解析,提取出来脚本内容,比如上下文和停顿信息,这部分细节都在 CoursewareSpeechVideoGenerator.cs 文件里面,核心提取逻辑都是采用正则匹配,如果大家感兴趣,还请拉取代码了解细节
最后一步就是使用 FFMpeg 将每一页的截图和对应的音频拼接成完整的视频,这里我封装了 FFmpegVideoComposer 类处理视频合成的逻辑,自动处理图片时长和音频的对齐:
await using var ffmpegVideoComposer = new FFmpegVideoComposer(
options.FfmpegExecutableFile,
workingDirectory: options.OutputDirectory,
logHandler: (level, message) => progress?.Report($"[{level}] {message}"));
// 逐页添加视频片段
foreach (var slideInfo in speechInfo.SlideInfoList)
{
ffmpegVideoComposer.AddImageClip(
slideInfo.SlideMaterialInfo.SlideThumbnailFilePath,
slideInfo.AudioFilePath);
}
// 合成最终视频
var outputVideoFile = new FileInfo(Path.Combine(options.OutputDirectory.FullName, $"courseware_speech_{DateTime.Now:yyyyMMddHHmmss}.mp4"));
await ffmpegVideoComposer.ComposeAsync(outputVideoFile, cancellationToken);合成的视频默认保存在输出目录下,文件名带时间戳,中间生成的临时音频和图片文件会在合成完成后自动清理,不会占用额外磁盘空间。
提示词部分是我采用 HyperAgent 思想的实践 制作 PPT 文档内容分析提示词 的方式炼丹获取的,大家可以换成其他提示词