浏览器端 AI 视频实验:结合目标检测与光流实现群体运动追踪
项目地址:https://github.com/MartinDelophy/ai-video-editor
在线体验:https://video-editor.ai-creator.top/
Timeline Studio 是一个本地优先的浏览器 AI 视频编辑器。最近我们为它开发了一项实验功能:光流追踪。
这项功能不只是计算相邻帧之间的像素变化,而是先识别视频中的人物或物体主体,再在主体区域内计算光流、聚合运动向量并累计轨迹,最终生成一段可以继续放入时间线编辑的视频素材。
本文将介绍这项功能的整体设计、核心算法,以及浏览器端视频处理中的性能与清晰度优化。
一、从“像素变化”升级为“主体运动”
光流描述的是相邻视频帧之间的像素位移。
对于某个采样点,可以使用二维向量表示它的运动:
[
v=(\Delta x,\Delta y)
]
其中:
- (\Delta x) 表示水平方向位移;
- (\Delta y) 表示垂直方向位移。
如果把所有光流向量直接绘制在视频上,可以得到常见的“满屏箭头”效果。但这种效果并不理解视频内容。
例如,以下变化都可能产生光流:
- 摄像机抖动;
- 背景纹理移动;
- 视频字幕发生变化;
- 灯光闪烁;
- 视频压缩噪声;
- 人物衣服和头发的局部变化。
如果直接对全部向量进行聚类,就可能把背景误认为一个运动群体。
所以我们没有从“如何绘制更多向量”开始,而是先解决另一个问题:
这些向量属于谁?
二、整体处理流程
光流追踪被拆分为六个阶段:
读取所选视频片段
↓
检测人物或主要物体
↓
建立大块语义区域
↓
区域内部计算局部光流
↓
聚合群体方向并累计轨迹
↓
编码结果并加入“我的素材”
这套流程有两个重要特点:
- 光流只服务于已经识别的语义主体;
- 分析结果最终会生成视频素材,而不只是停留在临时预览中。
三、先识别人或物,再计算光流
系统会首先从视频的锚点帧中寻找人物或主要物体。
浏览器端依次使用轻量级检测与分割能力:
- NanoDet 用于获取人物和物体候选区域;
- MediaPipe 人物分割用于辅助确认人物主体;
- YOLOS 作为边界明确的检测回退;
- 当模型不可用但主体非常明显时,使用保守的中心语义区域作为降级方案。
这里并不要求视频中一定出现多个人。
一个清晰的人物或者一个主要物体,本身就可以被视为一个有效的语义运动群体。
对于近景视频,人物可能占据接近整个画面。如果沿用过于严格的面积限制,就会把这种正常构图误判为检测失败。因此,我们对近景人物采用了更加宽松的有效区域标准。
四、建立语义运动群体
目标检测通常会返回一个或多个候选区域。系统需要把这些候选区域转换成适合光流传播的“大块群体”。
每个群体包含以下信息:
{
id,
label,
box,
center,
dx,
dy,
confidence,
stability
}
其中:
box是群体在画面中的归一化区域;center是群体中心;dx、dy是当前主要运动向量;confidence表示运动向量可信度;stability表示连续帧之间的轨迹稳定程度。
当画面中有多个相邻人物时,可以按照区域距离和运动一致性进行合并。对于单个人物或主要物体,则保留一个完整的大块区域。
这样得到的结果更接近用户理解中的“这一群人”或者“这个物体”,而不是大量互不关联的像素块。
五、语义区域内部的局部光流
完成主体检测后,系统开始读取连续视频帧,并将分析帧转换为灰度图。
为了寻找图像块在下一帧中的位置,可以在局部搜索窗口内计算匹配误差:
[
E(dx,dy)=\frac{1}{N}\sum_{i=1}^{N}|It(i)-I{t+1}(i+dx,i+dy)|
]
其中:
- (I_t) 表示当前帧;
- (I_{t+1}) 表示下一帧;
- ((dx,dy)) 是候选位移;
- (N) 是图像块中的像素数量。
误差最小的位置会被视为当前图像块的候选运动方向。
为了避免背景和噪声影响,还要继续过滤:
- 位移过小的静止向量;
- 匹配误差过大的向量;
- 超出语义区域的向量;
- 与群体主要方向差异过大的离群向量;
- 置信度不足的局部变化。
最终留下的向量才会参与群体运动计算。
六、聚合群体的主要运动方向
假设一个语义区域内有多个有效向量,可以使用置信度作为权重计算群体平均运动:
[
V_g=\frac{\sum_i c_i v_i}{\sum_i c_i}
]
其中:
- (v_i) 是第 (i) 个局部光流向量;
- (c_i) 是这个向量的置信度;
- (V_g) 是群体的主要运动方向。
除了平均向量,还需要计算向量之间的一致程度。
如果区域内的大部分向量方向接近,说明这个群体运动比较稳定;如果向量方向非常分散,则可能出现遮挡、镜头切换或者识别区域漂移。
因此,最终的实验面板会展示:
- 有效向量数量;
- 运动群体数量;
- 主要运动方向;
- 轨迹稳定度;
- 当前检测模型;
- 已处理帧数;
- 分析进度。
这些指标不仅让界面更有实验感,也方便开发者判断结果是否可信。
七、把瞬时运动累计成轨迹
单帧光流只能说明主体在某个瞬间的移动方向。
为了得到完整运动轨迹,每处理一个采样帧,系统都会更新群体中心:
[
Pt=P{t-1}+V_t
]
新的位置会被加入轨迹点数组:
track.points.push({
x: nextCenterX,
y: nextCenterY,
time: frameTime
});
连续处理后,就可以得到主体从 A 点移动到 B 点的路径。
在结果画面中,我们绘制了:
- 原始视频底图;
- 青色局部光流箭头;
- 不带文字标签的群体区域边界;
- 不同颜色的累计运动轨迹;
- 群体的主方向箭头;
- 右上角动态实验时间码。
我们特意去掉了画面左侧的群体文字标签,因为在人物较大或者画面元素较多时,标签会遮挡主体。群体类型和数量仍然可以在实验数据区域中查看。
八、浏览器端性能优化
浏览器本地视频处理必须平衡计算量、内存占用和输出质量。
如果直接在1080P甚至4K视频上逐帧计算光流,处理时间会明显增加。另一方面,如果直接使用低分辨率分析帧生成最终视频,输出结果又会非常模糊。
因此,我们把处理分成两条路径。
1. 低分辨率分析路径
光流计算使用较小的分析帧:
- 缩小视频画面;
- 转换为灰度图;
- 执行局部块匹配;
- 计算语义区域内的运动向量;
- 累计群体轨迹。
低分辨率足以完成运动分析,同时可以明显减少浏览器CPU和内存压力。
2. 清晰成片路径
生成结果时不放大低分辨率分析帧,而是重新使用清晰的源视频采样帧:
- 保存最高1280像素宽的源视频画面;
- 将分析坐标按比例映射到清晰画面;
- 重新绘制向量、边界和轨迹;
- 写入右上角时间码;
- 使用 WebCodecs 编码成 WebM。
因此,算法可以在192像素宽的画面上计算,但一段852×480的源视频仍然会生成852×480的结果素材。
这种“低分辨率计算、高分辨率合成”的结构,是浏览器视频处理中特别实用的优化方式。
九、使用 WebCodecs 生成结果视频
分析结束后,系统会先把每个采样时刻渲染成结果帧,然后使用 WebCodecs 编码。
简化后的流程如下:
const blob = await encodeFrames(
renderedFrames,
width,
height,
sampleRate,
frameTimes,
duration
);
为了让生成素材进入时间线后能够显示真实画面,还会额外生成一组紧凑的缩略帧:
const trackFrames = await createVideoTrackFramesFromBlobs(
renderedFrames,
{
duration,
width,
height
}
);
最终形成的视频素材结构包含:
{
type: "video",
src,
blob,
duration,
width,
height,
trackFrames,
trackFrameDuration: duration,
generatedBy: "optical-flow-tracking",
diagnostics: {
detector,
sampleRate,
vectors,
cohorts,
dominantAngle,
stability
}
}
分析成功后,新生成的视频会自动加入“我的素材”,但不会直接插入时间线。
这样既方便用户立即查看结果,也不会打乱当前正在编辑的项目结构。
十、一次实际测试
我们使用一段分辨率为852×480、时长约2秒的视频进行了测试,并选择4fps时间采样。
本次分析结果为:
- 9个采样帧;
- 268个有效运动向量;
- 1个主要语义运动群体;
- 主运动方向约235度;
- 轨迹稳定度约78%。
分析完成后,浏览器生成了一段852×480的 WebM 视频,并自动将其添加到“我的素材”。
成片中保留了原始视频清晰度,同时叠加了局部向量、群体边界、累计轨迹和动态时间码。
十一、浏览器本地处理的优势与限制
整个处理过程都在浏览器中完成,包括:
- 视频帧读取;
- 人物和物体检测;
- 人物分割;
- 局部光流计算;
- 群体轨迹聚合;
- 结果视频编码;
- 时间线缩略帧生成。
这种方式的优势是:
- 用户视频不需要上传服务器;
- 减少后端存储和推理成本;
- 不需要等待云端任务队列;
- 参数修改后可以直接重新运行;
- 生成结果能够马上进入视频编辑流程。
但它也存在一些限制:
- 长视频会增加内存压力;
- 高采样率会延长计算时间;
- 快速遮挡可能导致群体身份漂移;
- 镜头切换会破坏连续轨迹;
- 严重运动模糊会降低向量稳定度;
- 不同浏览器的 WebCodecs 和模型运行能力存在差异。
因此,目前更适合把它作为视频编辑器中的实验功能,用于运动可视化、技术演示、教学内容和短视频特效。
十二、总结
这次光流功能开发最重要的改进,并不是增加更多箭头,而是为光流增加了语义边界和完整的产品闭环。
它解决了三个问题:
- 这些运动向量属于哪个人物或物体?
- 这些局部向量能否聚合成可以理解的群体方向和轨迹?
- 分析完成后,结果能否成为真正可复用的视频素材?
最终形成的技术路径是:
语义检测
+
区域光流
+
群体向量聚合
+
轨迹累计
+
清晰成片渲染
+
浏览器视频编码
+
素材库接入
这样,光流就不再是孤立的算法演示,而是成为视频编辑器里可以预览、生成、复用和继续创作的完整能力。
如果你对浏览器端 AI、视频编辑、WebCodecs 或本地模型推理感兴趣,欢迎访问项目仓库: