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 +43 -10
- package/dist/index.cjs +6942 -2363
- package/dist/index.d.cts +85 -1
- package/dist/index.d.ts +85 -1
- package/dist/index.js +6942 -2363
- package/package.json +1 -1
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:
|
|
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.
|
|
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/`) —
|
|
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×
|
|
208
|
-
| large | 640×
|
|
209
|
-
| medium | 512×
|
|
210
|
-
| small | 384×
|
|
211
|
-
| xs | 384×
|
|
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
|
-
- [
|
|
254
|
+
- [x] Face landmarks + touch-up
|
|
255
|
+
- [ ] Multi-face support
|
|
256
|
+
- [ ] Auto-reframe
|
|
257
|
+
- [ ] AR effects
|
|
225
258
|
- [ ] Lighting correction
|
|
226
259
|
|
|
227
260
|
|