把手机支在2.5到3米外,低一点、镜头朝上,整个人进画面。点一下开摄像头,然后双手举过头顶,屏幕上出现"举手菜单",手腕变成黄色圆环,悬停1.5秒就算按下按钮。接下来,它放音乐,看着你跳。

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

跳完30秒,屏幕上跳出一个百分制分数,外加一条下次要改的建议。这就是Step Up!,一个判断你跳萨尔萨时脚步有没有踩在拍子上的网页应用。

它教给开发者的第一件事,是关于他自己的。在录下的每一次练习里,他的脚步都晚了一拍——他踩的是2、3、4,而不是1、2、3。他一直这么跳,自己没察觉,家里也没人会告诉他。

这正是它想解决的问题。在课堂上,老师能告诉你跑拍了;一个人在家练,你听不出自己脚下的问题,同一个错误可以练上好几周。

它到底怎么打分

应用会放音乐:内置的牛铃、克拉维和康加节奏,一支带钢琴和贝斯的萨尔萨乐队,或者三首真实歌曲,速度在140到200 BPM之间。全程不用碰手机,举手就能操作。

打分看四项:速度对不对、停顿长度(4拍和8拍上有没有停住)、起拍时机(基本步是不是从1开始)、以及每一步是否落在节拍前后80毫秒以内——拖了还是抢了,它都分得清。

它还会画出你"典型的基本步":把你跳过的每个基本步取平均,画成六个点,绿、黄、红三色。点一下分数,就能看到它对应在哪几个点上。完整分析会逐项拆开讲,每个框最后都落到一件具体要做的事上。它会把你的123和567分开对比,把4拍和8拍的停顿分别展示。每次练习都存在你自己设备的浏览器里,配一张"分数随时间变化"的图。

开发者自己跑完一次的结果是:速度和停顿都对,但还是晚了一拍。

33个点到"第5步晚了120毫秒"

核心的开源AI是谷歌的MediaPipe Pose Landmarker,用lite模型在浏览器里跑,靠手机自己的GPU,在每一帧里找出身上的33个点。他只用到髋、膝、踝。其余部分是纯JavaScript和Web Audio API。

从"33个点"走到"你第5步晚了120毫秒",中间有四道坎:

  1. 两个时钟。音乐走音频时钟,摄像头走视频时钟,两者并不一致。差50毫秒,每一步看起来就都偏50毫秒,而这恰好是他要测量的误差量级。解法是给每帧从requestVideoFrameCallback取时间戳,再用AudioContext.getOutputTimestamp()把每个节拍挪到同一个时钟上。验证方法很土:原地跟着咔哒声踏步,检测器在80步里找到78步,中位数是节拍后6毫秒。
  2. 什么算一步。萨尔萨的步子很小,2拍和6拍上几乎只是重心变化。他对每只脚测量脚踝高出静止位置多少,再除以腿长,这样站得远近都不影响。开头3秒的"动作校准"(站着别动)测出静止时点的抖动幅度,据此定下脚要抬多高才算一步。计时点取脚落回峰值高度一半的瞬间——因为算数的是重心落地,不是脚抬到最高。
  3. 蓝牙。蓝牙耳机和音箱的声音会晚150到200毫秒,浏览器并不知道。这会让每一步看起来都偏晚,哪怕跳得完美。所以有个音频校准:跟着16下咔哒声踏步,应用取中位间隔,之后一直补偿。换新设备时,举手菜单上的"完整校准"按钮会先跑动作校准再跑音频校准,没做之前它一直是黄色高亮,写着"先做这个"。
  4. 分数之间要自洽。第一版结果页满是百分比和图表,数字有时互相打架。现在一切都来自"典型基本步",也就是六个步点的平均位置。文字、分数和颜色都出自这一个基本步,所以绿色格子永远不会说"太短"。建议取第一个没达标的项,于是一个晚一拍的舞者会先被告知"从1开始"。

踩过的坑

一个碰不到的菜单必须保持安静。你离手机3米远,举手菜单原本会在屏幕上打出大红字"退后,我看不到你的脚",还念出来。现在"看不到你"和"看不到你的脚"只是角落里的小字提示,按钮则始终保持在屏幕底部往上一个按钮高度的地方。

模型需要你的脸。他试过用低机位只拍腿,结果模型找不到他了——MediaPipe的检测器是靠脸来定位身体的。解法是低机位、镜头朝上、从头到脚都在画面里。

光线决定一切。有一次深夜练习一分没得,因为摄像头在昏暗房间里把帧率砍了一半(16fps掉到约8fps),短促的步子掉进了帧与帧之间。把主灯打开就正常了。

音乐方面,内置节奏和乐队是用Web Audio一个音符一个音符生成的;三首歌来自Free Music Archive的CC授权曲目。现场乐队的速度会轻微漂移,所以他用节拍追踪找出每首歌每个节拍的时间点,应用按这些真实节拍时间给你打分。

为什么要在浏览器里跑

隐私。这个应用拍的是人在自家客厅跳舞。MediaPipe在浏览器里跑,视频从不离开手机,没有东西可上传,也就没有东西可泄露。

成本。闭源视觉API按帧收费,一秒15到30帧,一次30秒的练习最多就是900次调用,而勤快的学习者一天要练好几次。本地推理每次练习零成本,这是便宜甚至免费版本能存在的前提。

速度和离线。没有网络往返,每帧到达就处理;页面和模型加载完之后,一次练习不需要联网。

还有一点:他能看懂它是怎么工作的。MediaPipe的模型和文档是开放的,所以他才查得出"只拍腿就丢人"的原因——检测器建立在人脸检测之上。换成黑盒API,他只能靠猜。

整条链路都是开放的:音乐是CC授权,应用是MIT协议。一个舞蹈老师想换速度、换风格、换自己的数拍方式,直接fork就行。

整个应用就是一个index.html文件,没有构建步骤,没有服务器,没有账号。开发者用三天时间、以Claude Code作为编码助手做完,他负责决定应用做什么、长什么样,每个版本都亲自在手机和笔记本前跳一遍测试。所有改动都以带预览链接的拉取请求形式提交,合并前他自己试过,一共46个拉取请求。

想试的话,把手机或笔记本支在2.5到3米外,低机位朝上,全身入画,灯打开。点摄像头按钮,双手举过头顶打开菜单,先选"完整校准"(站住不动,再跟着16下咔哒声踏步),然后开始。跳30秒基本步,看分数。