
Vimpo 博客 · 2026 年 10 月 16 日
Vimpo 为什么没有数据库
两年多前我写过一篇《在 Electron 中使用 SQLite 的最好方式》,那时候做 EpubKit, 需要存数据,我几乎没有犹豫,第一句话就写了「最好的选择是 SQLite」。
这次做 Vimpo, 我没有用 SQLite, 也没有用 Core Data. 准确地说,Vimpo 根本没有数据库。
这个决定的起点是 Obsidian 的 CEO Steph Ango 写的一篇很短的文章 File over app. 文章里有一句话我很喜欢:
Apps are ephemeral, but your files have a chance to last.
App 是短暂的,但你的文件有机会留存下来。
他的意思是,如果你想让自己创造的东西活得久,它们必须是你能掌控的文件,而且是用什么工具都能打开的格式。App 会停更,公司会倒闭,但文件不会因为某个 App 消失就跟着消失。他自己在用 Obsidian 写东西,但他也承认 Obsidian 不会永远存在。
做 Vimpo 的时候,我一直在想这件事。Vimpo 帮你下载视频,在本地把语音转成字幕,再用 AI 翻译成你的语言。最后留下来的东西,才是用户真正在乎的:影片、封面、字幕。那它们应该放在哪里?
资料库就是一个文件夹
第一次打开 Vimpo, 它会让你新建一个资料库,默认建议放在「影片」文件夹里。这个资料库就是一个以 .vimpo 结尾的普通文件夹。不是 bundle, 也没有藏在 ~/Library 的某个角落。你在 Finder 里双击就能进去:
影视库.vimpo/
├── library.json
└── How Film Cameras Work [Xk2pR8vL0aQ]/
├── item.json
├── video.mp4
├── cover.jpg
├── video.en.srt
└── video.zh-Hans.srt每部影片一个文件夹,名字就是影片的标题。里面的东西你用什么 App 都能打开:
video.mp4就是一个普通的 MP4, QuickTime、IINA、VLC 都能直接播放。cover.jpg是封面,一张 JPEG.video.en.srt、video.zh-Hans.srt是字幕,每种语言一个 SRT 文件。不管是 Whisper 在你 Mac 上识别出来的原文,还是 AI 翻译出来的译文,最后都会写成一个 SRT 文件,而不是只存在 App 的缓存里。item.json记录了标题、来源链接、时长、有哪些字幕、你看到了哪里。
没有数据库
Vimpo 的代码里有一句注释:「The files are the library — there is no database.」这不是一句口号,是字面意思。每部影片的 item.json 就是它唯一的记录。
这个 JSON 是排过版的,key 按字母排序,日期是 ISO 8601. 也就是说,它是写给人看的:
{
"cover" : "cover.jpg",
"createdAt" : "2026-10-12T09:41:07Z",
"duration" : 1264,
"id" : "6F1C2A9E-3B7D-4C51-9A0E-2D8B5F47C310",
"lastPlayedAt" : "2026-10-14T21:03:55Z",
"playbackPosition" : 812.4,
"sourceURL" : "https://www.youtube.com/watch?v=Xk2pR8vL0aQ",
"subtitles" : [
{
"fileName" : "video.en.srt",
"isOriginal" : true,
"languageCode" : "en",
"lineCount" : 418,
"origin" : "recognized"
},
{
"fileName" : "video.zh-Hans.srt",
"isOriginal" : false,
"languageCode" : "zh-Hans",
"lineCount" : 418,
"origin" : "translated"
}
],
"title" : "How Film Cameras Work",
"uploader" : "Film Notes",
"video" : "video.mp4"
}里面的文件名都是相对路径,所以整个资料库搬到哪里都能用。除了 id 和 title, 其他字段都是可选的。你甚至可以自己手写一个 item.json, Vimpo 也能读进来。
那为什么不用 SQLite? 我想了一下,用数据库会带来三个问题:
- 离开了 App, 数据库文件对你来说就是一堆看不懂的二进制。
- 放进同步盘的话,一个数据库文件加上 WAL, 很容易同步冲突,甚至损坏。
- 你在 Finder 里拖动、改名都没有意义,因为 App 只认数据库里的记录。
而每部影片一个小小的 JSON 文件,这三个问题都没有。当然,不用数据库是有代价的,每次都要把整个文件夹扫一遍。但一个人的影片库,通常也就几百到几千部,扫一遍的成本很低。真到了扫不动的那天,再加一个 SQLite 索引也不迟。但它只会是一份缓存,随时可以删掉,再从 JSON 重新生成。
你在 Finder 里做的事,Vimpo 都认
既然文件夹就是资料库,那你在 Finder 里做的事情,Vimpo 理应都认。所以每次你切回 Vimpo, 它都会重新扫描一遍资料库:
- 在 Finder 里给影片文件夹改名,它还是同一部影片,播放进度不会丢。
- 改了
item.json里的标题,回到 Vimpo 就能看到新标题。 - 在 Finder 里复制一份影片文件夹,就会多出一部独立的影片。
- 把文件夹删掉,这部影片就从墙上消失了。
- 反过来,在 Vimpo 里删除影片,文件夹会被移到废纸篓,而不是直接抹掉。
这也意味着 Vimpo 不需要做「导出」和「备份」功能。Time Machine 会帮你备份,iCloud 云盘、Dropbox、Syncthing 可以帮你同步。换一台 Mac, 把整个 .vimpo 文件夹拷过去,用「打开资料库」(⌘O)打开就好了。
什么东西不在资料库里
并不是所有东西都放在资料库里。yt-dlp 和 ffmpeg 这些下载工具、Whisper 模型、翻译缓存都放在 ~/Library/Application Support/Vimpo/, API key 放在钥匙串里。
我给自己定的规则很简单:你创造的东西进资料库,App 自己需要的东西留在外面。外面的东西丢了,重新下载、重新生成就好,你不会因此少一部影片、少一行字幕。比如翻译缓存,它只是帮你省点 token 和时间,真正的译文早就写进资料库里的 SRT 了。
另外,Vimpo 没有账号,也没有服务器存你的任何东西。没有账号,就永远不会收到「本服务即将关闭,请在 30 天内导出你的数据」这种邮件 😂
结论
我很清楚,Vimpo 总有一天会过时。可能是我不再维护它,也可能是出现了更好的工具。我希望到了那一天,你打开「影片」文件夹,那些影片、封面和字幕都还在,用任何播放器、任何文本编辑器都能打开,就好像 Vimpo 从来没有存在过一样。
对于一个做 App 的人来说,这听起来有点奇怪。但我觉得,一个 App 能为用户做的最好的事情之一,就是让自己变得可以被替代。