全球有数不清的卡拉OK应用,但每到朋友聚会的夜晚,大家还是会不自觉地打开视频网站来放伴奏。同一台设备上,一个人搜索,一个人误触播放,再一个人不停地问“下一首是什么”——排队全靠嗓子喊,控制权像击鼓传花。VKara 做的事很简单:把电视或笔记本变成纯粹的播放大屏,每个人的手机则靠一个4位房间码或二维码,同时登录同一个房间,搜索、点歌、暂停、切歌全在各自掌心完成。它没打算替代视频平台,只是补上了多人协同点歌这个缺口。

这个产品的初版诞生在2025年初。作者坦率地说,自己的需求非常个人:就是想跟朋友在家唱得痛快一点。最开始的方案只是个功能跑通了的原型,验证了可行性,但完全不敢拿去真实的卡拉OK之夜用。用他自己的话说,叫“危险的能用”。界面在跳动,视频有时会跳过搜索步骤直接播放,歌曲队列说乱就乱。而最致命的地方在于,VKara本质上是一个实时同步的应用,前端与后端必须在房间状态、队列数据、视频元信息、播放指令和 WebSocket 消息上保持一套一致的契约。当这些契约分散在不同仓库里各自演进时,每做一次修改都像在踩地雷。于是项目被搁置了——不是点子不行,是改动成本高到让人不敢下手。

打开网易新闻 查看精彩图片

今年重新捡起项目时,他没有急着加功能,而是先问自己一个问题:怎么才能让这个项目“可以安全地改动”?答案的第一步,就是把旧的前端仓库和旧的后端仓库合并成一个 Bun 工作区单体仓库(monorepo)。apps/web 是 Next.js 的前端,apps/api 是基于 Elysia 和 WebSocket 的后端,packages/shared‑types 存放共享的 API 与 WebSocket 合约,packages/shared‑utils 放公共辅助函数。这不是一次简单的文件整理,它直接改变了后续所有工作的节奏。

在那个散乱的旧结构里,前端和后端对“一个房间该是什么样子”的认知很容易出现偏差。现在,只要在 shared‑types 里定好一个接口,修改会同时传导到前后端,类型检查器会立刻叫停任何不一致。共享工具函数也把解析房间码、格式化时间这类反复用到的逻辑收拢在一起,不再需要手动比对两端是否写了同一段正则。对实时应用来说,这种契约的集中存放就像把散落各处的乐谱合成了一本总谱——每个部件该在什么时候发出什么信号,一目了然。正因为改动变得安全了,那些搁置已久的真正产品问题才开始被逐个解决。

原先的版本让人感觉是在一个视频播放器外头硬套了一层点歌流程:界面重心还在视频本身,移动端的操作路径又长又容易误触。重写后的移动端流程把“加入房间”“搜索歌曲”“选择执行动作”和“控制播放”变成了四个清晰的步骤,并且页面只围绕这几个核心行为来设计。手机不再是一个投影遥控的小屏,它就是每个参与者的专属点歌台。这个产品上的转向,归根结底是工程架构转向后才得以执行的——如果每一次调整播放指令的 WebSocket 消息结构都还要在两个仓库间小心翼翼地手动同步,这样的体验优化可能永远无法落地。

现在 VKara 的演示环境跑在非常有限的资源上,作者特意提醒如果加载慢请稍微等一下,因为钱包还停留在学生预算级别。但它的运转逻辑已经非常直白:一台播放设备负责渲染视频画面,其他人的手机通过浏览器加入房间,每个人都能独立搜索、队列管理、控制播放,而所有状态都实时同步在所有人的屏幕上。那个曾经让人在聚会里不得不交出遥控器的场景,现在被拆解成了一个不需要安装任何应用的纯网页协作流程。从一套危险的、不敢上场的原型,到一个能安全迭代、能明确产品边界的工具,变化背后并不是某个单一功能的增添,而是整个工程世界的重构,让原先卡在理想与现实之间的点子,终于可以稳稳地走到下一个朋友聚会的客厅里。