longpipe 0.0.12 → 0.0.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -33,6 +33,7 @@ const inputStream = await navigator.mediaDevices.getUserMedia({ video: true, aud
33
33
 
34
34
  const pipeline = new EffectsPipeline(inputStream, {
35
35
  background: 'blur',
36
+ audio: 'denoise'
36
37
  })
37
38
 
38
39
  videoEl.srcObject = pipeline.stream // available immediately
@@ -98,13 +99,13 @@ new EffectsPipeline(stream, { preset: 'balanced' }) // medium model
98
99
  new EffectsPipeline(stream, { preset: 'quality' }) // xl model
99
100
  ```
100
101
 
101
- `'auto'` runs a microbenchmark at init and picks the largest preset that fits the per-frame budget on the current device. While `'auto'` is in effect an adaptive controller polls FPS / model time and swaps preset up or down as conditions change. Explicit preset choices (`'fast'`, `'balanced'`, `'quality'`, or a manual config) are always respected and never auto-overridden.
102
+ `'auto'` runs a microbenchmark at init and picks the largest preset that fits the per-frame budget on the current device, **topping out at `large`** — `xl` is the explicit opt-in flagship (`'quality'` or a manual config). While `'auto'` is in effect an adaptive controller polls FPS / model time and swaps preset up or down as conditions change. Explicit preset choices (`'fast'`, `'balanced'`, `'quality'`, or a manual config) are always respected and never auto-overridden.
102
103
 
103
104
  You can also pass a manual config:
104
105
 
105
106
  ```ts
106
107
  new EffectsPipeline(stream, {
107
- preset: { model: 'large', dtype: 'f32', resolution: { w: 640, h: 360 }, skipFrames: 0 },
108
+ preset: { model: 'large', dtype: 'f32', resolution: { w: 640, h: 400 }, skipFrames: 0 },
108
109
  })
109
110
  ```
110
111
 
@@ -177,7 +178,7 @@ pipeline.destroy()
177
178
 
178
179
  ## Self-hosting weights
179
180
 
180
- By default Longpipe fetches model weights from `https://cdn.longpipe.dev/models/v/0.0.4/`. You can browse the available files, sizes, and SHA-256 hashes at [cdn.longpipe.dev/models/v/0.0.4/index.html](https://cdn.longpipe.dev/models/v/0.0.4/index.html) (machine-readable list at [manifest.json](https://cdn.longpipe.dev/models/v/0.0.4/manifest.json)).
181
+ By default Longpipe fetches model weights from `https://cdn.longpipe.dev/models/v/0.0.5/`. You can browse the available files, sizes, and SHA-256 hashes at [cdn.longpipe.dev/models/v/0.0.5/index.html](https://cdn.longpipe.dev/models/v/0.0.5/index.html) (machine-readable list at [manifest.json](https://cdn.longpipe.dev/models/v/0.0.5/manifest.json)).
181
182
 
182
183
  To serve them yourself, mirror the files under any base URL with the same `model_${name}.bin` naming convention and pass it via `weightsBaseUrl`:
183
184
 
@@ -193,22 +194,51 @@ Works on Chromium (Chrome, Edge), Firefox, and Safari (desktop and iOS). WebGPU
193
194
 
194
195
 
195
196
 
197
+ ## Face touch-up
198
+
199
+ UV-space skin smoothing (the "beautify" filter). It runs **in parallel with any background effect** — both features share one encoder pass per frame, and the retouched frame feeds the background compositor.
200
+
201
+ ```ts
202
+ new EffectsPipeline(stream, {
203
+ background: 'blur',
204
+ touchup: { strength: 0.6 }, // presence enables it
205
+ })
206
+
207
+ await pipeline.setTouchup({ strength: 0.8, style: 'bilateral' }) // live update
208
+ await pipeline.setTouchup(null) // disable
209
+ ```
210
+
211
+ ```ts
212
+ interface TouchupOptions {
213
+ strength?: number // 0..1 — blend of smoothed skin over original (default 0.6)
214
+ amount?: number // smoothing radius (default 8)
215
+ detail?: number // high-frequency (pore texture) keep — freq-sep only (default 0.35)
216
+ style?: 'freq-sep' | 'bilateral' // default 'freq-sep'
217
+ }
218
+ ```
219
+
220
+ How it works: a 5-point face-keypoint head rides the matting encoder (no second encoder pass); its heatmaps are decoded on the GPU into a face box; a 478-point landmark model runs on the face crop; the face is unwrapped into a pose-independent UV atlas, smoothed there, and composited back through a per-region weight mask. Eyes, brows, and lips are protected and stay pixel-exact; `'freq-sep'` smooths while keeping pore-level texture, `'bilateral'` is a stronger edge-preserving filter. The whole chain is GPU-resident — no per-frame readback.
221
+
222
+ On first enable the landmark weights (`model_landmark_mesh.bin`, ~2.6 MB) and two small static assets are fetched from `weightsBaseUrl`, then cached; parameter updates are instant. With no face in frame the effect passes through cleanly.
223
+
224
+ Current limitation: single face — with multiple people in frame, detection can jump between faces. Multi-face support is on the roadmap.
225
+
196
226
  ## How it works
197
227
 
198
228
  Two layers:
199
229
 
200
- - **Model** (`src/model/`) — an EfficientNet-Lite encoder (lite0; lite4 on the `xl` tier) with a U-Net decoder, plus a lightweight U-Net *wrapper* that sharpens the matte at higher resolution and a temporal ConvGRU that smooths it across frames. Written as TypeScript op classes — each layer is a class; weights load as binary tensors at init; the backend (WebGPU or WebGL2) is injected at construction. BatchNorm is fused into conv weights at export — there is no BN op at inference.
230
+ - **Model** (`src/model/`) — a shared EfficientNet-Lite encoder (lite0; lite3 on the `xl` tier) feeding multiple heads: a U-Net matting decoder (sharpened at higher resolution by a lightweight U-Net *wrapper*), a 5-point face-keypoint head (drives touch-up, and auto-reframe later), and a small optical-flow head that provides temporal stability — the renderer warps the previous outputs along the predicted flow and blends them through a flow-gated stabilizer, so the matte is steady without any recurrent state in the network. A separate 478-point landmark model runs on the detected face crop. Written as TypeScript op classes — each layer is a class; weights load as binary tensors at init; the backend (WebGPU or WebGL2) is injected at construction. BatchNorm is fused into conv weights at export — there is no BN op at inference.
201
231
  - **Pipeline** (`src/pipeline/`) — capability detection, per-browser frame transport selection, worker spawn, audio passthrough, autotune, and the adaptive controller. Designed to absorb the browser/codec/canvas plumbing complexity so consumers don't have to.
202
232
 
203
233
  Five trained presets cover the hardware range. "Resolution" is the model's working (canvas) resolution; the encoder runs at a lower internal resolution and the U-Net wrapper refines back up to this.
204
234
 
205
235
  | Preset | Resolution | Encoder | Decoder | Skip frames |
206
236
  |--------|------------|--------------|----------|-------------|
207
- | xl | 1280×720 | full (lite4) | 2× ch | 0 |
208
- | large | 640×360 | full (lite0) | standard | 0 |
209
- | medium | 512×288 | full (lite0) | standard | 1 |
210
- | small | 384×216 | small | standard | 1 |
211
- | xs | 384×216 | small | standard | 2 |
237
+ | xl | 1280×768 | full (lite3) | 2× ch | 0 |
238
+ | large | 640×400 | full (lite0) | standard | 0 |
239
+ | medium | 512×320 | full (lite0) | standard | 1 |
240
+ | small | 384×224 | small | standard | 1 |
241
+ | xs | 384×240 | small | standard | 2 |
212
242
 
213
243
  `Skip frames` is how many input frames the model sits out between runs — the compositor still renders every frame using the most recent alpha matte. Autotune picks one of these at init based on a microbenchmark of the actual network on the actual device.
214
244
 
@@ -221,7 +251,10 @@ Training scripts, fixture generation, and the weight export pipeline are not yet
221
251
 
222
252
  - [x] Background segmentation / virtual backgrounds
223
253
  - [x] Background noise removal (audio, separate pipeline)
224
- - [ ] Face Landmarks / Touchup / AR Effects
254
+ - [x] Face landmarks + touch-up
255
+ - [ ] Multi-face support
256
+ - [ ] Auto-reframe
257
+ - [ ] AR effects
225
258
  - [ ] Lighting correction
226
259
 
227
260