我们把团队的会议录屏全丢给 AI 做了个检索库,今天开源了
我们把团队的会议录屏全丢给 AI 做了个检索库,今天开源了
6 个月,340 个会议录屏,总计 412 小时。当我们试图找出半年前那个"数据库连接池方案"到底是谁说的、在哪次会议上说的——发现这件事比重新开一次会还难。于是我们写了一个开源工具,今天放出来了:DiTingAI/ditingyun
一、问题:90% 的企业知识,沉睡在录屏黑洞里
如果你在一家成长型团队,大概率是这样的:
- 每周高管复盘会、架构评审、客户访谈、新人培训,录屏堆在飞书 / Zoom / 腾讯会议里
- 会后助理整理一份纪要,关键细节依然遗漏
- 三个月后想找一个技术决策的原始上下文,翻遍聊天记录找不到
- 新人入职面对几十小时的技术分享录屏,无从下手
- 离职员工带走了他脑子里的"会议记忆"
我们自己的团队就是这样的。当 CTO 问"半年前我们为什么选了 Redis 而不是 Memcached"的时候,五个人花了整整一个下午翻录屏,最后还是靠一个老员工的记忆拼出来的。
那一刻我们意识到:录屏不是资产,能被检索的录屏才是资产。
二、市面上的方案,为什么都不对
我们调研了一圈,发现现有方案都有各自的问题:
- 飞书 / 钉钉的会议纪要:只能处理自家平台的会议,且纪要是 AI 自动总结的,丢失原话和时间戳
- Otter.ai / 通用转写工具:单次转写,没有团队知识库概念,不能跨视频检索
- Notion / 语雀:得人手动整理,整理的成本比开会还高
- 企业级知识库(Glean / Fireflies):贵,且数据要上传到他们的云上,国内合规过不去
我们需要的是:
- 能上传任何来源的音视频(Zoom、腾讯会议、本地录屏都行)
- AI 自动转写 + 清洗,不需要人干预
- 能跨视频语义检索,输入问题直接定位到原话
- 数据完全在自己手里,代码可审计
- 5 分钟能部署起来,不是又一个需要运维团队的基础设施
找不到,就自己写一个。
三、架构:一个 Go 二进制,跑完整条管线
技术选型的三个坚持
1. 单二进制交付,零外部依赖
我们没有用 MySQL + Redis + Milvus + 消息队列这套"标准 SaaS 架构"。原因是:开源项目最大的门槛是部署门槛。如果用户要装 4 个服务才能跑起来,90% 的人在第一步就放弃了。
所以我们选了:
- SQLite(纯 Go 的
modernc.org/sqlite,不需要 CGO)存储元数据和向量 - Go 单二进制,
CGO_ENABLED=0 go build编译出来 10MB,拷到任何 Linux 机器直接跑 - Docker Compose 单服务,一条命令起整个系统
代价是单机性能上限——但对"个人和小团队的私有知识库"这个场景,够了。当团队长大需要分布式时,自然演进到我们的云端托管版(这是后话)。
2. AI 服务彻底解耦,三路独立
这是我们踩坑最多、也最满意的架构决策。
最初我们假设"一个 OpenAI 兼容端点搞定一切"——但实际跑起来发现:
- Chat 模型用 GPT-4o-mini 走商业 API
- 语音转写用 Whisper,但 OpenAI 的 Whisper 太贵,自建了 whisper.cpp 服务
- 向量化用 bge-m3(1024 维,中文效果好),也是自建
三个服务在三台不同的机器上,协议也不完全一致。所以我们把客户端设计成三路独立:
chatClient := openai.New(cfg.ChatURL, cfg.APIKey) // 清洗 + 问答
whisperClient := openai.New(cfg.WhisperURL, cfg.APIKey).WithoutAuth() // 转写,自建无认证
embedClient := openai.New(cfg.EmbedURL, cfg.APIKey) // 向量化
开源用户可以:
- 全部用 OpenAI 官方 API(填一个 Key 就行)
- 全部自建(完全离线,零 API 成本)
- 混搭(比如我们自己的配置:Chat 走商业 API、Whisper 和 Embed 自建)
3. 向量化函数抽象,屏蔽协议差异
bge-m3 的 API 不是标准 OpenAI 格式——请求字段是 texts 而不是 input,响应字段是 dense 而不是 embedding。我们没有在业务代码里写 if/else,而是定义了一个 EmbedFunc 函数类型:
type EmbedFunc func(text string) ([]float32, error)
在 handler 初始化时绑定具体实现,业务代码只依赖这个函数签名。切换 embedding 后端(OpenAI / bge-m3 / 本地模型)只改一行配置,不动业务代码。
数据流
上传音视频
│
▼
ffmpeg 抽 16kHz mono WAV ← Whisper 最佳输入格式
│
▼
Whisper 转写 → 原始文本
│
▼
LLM 清洗(去语气词 + 修正术语)
│
▼
滑动窗口切片(500 字 / 100 字重叠)
│
▼
bge-m3 向量化 → SQLite 落库
│
▼
语义检索 / RAG 问答(答案自带出处引用)
整套管线对一段 14 秒的音频,端到端 4.65 秒处理完。
四、踩过的坑:真诚分享
开源不是只展示光鲜的一面。我们把踩过的坑也写出来,希望能帮到同样在做音视频处理的朋友。
坑 1:Whisper 冷启动,第一次请求卡 4 分钟
自建的 whisper.cpp 服务用了懒加载——第一次请求时模型还在从磁盘加载到内存,Go 的 HTTP 客户端(300 秒超时)就一直等着。用户在 UI 上看到"正在处理..."转了 4 分钟,以为程序挂了。
解决:加了分步日志,每一步都打印耗时。后来发现第二次请求就 1.4 秒了——是冷启动的代价,不是 bug。生产环境可以做预热。
坑 2:HTTP keep-alive 导致 EOF
自建 embed 服务在空闲一段时间后会关闭连接,但 Go 的 HTTP 客户端默认复用 keep-alive 连接。下次请求复用了这个死连接,直接 EOF。
解决:http.Transport 设置 DisableKeepAlives: true。代价是每次请求多 30ms 的 TCP 握手,但对低频请求场景完全可接受。
Transport: &http.Transport{
DisableKeepAlives: true,
MaxIdleConnsPerHost: -1,
}
坑 3:ffmpeg 不能原地覆盖输入文件
当用户上传的本身就是 WAV 文件时,我们的代码会尝试用 ffmpeg 把它"转换"成 WAV——输入输出路径相同,ffmpeg 直接拒绝:cannot edit existing files in-place。
解决:检测扩展名,WAV 直传跳过 ffmpeg,其他格式才走转换。
坑 4:同名文件上传触发 UNIQUE 约束
最初 task_id 用文件名生成(test_meeting),chunk id 是 test_meeting_0。同名文件第二次上传,chunk id 冲突,SQLite 报 UNIQUE constraint failed。
解决:task_id 追加 Unix 时间戳(test_meeting_1786288836),每次上传唯一。
五、为什么开源,为什么 AGPL
我们选了 Open-Core 模式,这个决定想了很久。
开源的真正动机:信任
做企业知识库,最大的障碍不是技术,是信任。企业 IT 主管在评估时最防备的就是:"你不会偷偷上传我们的会议内容吧?"
闭源产品再怎么写"我们承诺不泄露",也是黑盒。开源是降维打击——代码就在 GitHub 上,你自己审,自己编译,自己部署。这种透明感是任何 SLA 都换不来的。
为什么 AGPL 而不是 MIT
- MIT 的风险:任何人可以拿你的代码、改个 Logo、做成商业 SaaS 去卖,不需要回馈一行代码。在 AI 和基础设施领域,这种事发生过太多次。
- AGPL-3.0 的网络传染条款:如果你基于修改版通过网络对外提供 SaaS 服务,必须开源你的完整修改。
- 不影响企业内部使用:企业把谛听云部署在内网给员工用,不触发开源义务。
- 商业授权:想闭源二次开发?找我们买商业授权。
这条路 Supabase、PostHog、Dify 都走通了——既能享受开源的传播红利,又能用法律武器保护商业护城河。
社区版 vs 云端版
| 能力 | 社区版(本仓库) | 谛听云云端版 |
|---|---|---|
| 音视频转写 + 清洗 | ✅ | ✅ |
| 语义检索 + 知识问答 | ✅ 单机 | ✅ 分布式集群 |
| 部署方式 | Docker 自托管 | 免运维托管 |
| 团队协作 / 多级权限(RBAC) | ❌ | ✅ |
| 企业自研术语纠错优化 | ❌ | ✅ |
| 多租户隔离 / 审计 / SLA | ❌ | ✅ |
社区版完整覆盖"个人与小团队的私有知识库"场景;当团队长大、需要协同与合规时,自然演进到云端版。我们不靠社区版赚钱,靠它建立信任和生态。
六、5 分钟部署,真的
git clone https://github.com/DiTingAI/ditingyun.git
cd ditingyun
cp .env.example .env # 填入你的 API Key
docker compose up -d
打开 http://localhost:8080,上传第一段视频,开始构建你的知识库。
不想用云端 API?Roadmap 里的本地 whisper.cpp 支持将实现零 API Key、完全离线运行。
七、我们在思考的下一步
- 本地 whisper.cpp:让整个系统完全离线运行,零 API 成本
- 说话人分离:自动区分会议发言人,"张工说..."、"李总问..."
- 时间戳定位:检索结果直接跳到视频对应时间点播放
- 中文术语社区共建:技术词汇纠错词库,社区一起维护
- Web 管理台:MVP 阶段先让管道跑通,UI 是下一步重点
八、最后
我们不是大厂,没有工程师专门做开源运营。这个项目能走多远,取决于第一批种子用户的反馈。
如果你也受够了"会议录屏黑洞",欢迎来 GitHub 看看:
👉 github.com/DiTingAI/ditingyun
- 觉得有用,给个 ⭐ Star,这是开源作者最大的动力
- 有想法,开个 Issue,我们都会认真看
- 想贡献代码,PR 欢迎
我们会在 GitHub 持续更新进展。也欢迎在本文评论区交流——你团队的会议知识是怎么管理的?踩过什么坑?
作者:谛听云团队。我们在做"让每一段音视频都可被检索"这件事。官网:www.ditingyun.cn
浙公网安备 33010602011771号