基于 Google 多模态嵌入模型 EmbeddingGemma 2 的 Mac 菜单栏搜索工具,连视频和声音片段都能搜
DigUp 把照片、文档、代码和音视频片段变成可按含义搜索的本地资料,再带你跳到文件里的相关位置。
DigUp 是一款基于 Google 多模态嵌入模型 EmbeddingGemma 2 打造的 Mac 菜单栏搜索工具,可以搜索你选定文件夹里的各种内容,包括照片、文档、代码,以及视频和声音片段。它由开发者 Abdur Rahim 开源:描述你记得的内容,就能在本地找出相关文件,再跳到视频时刻、文档页码或代码段。
Mac 自带的 Spotlight 已能搜索文件名、文档正文和元数据。DigUp 进一步处理照片里的场景、录音里的话题,以及视频中出现的画面,例如:
- 拍过的一段视频,只记得画面里出现过斑马,却想不起文件名;
- 听过的一期播客,依稀记得聊到了睡眠话题,却只能拉动进度条盲猜;
- 签过的一份长篇 PDF 租约合同,不知道宠物条款具体在第几页;
- 本地代码仓库里的一段指数退避重试函数,文件名和函数名里都没有包含
retry。
它基于 Google DeepMind 推出的多模态嵌入模型 EmbeddingGemma 2,(嵌入模型把内容编码成一串可比较的数字,称为向量)在 Mac 本地为图片、截图、PDF、文本文档、音频和视频建立统一的向量表示,实现按文件“包含什么内容”而非“叫什么名字”进行语义检索。
更进一步,DigUp 的定位不只是指出文件本身,而是直接跳转到文件内部的相关位置:将播放器跳到出现相关画面的时间点、将播客定位到对应话题的音频区间、将 PDF 翻到相关条款所在的页码,或在编辑器中定位到相关代码段。所有切片与检索均在 Apple Silicon 本地完成,无需将个人文件上传到外部服务。
为什么一句话能找到照片和录音
要理解 DigUp 的检索逻辑,核心在于其搭载的多模态嵌入模型 EmbeddingGemma 2(由 Google DeepMind 开源,遵循 Apache 2.0 协议)。
一种常见的多模态检索做法是先经过中间文字转换:用语音识别转出台词、用 OCR 提取画面字符,再基于纯文本计算相似度。这种链路依赖文字作为媒介,容易漏掉未被文字标注的信息,例如语音里的语调、背景声响,或是画面中的构图、动作与非文字细节。
EmbeddingGemma 2 走的是原生多模态对齐(Native Multimodality)路线:
- 统一的向量空间:模型总参数量为 740M(包括 270M 文本主干、170M 视觉编码器和 300M 音频编码器)。文本、静态图像、视频抽帧和音频切片均被映射到同一个 768 维向量空间中。
- 跨模态的可比表示:统一空间让文字查询能与图片、音频或视频片段直接计算余弦相似度。应用据此给候选资料排序,再让你查看原文件。
- 任务指令前缀(Task Instruction Prefixes):模型在训练时对不同任务使用了特定文本前缀引导。常规搜索查询使用
task: search result | query: {query};代码意图检索使用task: code retrieval | query: {query};文档内容则包装为title: {title} | text: {content}。前缀帮助文本向量更好地对齐目标检索场景。 - 编码器模块化解耦:视觉编码器和音频编码器相互独立。在仅需要根据输入文本进行匹配的搜索阶段,只需调入文本主干,无需同时加载视觉与音频编码组件。
了解模型按需加载、输入预算与向量压缩之间的取舍。
阅读模型解读 →找到文件以后,怎样跳到对应页和时刻
如果只是把整部视频或几百页的 PDF 整体算成单个向量,检索结果最多只能指出文件本身。DigUp 的实际做法是将不同媒体切分为具备时间戳或位置元数据的片段(Segments),以便直接定位到文件内部。
在 macOS 系统下,DigUp 调用 AVFoundation、PDFKit、Vision 与 ImageIO 框架实现文件解析与特征抽取:
1. 视频切片:关键帧抽样与图像指纹去重
视频是数据量最大的媒体类型。在后台处理时,DigUp 采取了抽样预算与指纹去重策略(见 Media+Apple.swift 源码):
- 抽样步长与帧数预算:抽样步长按
max(3, duration / 1200)秒计算。通常每 3 秒抽取一帧;当视频时长变长时,以最多 1,200 帧作为数量预算动态拉大步长,而不是只截取前 1,200 帧。每帧按 70 个视觉 soft token 的预算进行编码; - 均值哈希(aHash)去重:抽取出的每一帧会缩放至 8×8 灰度图并计算均值哈希。若相邻两帧的汉明距离在 4 位以内(
(hash ^ lastHash).nonzeroBitCount <= 4),表明画面高度近似,DigUp 会跳过该帧编码,仅将前一帧的代表区间向后延伸。它对幻灯片、固定机位等近似画面做去重,决定保留哪些画面代表后面的区间; - 画面与音轨分路处理:视频文件会被拆解为画面与声音两条独立路径。画面进行抽帧编码,音轨则提取后送入音频处理流程,分别支持画面动作搜索与口播台词搜索。
2. 音频切片:滑动窗口与静音切除
在音频处理上,EmbeddingGemma 2 的通用模型卡具备 8,192 token 的上下文窗口,理论上可容纳更长音频;而 DigUp 当前运行路径设定了单输入上限 30 秒(源码注释标明单次输入忽略 30 秒之后的内容):
- 窗口规格:音频统一重采样为 16 kHz 单声道,切分为 30 秒的固定时间片,窗口之间以 25 秒步长滑动(即保留 5 秒重叠)。5 秒重叠让一部分跨边界的语句仍能落在完整窗口内;
- 静音剔除:计算切片的均方根能量(RMS)。若 RMS ≤ 0.003(约低于 -50 dBFS),视作无声或极低底噪环境,直接跳过不生成向量,节省存储空间。
3. PDF 与长文档:两阶段调度与图文混合
面对长篇文档与合同,DigUp 设计了分批读取机制:
- 按页数分流与两阶段调度:源码中设置
bigPDFPages = 50。50 页以内的 PDF 会在首次索引时整份读完;超过 50 页的长 PDF,第一阶段只读取前 30 页,确保大部分文件能快速进入可检索状态,30 页之后的内容则留待后台后续收尾(单文件上限 5,000 页)。普通文本文档也按前 40 块(约 6.4 万字符)优先索引、后续追加的策略处理; - 扫描件图文融合:单页提取文字少于 200 字时(常见于扫描件或幻灯片),DigUp 会将页面渲染为图像调用视觉编码器;同时结合 Apple Vision 进行 OCR,使扫描发票或单据中的编号也能被关键词检索覆盖。
4. 代码项目:独立索引与结构化行段
代码搜索在开启后使用独立的数据库(code.sqlite):
- 行段切片:以完整代码行为单位切分,每段上限控制在约 1,800 字符。源码注释指出,切片过短容易切散函数逻辑,切片过长则容易模糊意图;
- 规则过滤:遵循
.gitignore规则,主动跳过依赖库、测试生成物、密钥和证书。
这种按窗口与抽样帧切分的机制也带来了粒度上的代价:系统定位给出的是命中的时间窗口或抽样帧,并非逐字逐帧的精细锚点;若某些关键画面在视频中仅短暂闪现且恰好落在抽样间隔之间,就存在错过的可能。
按含义找和按原词找,怎样配合
当所有片段的向量存入本地数据库后,如果直接比较一段文本查询与文本、图像、音视频之间的原始余弦相似度,往往会遇到模态间的分布差异。
1. 模态均值校准与标准化得分
在实际检索中,针对同一次输入查询,不同模态(文本、图像、音频)的原始余弦相似度分布可能具有不同的均值水平。若直接按原始相似度混排,均值偏高的模态可能会占据前列,从而掩盖其他模态中真正相关的候选内容。
DigUp 在 Searcher.swift 中采取了模态均值校准(Modality Centering)的处理方案:
- 计算各模态均值:统计当前查询下文本、图像、音频各模态各自的余弦均值。若某个模态的向量数量少于 20 个,则借用全体向量的平均分作为该模态的均值;
- 模态中心化:计算每个片段减去其模态均值后的差值:
中心化差值 = 余弦相似度 − 对应模态的平均值。 - 计算联合标准差与校准得分:计算所有参与定标片段的中心化差值均值,以及跨模态的联合标准差(设 0.02 为下限),最终得出标准化 Z 分数:
Z =(中心化差值 − 定标片段的中心化均值)÷ 联合标准差。 - 突出门槛过滤:设置门槛
zGate = 2.0。该分数衡量的是某个片段偏离其模态平均水平的标准差程度,用于判断其是否在所属模态中相对突出,而非直接等同于相关概率或检索准确率。使用各模态共同的联合标准差,可以避免样本分布较窄的模态被过度放大。
2. 精确匹配补充:为什么需要 FTS5 全文搜索?
嵌入模型擅长理解自然语言意图,但向量表示无法可靠保留逐字符的代码、编号或发票单号。
因此,DigUp 采用了双轨混合检索结构:
- 语义轨(Meaning):依托 EmbeddingGemma 2 的向量相似度与模态校准得分;
- 精确轨(Words):依托 SQLite 原生 FTS5 全文检索模块,对文件名、目录路径、文档文字与 OCR 提取字符进行词干提取与归一化检索。
系统根据查询词特征动态平衡两轨比重:
- 常规搜索:以语义向量得分为主导,关键词命中提供额外加分;
- 特殊编号查找(Lookup):源码中的
isLookup判定要求查询中的所有有效词项均包含数字,且要么包含字母、要么数字长度达到 4 位及以上。例如输入单纯的订单编号4815162342或代码K7Q2LM时,会触发此模式,系统将关键词权重提升一倍,并将语义向量权重减半;但如果输入包含常规词汇的组合(如invoice 4815162342,由于invoice并非停用词且不含数字),则不会触发该特殊权重; - 代码权重调优:在代码搜索中,像
app、get、running等高频词汇在源文件中极为普遍,因此代码检索下的关键词权重被设为 1.0(常规搜索为 2.0),防止浅层词频重合干扰真实意图。
切换下面的查询例子,可以看到它进入哪个索引,以及含义与原词如何参与检索:
换一种查询,看检索怎样走
输入含义由模型编码,具体编号交给关键词匹配。切换查询,可以看到两条通道如何配合。
zebra in a videoEmbeddingGemma 2 → 向量比较
把查询和视频抽样画面放进同一 768 维空间,比较它们的语义相似度。
语义权重 1关键词 → FTS5 全文索引
在文件名、正文及 OCR 文字中查原词,为语义匹配补充线索。
关键词权重 2Masai Mara - day 2.mp4
返回含斑马的相关画面位置,打开后从该处查看。
视频索引默认约每 3 秒抽样并去重;定位依据是抽样画面和保存的时间。
作者演示中,四种搜索各自返回什么
在开发者 Abdur Rahim 公开(并由 Google Gemma 官方账号转发推荐)的实机演示中,呈现了典型的工作流交互:
依次呈现视频内斑马画面定位、播客内睡眠片段、租约合同条款、多语言照片以及 Zed 编辑器打开代码段的过程(约 60 秒)。 下载中英双语字幕视频 · 查看原视频
案例 1:视频画面定位(zebra in a video)
在搜索框键入 zebra in a video,候选列表命中名为 Masai Mara - day 2.mp4 的视频,并给出时间标记。
- 直接动作:按回车键打开后,调用 QuickTime Player 并跳转至包含斑马画面的相关播放位置;
- 权限机制:由于 macOS 的自动化控制权限要求,应用首次控制 QuickTime Player 时会弹出系统确认对话框,允许后即可直接控制播放器跳转。
案例 2:播客对话定位(where they talk about sleep)
键入 where they talk about sleep 后,搜索列表命中音频文件 The Long Run - Ep 14.mp3。
匹配结果直接给出 7:55 的时刻标记,并在右侧预览面板中显示“playing from 7:55”。
案例 3:长篇 PDF 条款定位(the clause about pets in the lease)
检索长租合同中的宠物规定,系统从合同 Lease - 14 Elm Street.pdf 中定位至第 4 页。
预览直接显示第 4 页,并联动系统预览(Preview)的搜索框对查询关键词进行高亮标注。
案例 4:代码意图检索(code: retry with backoff)
当输入以 code: 前缀开头时,DigUp 针对配置的代码目录进行检索。
演示结果呈现了 retry.ts(第 1–47 行)代码范围与 retry.py,右侧提供“Open in Zed”快捷入口,点击即可在编辑器中打开对应代码段。
在代码检索逻辑中,意图搜索返回的是相关的代码段(stretches of lines);只有当用户输入确切的符号名称或标识符时,系统才会尝试定位到具体的定义行。除了 Zed,DigUp 还支持 VS Code、Cursor、Xcode、Sublime Text 与 JetBrains 系列等编辑器。
多语言与中文支持情况
- 跨语言语义能力:EmbeddingGemma 2 预训练覆盖 100 多种语言,但各语言之间的表现并不完全一致;项目自身的评估集目前主要测试了英语、孟加拉语和阿拉伯语。正文中所附的中文查询示例为面向中文读者的译写参考,并非项目原有的测试用例;
- 关键词与文字识别:在 FTS5 关键词层,SQLite 默认分词器对中文、日文、泰文等非空格分词语言不会按词切开;对于截图与图片中的文字识别,能力取决于 Apple Vision 框架(支持约 25 种语言);
- 输入法体验改进:在 0.6.1 版本中,开发者修复了中文、日文、韩文等复合输入法(IME)在搜索框中键入拼音组合时字符被打散的问题,使输入过程保持连续。
资料留在本地,计算和存储怎么安排
在本地资源占用和系统架构设计上,DigUp 没有依赖外部守护进程或独立的专业向量数据库:
- 单文件本地存储与向量开销:
DigUp 将文件记录、切片元数据和 768 维
float16向量统一保存在一个本地 SQLite 文件中。以两万个向量片段为例,原始向量数据本身大约占用 30MB(仅为纯向量存储大小,不含其他元数据和主程序运行开销)。搜索时将这部分向量载入内存直接做矩阵点积比对,无需维护庞大的向量数据库服务。 - 助手进程执行完即退出: 重负荷的文件扫描与 GPU 向量编码由独立的 Helper 进程执行,借助 llama.cpp 的 Metal 后端调用 Mac GPU。当待处理队列完成后,该助手进程会主动退出并释放占用的计算资源;而在用户触发搜索时,主程序才会按需加载文本查询编码部分(README 估计约 250MB 内存),平时仅保留菜单栏常驻。
- 选哪些文件夹,就读哪些资料:
DigUp 仅在用户选定的文件夹范围内读取文件,不修改、不移动原文件,也不上传所索引的内容。在扫描过程中,它会自动跳过密钥、证书、密码文件、隐藏目录(如
~/.ssh)、应用包体与缓存,并跳过类似数据集的目录;对于保存在 iCloud 且未下载到本地的云端占位文件,DigUp 不会触发自动下载。网络请求仅用于初次拉取模型权重(约 865MB)以及每日版本更新检查(可在设置中关闭),不包含任何账户体系或使用遥测。应用采用 MIT 协议开源,底层模型采用 Apache 2.0 协议,Windows 与 Linux 版本目前尚在计划中。
在自己的 Mac 上走通一次
持有 Apple Silicon Mac(M 系列芯片,macOS 14 及以上系统)的用户可以按以下路径上手体验:
第一步:获取与安装
- Homebrew Cask 安装(需系统已安装 Homebrew,在终端执行):
brew install --cask arahim3/tap/digup - 手动 DMG 下载:前往项目的 Releases 页面 下载经签名的
DigUp-0.6.1.dmg,打开 DMG 后将 DigUp 拖入 Applications 应用程序目录。
第二步:模型下载与本地导入
- 启动 DigUp 后,它会驻留在菜单栏中;
- 首次启动会自动下载 EmbeddingGemma 2 模型权重(约 865MB,其中文本主干约 310MB,音视觉编码器约 555MB);
手动导入模型: 若本地网络直接下载受阻,可在 Settings → Storage 中点击 Use Files… 手动指定模型文件。所需文件为 ggml-org 维护的 Q8_0 量化权重:
embeddinggemma-2-Q8_0.gguf与mmproj-embeddinggemma-2-Q8_0.gguf,可前往 Hugging Face 官方仓库入口 ggml-org/embeddinggemma-2-GGUF(固定版本 commit 为bfcd298762cc34d0357ece5ebdd31791a3a374d8)下载对应的两个文件,选定后 DigUp 校验通过即可使用。
第三步:配置扫描目录与索引策略
在 DigUp 应用自身的 Settings 窗口中勾选需要索引的文件夹:
- 首次体验建议:建议先选定一个文件数量较少的小型本地文件夹,观察菜单栏进度,待索引完成后再进行搜索尝试;
- 耗时预期:几百个常见文件的初次索引通常只需几分钟,而对于庞大的“下载”等目录,README 明确指出首次扫描可能需要一小时左右;
- 低电量与供电选项:当 Mac 开启“低电量模式”时后台索引会自动暂停,退出低电量模式后恢复;是否必须在连接电源时才进行索引则为单独的设置开关;
- 定时索引:若不希望白天占用系统能耗,可在 Settings → Folders 中开启定时索引(默认设为凌晨 1:00 至 7:00 执行)。
第四步:常用全局快捷键
| 快捷键 | 用法 |
|---|---|
| ⇧⌘Space | 打开搜索面板,快捷键可在 Settings 中修改 |
| ↑ / ↓ | 选择结果,查看对应预览 |
| ↩ | 打开结果中的页码、时刻或代码行段 |
| Space | 选中结果后用 Quick Look 查看 |
| ⌘↩ | 在 Finder 中显示文件 |
| ⌘C | 复制文件 |
| ⌘O | 在较大的窗口中浏览同一搜索结果与筛选器 |
第五步:复制一种查询,查看命中的原文件
搜索时只需使用一种语言表达意图(支持英文或中文),前提是选定的检索目录中包含对应内容:
以下英文来自项目示例,中文为译写参考,选一种输入即可:
视频画面
zebra in a video
有斑马出现的视频
播客话题
where they talk about sleep
讨论睡眠的那段录音
PDF 条款
the clause about pets in the lease
租约中关于宠物的条款
代码意图
code: retry a failed call with backoff
code: 调用失败后按退避策略重试
先开启代码搜索: 代码搜索默认处于关闭状态。若需搜索代码,先在 Settings → Code 中添加目标代码仓库、开启功能并指定偏好的代码编辑器(如 Zed、VS Code、Cursor、Xcode 等),随后在搜索框以
code:前缀开始检索。建议先在右侧面板查阅代码段预览再按回车打开;若未检索到预期结果,可检查目标目录是否已建立索引完毕、文件是否为云端未下载占位,并适当微调描述词。
文件名忘了,内容还能成为入口
DigUp 扩展了本地资料的检索入口:让照片画面、视频镜头、长录音片段、复杂文档条款以及代码逻辑,都能通过自然语言被直接检索并定位到具体位置。在完全依靠本地芯片算力、不上传个人隐私的前提下,它为 Mac 上的多媒体资产检索提供了一种轻量且实用的新路径。
基于 Google 多模态嵌入模型 EmbeddingGemma 2 的 Mac 菜单栏搜索工具,连视频和声音片段都能搜
忘了文件名,却记得视频里有斑马、播客聊过睡眠,或者租约里有宠物条款?DigUp 让这些内容线索成为搜索入口。它由 Abdur Rahim 开发,使用 Google DeepMind 的 EmbeddingGemma 2 模型。
一句话,怎样连到文件里的那一段?
模型把文字、图片与声音编码为可比较的向量。文字查询与多媒体片段进入同一个空间,就能按内容相似程度找候选;视频与录音不必先全部转成文字才能搜索。
位置从哪里来?在建索引时先切开文件
这些位置来自抽样与切片,因此不是逐字逐帧的精确锚点。
模糊记忆与精确编号,各有一条路
4815162342。全文索引补充文件名、路径、文档及 OCR 文字的字面匹配,避免只靠向量记住字符串。不同媒体的原始相似度分布可能不同。DigUp 先减去各模态均值,再用联合标准差定标,让候选按“相对同类有多突出”参与比较;这类分数不等于相关概率。
资料留在 Mac,第一次需要建立索引
DigUp 只读取你选定的文件夹,文件内容不上传。切片、向量和位置记录存入本地 SQLite;后台 Helper 使用 Mac GPU 编码,队列完成后退出。搜索时按需加载文本查询部分。
首次需下载约 865MB 模型权重,也可手动导入。每日更新检查可关闭;未下载的 iCloud 占位文件会跳过。
先用一个小文件夹,走通第一次搜索
- 确认条件:Apple Silicon Mac,macOS 14 或更高版本。安装 DigUp,完成模型下载。
- 等待索引:在 Settings 选一个小型本地文件夹;确认进度完成后再试查询,大目录首次索引可能更久。
- 输入线索:按 ⇧⌘Space 打开搜索,例如输入
zebra in a video;选中结果后按回车,查看原文件的位置。 - 搜索代码:先在 Settings → Code 添加仓库并开启功能,再输入
code: retry with backoff。
中文描述可以尝试,但项目主要评估了英语、孟加拉语和阿拉伯语,语言效果并不相同;中文关键词分词也有局限。先用自己的资料确认实际命中效果。
What if Spotlight actually understood the meaning inside your files?
DigUp is an open-source macOS menu bar app powered by EmbeddingGemma 2 that brings 100% local, multimodal semantic search to your Mac.
Instead of searching for file names, you can use natural language to:
📸 Find specific scenes in your photos ⏳ Jump to the exact timestamp in audio or video 💻 Search through your codebase by intent
Everything runs locally in a single vector space.
