{
  "lead": "打开摄像头，把每一帧画面实时交给 WASM 做滤镜处理。和「图像滤镜」用的是完全相同的 Rust 函数，只是输入从一张静态图片变成了每秒几十帧的视频流。",
  "formulas": [
    [
      "1 帧 ≈ 33ms",
      "30fps 下每帧的处理预算"
    ]
  ],
  "terms_notes": [
    "5 种滤镜的算法与「图像滤镜」相同：灰度（BT.601 加权亮度）、反色、3×3 均值模糊、Sobel 边缘检测、方向卷积浮雕。区别在于它们必须在一帧的时间（约 33ms）内完成，才能保持画面流畅。"
  ],
  "flow": [
    [
      "js",
      "JS 通过 WebRTC 的 <code>getUserMedia()</code> 请求 320×240 的摄像头视频流，放入隐藏的 <code>&lt;video&gt;</code> 元素。"
    ],
    [
      "js",
      "每当有新的视频帧（<code>requestVideoFrameCallback</code>，不支持时退回 <code>requestAnimationFrame</code>），JS 把这一帧画到左侧 Canvas，再用 <code>getImageData()</code> 取出像素。"
    ],
    [
      "rust",
      "JS 调用 <code>apply_filter()</code>，由 Rust 处理这一帧的像素。"
    ],
    [
      "js",
      "JS 把结果 <code>putImageData()</code> 到右侧 Canvas，并统计 FPS 和每帧耗时。"
    ]
  ],
  "perf": [
    "每帧有 320 × 240 × 4 = 307,200 字节的数据要复制进 WASM、再复制出来。底部的「ms/帧」包含了这部分开销。",
    "摄像头需要安全上下文：通过 <code>http://localhost</code> 访问可以使用，通过局域网 IP 访问则需要 HTTPS。"
  ],
  "src": [
    [
      "crates/media/image-filter/src/lib.rs",
      "与图像滤镜共用"
    ],
    [
      "www/video-filter/index.js",
      ""
    ]
  ]
}
