
简介AI-Media2Doc是一款基于AI大模型的开源Web工具可将视频与音频一键转为小红书文案、公众号文章、知识笔记、思维导图等多种风格文档。这款工具面向希望自建媒体处理工作流的开发者、内容创作者与技术爱好者完全开源并采用MIT协议支持本地部署、免登录注册前端借助ffmpeg wasm运行免去本地安装ffmpeg的麻烦还提供AI对话与字幕导出能力。源码包共115个文件、约15.2MB其中Vue前端组件负责界面交互Python后端脚本承担API与转换逻辑TypeScript与JavaScript代码处理前端状态与工具集成另含Dockerfile、环境变量模板、Markdown说明等便于快速部署和二次改造。部署方式支持Docker一键启动或本地前后端分离运行后端依赖字节跳动火山引擎Arkitect SDK需按照模板配置相关环境变量。当前已有36人学习下载适合想快速搭建媒体转文档工具、或深入研究大模型应用与ffmpeg wasm集成的开发者参考。1. 这个工具解决的痛点媒体文件躺在那儿文档却要手写先说一下我做 AI-Media2Doc 的初衷。日常工作中我最烦的一件事就是处理会议录音、课程录屏、访谈视频这类媒体素材。通常一个小时的录音要整理成结构化的会议纪要或者文档至少得花两三个小时——一边听一边记关键信息一多就容易漏回头再找某个时间点说了什么更是翻来覆去地拖进度条。这种重复劳动效率极低而且非常消耗耐心。所以我把整个流程梳理了一遍媒体文件进来语音转文字文字再过一遍大模型做结构化整理最后输出成 Markdown 或者 Word 文档。这本质上就是把“听写归纳排版”这三件事全部自动化。对谁最有用我觉得首先是内容创作者和知识工作者——要把播客、课程、直播回放变成图文稿的人其次是经常开会、需要沉淀会议纪要的团队再就是程序员这类需要把技术分享视频变成文字笔记的群体。如果你也属于其中之一这个工具应该能给你省下大量时间。这个工具的设计目标是输入一段音频或视频输出一份逻辑清晰、信息完整、可直接二次编辑的 Markdown 文档。项目是开源的源码就放在仓库里你可以直接拉下来跑也可以按自己的需求改流程、换模型、加功能。下面我从架构设计到核心实现再到使用方式和踩坑记录完整地把这个项目讲一遍。2. 系统架构与几个关键选型的理由2.1 整体流程媒体解析、语音识别、LLM 精炼、文档导出四段式管线AI-Media2Doc 的整体流程不复杂就是一条四段式管线媒体解析层负责把 mp3、mp4、wav、m4a 等格式的输入文件解码成统一的音频数据。语音识别层把音频切成片段逐段转写成带时间戳的文本。精炼层把上一步的转写文本交给大模型做分段、摘要、去口语化、结构化整理。导出层把结构化内容渲染成 Markdown 文档。每一层之间通过标准的数据结构对接所以你可以单独替换任意一层。比如你不想用我默认的语音识别服务可以换成其他的你不想用大模型做精炼也可以只保留转写输出。这种解耦设计保证工具不会绑死在某个具体模型上。分层设计不是一个炫技的选择而是有实际理由的。媒体解析和语音识别是两类完全不同的工作前者偏重格式兼容性后者偏重准确率而精炼层又是纯文本处理逻辑完全独立。如果揉在一起写改动任何一个环节都会牵一发动全身。分层之后每一层都能独立测试、独立升级调试的时候定位问题也快得多。2.2 为什么默认选 Faster-Whisper 做转写而不是其他方案语音识别层我默认用的是 Faster-Whisper。这不是随手选的而是比较过几个方案之后的结果。当时摆在面前的主要有这么几条路OpenAI 官方 Whisper、Faster-Whisper、云厂商的语音识别 API还有一些更轻量的本地引擎。云厂商 API 准确率好但要上传音频文件有些场景比如内部会议录音根本不适合把内容传出去而且按分钟计费长音频跑多了成本不低。OpenAI 官方 Whisper 可以本地跑但速度偏慢在 CPU 上处理长时间音频会很痛苦。Faster-Whisper 基于 CTranslate2 重写了 Whisper 的推理部分在保持准确率基本一致的前提下速度快了非常多尤其在 GPU 上非常明显。对于这个工具来说速度直接决定了它的实用性。一小时的音频如果转写要跑四十分钟那还不如手动如果只需要几分钟那这个工具就有真正的使用价值。Faster-Whisper 让后者变成了现实。而且它支持 int8 量化可以在不牺牲太多准确率的情况下把显存和内存占用压到一个很舒服的水平。另外Faster-Whisper 还能输出每个片段的时间戳这个时间戳在后续定位关键信息时特别有用。比如你可以根据关键词搜索直接跳到视频对应的位置去确认原话这一点在整理访谈类内容时几乎是刚需。2.3 为什么用 VAD 做音频切分而不是固定时长硬切音频切分是语音识别里很容易被忽视、但实际影响很大的一个环节。很多工具图省事直接把音频按 30 秒一段切好再送进识别模型。这种固定时长硬切的方式有一个很致命的问题如果切点正好落在句子中间模型就很难理解上下文容易出现错别字和断句混乱。比如一个句子前半段在上一段后半段在下一段模型单独看哪一半都拼不出完整的语义。我采用的是 VAD语音活动检测来做动态切分。简单理解VAD 会先把一整段音频扫一遍找到所有“有人说话”的区间和“没人说话”的停顿点然后在静音处切开再对每一段做语音识别。这样就可以尽量保证每个片段里是完整的一句话或几句话模型的识别准确率会明显提升。这个思路跟人听语音时自然停顿换气的状态是一致的它不是生硬地把语音分成等长的小块而是照着语义自然的边界去切。实现上我用了 Silero VAD它和 Faster-Whisper 配合得很顺检测速度很快在长音频上表现也稳定。一个小细节是切分参数需要根据内容类型调整。纯演讲类的停顿比较规律可以把静音阈值调高一些让分段长一点访谈类因为两个人会抢话停顿短分段就适当切碎一些。这些参数我都在配置里暴露了方便你自己调。3. 媒体解析与音频预处理最容易被忽略但最能决定成败的环节3.1 底层用什么解码怎么处理不常见的音视频格式媒体解析层我用了 FFmpeg 作为底层解码器。这是目前兼容性最强的方案几乎不需要自己处理编码格式的差异FFmpeg 会全包。你需要处理的输入格式范围一般很杂——mp3 是最基本的m4a 是苹果生态里常见的还有各种 mp4 视频文件甚至有些是手机录音直接生成的 amr 或者 ops 格式。FFmpeg 对所有这些格式的支持都很成熟你只需要调用一个命令就能把音频流无损提取成 wav 文件。不过这里有一个值得注意的坑不常见的容器格式不一定意味着音频编码也是常见的。比如有的视频文件扩展名是 mp4但里面的音频轨可能是 ac3 或者 opus这在某些录屏软件的输出里很常见。直接换成 wav 的时候必须显式指定音频编码否则 FFmpeg 可能会用默认的 pcm_s16le 做一次有损转换或者在某些场景下直接失败。我的做法是统一转成 16kHz 单声道的 wav这是 Faster-Whisper 最舒服的输入格式既能保证转写质量又能把文件体积压到最小。码率也是一个需要控制的点。16kHz 采样率对语音识别来说足够用了说话人的音色、语调这些信息不会丢失相比之下44.1kHz 的 CD 音质没有任何意义只会让文件更大、处理更慢。所以很多时候看起来是在处理格式其实是在决定后续所有环节的性能天花板。3.2 音量归一化、降噪、人声增强的取舍在实际使用中我遇到过大量低质量的输入音源。有的是在嘈杂的咖啡馆里录的访谈有的是从视频网站直接抓下来的音频底噪很重还有的是电话录音音量大起大落。如果不做任何预处理识别结果里就会出现大量“嗯”“啊”的对白错判而且嘈杂背景会让模型把环境声音误识别成内容。所以我在解析层加了几道可选的预处理步骤。第一道是音量归一化先把整段音频的音量压倒一个统一的标准线避免前面说话声大、后面说话声小导致模型在后半段识别率骤降。第二道是降噪我用的是基于 RNNoise 的实现适合处理稳态的底噪比如风扇声、电流声、空调声处理效果非常自然不会像某些激进降噪算法那样把人声也削得发闷。第三道是人声增强主要用于那些背景音特别复杂的场景把人声频率范围以外的声音压下去。这几种处理不是默认全开的因为它们会影响一个东西自然度。如果你处理的本来就是录音棚里的高质量播客降噪反而会破坏声音的细节。所以我在配置里把它们做成开关默认只开音量归一化其余按需启用。这一点我认为比未经思考地“把所有音频都做一遍全套处理”要更合理因为处理链越长引入的损耗就越多。4. 从转写到结构化精炼让大模型真正帮你干活的关键设计4.1 长文本的分段处理策略单次喂给大模型行不行拿到语音转写结果以后文字还是流水账没有章节、没有重点。要变成一份合格的文档得靠大模型做精炼。但是这里会撞上一个非常现实的问题大模型有上下文窗口限制而且越长的输入处理质量越不稳定费用也越高。一个小时的音频转写出来文字量一般在八千到一万五字之间而很多模型的最佳上下文是在四到八千字之间。直接一股脑塞进去效果不会好。我的做法是先做内容分段。具体思路是利用转写结果里自带的时间戳按段落语义把大段文本切成多个小段每段大约对应一个话题。这一步可以用一个轻量级的模型来粗分也可以完全用规则做——比如根据停顿时间、话题词出现频率来判断。分段之后每段单独交给大模型做精炼然后再把结果合并起来。分段的核心好处是每一段文本都能得到充分的注意力大模型能比较完整地理解这一段里说了什么、重点在哪而不是在大段文字里“走马观花”。上下文一短幻觉率也会明显下降。4.2 精炼层的 Prompt 设计我想要什么样的文档就说得越具体精炼层真正考验工程能力的是 Prompt 的设计。一开始我用的 Prompt 很简单只说“把下面的文字整理成文档”结果出来的东西非常不理想。模型会把所有内容都当成重点不分主次口语化内容删不掉该保留的细节也经常被砍掉。后来我慢慢总结出一套结构化的 Prompt包含了三个关键要素角色设定、输出结构要求、保留注意事项。角色设定让模型知道自己是“专业文档整理助手”输出结构要求明确告诉它应该产出哪些标题层级、每个部分应该包含什么信息保留注意事项则防止它把有价值的细节比如数字、人名、专有名词、关键结论悄悄改掉。举个例子我在 Prompt 里会强调“保留所有具体的数字、日期、名称和结论性内容”以及“去除嗯、啊、然后这类无意义的口语填充词”。这两个约束看似简单实际上对文档质量的影响非常大。前者让文档的信息密度保持在高位后者让文档读起来干净利落。处理片段时我会把该片段的转写文本连同它前后各一小段上下文一起送入模型这样能保证不同片段之间的边界更平滑不会出现一段和另一段之间话题断层的情况。4.3 怎么把大模型的输出稳定地变成 Markdown 结构大模型输出本身是自然语言要变成一份结构完整、可解析的 Markdown 文档还需要一层“约束”。我的做法是要求模型在输出时遵循一个强制性的格式模板。模板里定义了文档的一级标题、二级标题、列表、引用等标记规则。同时在解析层做了双重保险如果输出里有不符合模板的内容解析器会做容错处理比如自动把裸段落转成普通段落把乱用的标题层级修正掉。这里还有一个细节有时候模型会在精炼过程中把“口语化表达”过度删减导致文档失去了原文里讲话者的语气和风格。所以在 Prompt 里我还会约束“保留讲话者的核心语气但去除冗余表达”。这样产出的文档不是冷冰冰的摘要而是有“人味”的整理稿。5. 源码结构、环境配置与直接上手运行5.1 下载源码后的目录结构和模块职责源码仓库拉下来以后整个项目的目录结构是不复杂的核心模块一眼能看明白media2doc/ ├── main.py # 命令行入口 ├── requirements.txt # 依赖清单 ├── config/ │ ├── default.yaml # 默认配置 │ └── custom.yaml.example # 自定义配置模板 ├── media_parser/ │ ├── extract.py # 媒体解析与音频提取 │ └── preprocess.py # 音量归一化、降噪、人声增强 ├── asr/ │ ├── transcribe.py # 语音识别封装 │ └── vad.py # VAD 切分逻辑 ├── refine/ │ ├── chunker.py # 长文本分段 │ ├── prompt.py # Prompt 模板管理 │ └── llm_refine.py # 大模型精炼封装 ├── exporter/ │ └── markdown_exporter.py # Markdown 导出 └── utils/ ├── logger.py # 日志 └── file_utils.py # 文件处理辅助这个结构的设计思路很简单按论文里说过的四层管线一层一个目录。这样做有个立竿见影的好处就是你不需要看懂全部代码就能定位到自己关心的问题。比如你想改 Prompt就直接进 refine 目录你想换语音识别方案只看 asr 目录就够了。5.2 从零配置到跑通 Demo完整的命令级操作运行环境方面我建议用 Python 3.10 以上版本。先把项目代码拉下来进入项目根目录然后安装依赖创建虚拟环境是这一步最推荐的做法尽量别把依赖装到系统 Python 里。依赖的主要大头是 faster-whisper、torch、yaml、ffmpeg-python 这几个。依赖装好后还需要确认你机器上装了 FFmpeg。在命令行里输入ffmpeg -version能正常输出就说明没问题。FFmpeg 是媒体解析层唯一的外部依赖没有它整个工具都跑不起来。一切就绪后最简单的一条命令是python main.py -i meeting_recording.mp3工具会读取这个音频文件经过转写、精炼最终在输出目录下生成一份 markdown 文件。如果你想更进一步指定用 GPU 做加速或者换一个大模型模型可以在命令行追加参数python main.py -i meeting_recording.mp4 --model large-v3 --device cuda --language zh跑通之后你可以打开生成的文档检查识别准确率和文档结构是否符合预期。如果对某个环节不满意按前面说的去对应模块目录里改配置就行。5.3 默认模型、参数与成本预估以及显存占用默认情况我用的转写模型是小尺寸的small因为这个模型在中文场景下准确率和速度的平衡比较好。如果你对准确率要求更高可以换成medium或large-v3。用 smaller 模型跑一小时音频CPU 下大约需要十分钟左右如果用 large-v3 加 GPU可以压缩到两三分钟。显存占用方面small模型加 int8 量化在 GPU 上只需约 2GB 显存所以很多低端显卡也能跑得动。medium大概需要 5 到 6GBlarge-v3则建议至少 10GB 以上显存。这个数据是我实际在不同环境里测试出来的不同机器会有一些浮动但量级是可信的。精炼层默认接入的是 OpenAI 兼容的 API 接口所以理论上支持任何提供 OpenAI 兼容 API 的服务。你可以直接填 API Key也可以改成用本地部署的模型服务。成本方面精炼一小时音频大约消耗 3 万到 5 万 token具体取决于转写出的文字量。如果使用通用模型的开放 API这个量级的成本目前大概在几毛钱到几块钱之间是可以接受的。6. 开发与使用中踩过的几个比较典型的坑6.1 VAD 切分导致的上下文截断问题以及最终的解法最早版本我在 VAD 切分后直接对每一段单独识别不做任何上下文衔接。结果是段与段之间的衔接处经常出现语义断裂后一段开头几个人称代词、指代关系会识别错。比如前一句说的是“张三觉得这个方案有问题”下一句开头是“他说可以再讨论一下”模型单独看后面一句就完全不知道“他”指的是谁。这个问题困扰了我几天后来我参考了语音识别领域常用的“带上下文的重叠预测”思路识别当前段落时把前一段末尾的两三秒音频也一起送进去。模型能看到更多前文输出时再把重叠部分剪掉。这个改动不大但识别准确率确实有明显提升。如果你在用的过程里也遇到类似问题可以先检查一下 VAD 参数是不是切得太碎。分段越多上下文断裂的风险就越大。6.2 长音频的内存与时间开销以及断点续传的方案还有一个坑是内存和时间开销。长音频超过两小时处理时如果一次性把整个文件读进内存既占内存又容易在转写中途因为意外中断而前功尽弃。第一次跑一个三小时的培训录像时我直接把它读进内存做处理结果不知不觉占掉了好几个 GB机器都开始卡了。后来我把处理改成了分块流式先解析出音频文件的基本信息按时间戳切分成多个临时文件一个处理完再处理下一个同时把已处理的结果实时写盘。这样就算中途崩了已经处理好的部分也不会丢。我又加了断点续传机制每次处理完几个片段就把进度记录到一个状态文件里重新运行时自动跳过已完成的部分。这个机制在长任务场景里非常实用。6.3 时间戳在转写中的漂移问题以及校准方法时间戳漂移也是一个很隐蔽的问题。Faster-Whisper 会为每段识别结果生成开始和结束时间但在较长的音频里这些时间戳可能会产生一定偏移越往后越明显。如果你要基于时间戳做“跳转到对应视频位置”的功能这个问题会被放大。我的处理方案是转写完成后做一次基于子片段的对齐校准用音频文件的真实总时长与最后一段识别结果的结束时间对比得到一个全局偏移系数然后按比例修正每一条时间戳。这个修正不是绝对精确但能把误差控制在一个可以接受的范围。这个方案还可以结合音频特征对齐来做进一步优化但当前版本已经能满足绝大多数场景的需求。7. 按你自己的场景去改这个工具如果你只是想要一个“音频转文档”的现成工具那拉到代码直接跑就够用了。但如果你愿意多花点时间这个项目其实有很多可以按自己需求改的地方。比如你可以把导出格式从 Markdown 改成 HTML、PDF 或者 Word只需要在 exporter 目录下新增一个导出类就行。再比如如果你处理的内容高度垂直比如医学讲座、法律访谈、金融会议那可以在精炼 Prompt 里加入领域相关的术语表和输出要求让模型用更专业的表达方式输出。我自己的话最近在往这个项目里加字幕导出功能因为很多做视频内容的朋友需要从音频里直接生成 SRT 字幕。技术上没有什么新的挑战把 ASR 阶段的时间戳和文本直接映射成 SRT 格式就行。这种思路也给你一个参考这个工具的核心能力是“从媒体里提取结构化信息”只要把这个能力用好衍生功能其实都是水到渠成的事。最后分享一个我在实操中特别上头的用法把一小时的技术分享视频丢进去几分钟后得到一份带时间戳的 Markdown 笔记。配合 Obsidian 之类的知识库工具可以直接把笔记和原始视频建立双向链接。以后想找某段观点的出处直接搜笔记里的关键词再点击链接跳回原视频对应时间点就行。这种“媒体内容可检索化”的体验用一次就会觉得之前手动整理文档的时间全是白费的。我把整个工具开源出来也是希望它不只是在某一个场景里能用而是能给更多人省出时间去做更有创造力的事情。本文还有配套的精品资源点击获取