我们把团队的会议录屏全丢给 AI 做了个检索库,今天开源了

我们把团队的会议录屏全丢给 AI 做了个检索库,今天开源了

6 个月,340 个会议录屏,总计 412 小时。当我们试图找出半年前那个"数据库连接池方案"到底是谁说的、在哪次会议上说的——发现这件事比重新开一次会还难。于是我们写了一个开源工具,今天放出来了:DiTingAI/ditingyun

一、问题:90% 的企业知识,沉睡在录屏黑洞里

如果你在一家成长型团队,大概率是这样的:

  • 每周高管复盘会、架构评审、客户访谈、新人培训,录屏堆在飞书 / Zoom / 腾讯会议里
  • 会后助理整理一份纪要,关键细节依然遗漏
  • 三个月后想找一个技术决策的原始上下文,翻遍聊天记录找不到
  • 新人入职面对几十小时的技术分享录屏,无从下手
  • 离职员工带走了他脑子里的"会议记忆"

我们自己的团队就是这样的。当 CTO 问"半年前我们为什么选了 Redis 而不是 Memcached"的时候,五个人花了整整一个下午翻录屏,最后还是靠一个老员工的记忆拼出来的。

那一刻我们意识到:录屏不是资产,能被检索的录屏才是资产。

二、市面上的方案,为什么都不对

我们调研了一圈,发现现有方案都有各自的问题:

  • 飞书 / 钉钉的会议纪要:只能处理自家平台的会议,且纪要是 AI 自动总结的,丢失原话和时间戳
  • Otter.ai / 通用转写工具:单次转写,没有团队知识库概念,不能跨视频检索
  • Notion / 语雀:得人手动整理,整理的成本比开会还高
  • 企业级知识库(Glean / Fireflies):贵,且数据要上传到他们的云上,国内合规过不去

我们需要的是:

  1. 能上传任何来源的音视频(Zoom、腾讯会议、本地录屏都行)
  2. AI 自动转写 + 清洗,不需要人干预
  3. 能跨视频语义检索,输入问题直接定位到原话
  4. 数据完全在自己手里,代码可审计
  5. 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

posted @ 2026-10-14 23:12  谛听AI视频知识库  阅读(5)  评论(0)    收藏  举报