@maravilla-labs/platform 0.16.0 → 0.17.0
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/CHANGELOG.md +18 -0
- package/dist/config.d.ts +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +34 -6
- package/dist/index.js.map +1 -1
- package/dist/{transforms-DkAlUPu6.d.ts → transforms-C2zafn5k.d.ts} +52 -18
- package/package.json +1 -1
- package/src/transforms.ts +88 -25
- package/tests/focal-css.test.ts +52 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# @maravilla-labs/platform
|
|
2
2
|
|
|
3
|
+
## 0.17.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 16d4f8d: Extend `resize({ crop: 'focal' })` framing with three more opt-in knobs (on top
|
|
8
|
+
of the initial `zoom` factor):
|
|
9
|
+
- **`zoom`** now also accepts values `< 1` (crop _into_ the subject) and
|
|
10
|
+
`'auto'` (a curated, consistent occupancy); range is `0.4..=100.0` | `'auto'`.
|
|
11
|
+
- **`padding`** — margin around the subject box (`0.0..=2.0`, fraction per side)
|
|
12
|
+
so a tight crop keeps breathing room around the head.
|
|
13
|
+
- **`subject`** — `'union'` (all faces, default) or `'primary'` (the
|
|
14
|
+
highest-confidence face, re-centred on it), so a group photo can crop to one
|
|
15
|
+
person.
|
|
16
|
+
|
|
17
|
+
Still fully backward compatible: the new fields never serialize when omitted, so
|
|
18
|
+
existing derived keys are byte-identical. The SDK CSS helpers gain the same
|
|
19
|
+
knobs plus a new `primaryFaceBox()` for parity.
|
|
20
|
+
|
|
3
21
|
## 0.16.0
|
|
4
22
|
|
|
5
23
|
### Minor Changes
|
package/dist/config.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { T as TransformsConfig } from './transforms-
|
|
2
|
-
export { a as TransformsPatternSpec } from './transforms-
|
|
1
|
+
import { T as TransformsConfig } from './transforms-C2zafn5k.js';
|
|
2
|
+
export { a as TransformsPatternSpec } from './transforms-C2zafn5k.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* @fileoverview Typed schema for `maravilla.config.{ts,yaml,json}` files.
|
package/dist/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export { ActAsContext, AddCircleMemberOptions, AddRelationOptions, ApiKeyInfo, A
|
|
|
3
3
|
export { b as RenClient, a as RenClientOptions, R as RenEvent, g as getOrCreateClientId, r as renFetch, c as storageDelete, s as storageUpload } from './ren-DetHRhCL.js';
|
|
4
4
|
import { LocalParticipant } from 'livekit-client';
|
|
5
5
|
export { RegisterPushOptions, RegisterPushResult, offsetBefore, registerPush, unregisterPush } from './push.js';
|
|
6
|
-
export { D as DetachAudioOpts, e as DetectFacesOpts, l as DocConvertOpts, i as DocFormat, q as DocInsertQrCodeOpts, p as DocReplaceImagesOpts, s as DocTemplateMergeOpts, k as DocThumbnailOpts, n as DocToHtmlOpts, m as DocToMarkdownOpts, j as DocToPdfOpts, d as ExtractAudioOpts, E as ExtractFramesOpts, g as FaceBox, z as FocalCssFrame, y as FocalCssFrameInput, f as FocalPoint, h as FocalPointRecord, F as FramesetManifest, I as ImageFormat, o as ImageRef, u as JobHandle, J as JobStatus, v as JobStatusResponse, M as MediaInfo, O as OcrOpts, Q as QrCodeSpec, r as QrPayload, R as ResizeOpts, S as SubjectBox, c as ThumbnailOpts, b as TranscodeOpts, t as TransformSpec, T as TransformsConfig, a as TransformsPatternSpec, w as TransformsService, V as VideoFormat,
|
|
6
|
+
export { D as DetachAudioOpts, e as DetectFacesOpts, l as DocConvertOpts, i as DocFormat, q as DocInsertQrCodeOpts, p as DocReplaceImagesOpts, s as DocTemplateMergeOpts, k as DocThumbnailOpts, n as DocToHtmlOpts, m as DocToMarkdownOpts, j as DocToPdfOpts, d as ExtractAudioOpts, E as ExtractFramesOpts, g as FaceBox, z as FocalCssFrame, y as FocalCssFrameInput, f as FocalPoint, h as FocalPointRecord, F as FramesetManifest, I as ImageFormat, o as ImageRef, u as JobHandle, J as JobStatus, v as JobStatusResponse, M as MediaInfo, O as OcrOpts, Q as QrCodeSpec, r as QrPayload, R as ResizeOpts, S as SubjectBox, c as ThumbnailOpts, b as TranscodeOpts, t as TransformSpec, T as TransformsConfig, a as TransformsPatternSpec, w as TransformsService, V as VideoFormat, C as focalCssFrame, x as keyFor, B as primaryFaceBox, G as transforms, A as unionFaceBox } from './transforms-C2zafn5k.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Media service for video/audio room management.
|
package/dist/index.js
CHANGED
|
@@ -2096,6 +2096,7 @@ function keyFor(srcKey, spec) {
|
|
|
2096
2096
|
const ext = outputExtension(spec);
|
|
2097
2097
|
return `__derived/${srcHash}/${variantHash}.${ext}`;
|
|
2098
2098
|
}
|
|
2099
|
+
var AUTO_ZOOM = 1.22;
|
|
2099
2100
|
var clamp01 = (n) => Math.min(1, Math.max(0, n));
|
|
2100
2101
|
function unionFaceBox(faces) {
|
|
2101
2102
|
if (!faces || faces.length === 0) return null;
|
|
@@ -2115,17 +2116,42 @@ function unionFaceBox(faces) {
|
|
|
2115
2116
|
if (w <= 0 || h <= 0) return null;
|
|
2116
2117
|
return { x: x0, y: y0, w, h };
|
|
2117
2118
|
}
|
|
2119
|
+
function primaryFaceBox(faces) {
|
|
2120
|
+
if (!faces || faces.length === 0) return null;
|
|
2121
|
+
const f = faces.reduce((a, b) => b.score > a.score ? b : a);
|
|
2122
|
+
const x0 = clamp01(f.x);
|
|
2123
|
+
const y0 = clamp01(f.y);
|
|
2124
|
+
const x1 = clamp01(f.x + f.w);
|
|
2125
|
+
const y1 = clamp01(f.y + f.h);
|
|
2126
|
+
const w = x1 - x0;
|
|
2127
|
+
const h = y1 - y0;
|
|
2128
|
+
if (w <= 0 || h <= 0) return null;
|
|
2129
|
+
return {
|
|
2130
|
+
box: { x: x0, y: y0, w, h },
|
|
2131
|
+
focal: { x: x0 + w / 2, y: clamp01(y0 + 0.4 * h) }
|
|
2132
|
+
};
|
|
2133
|
+
}
|
|
2118
2134
|
function focalCssFrame(input) {
|
|
2119
|
-
const {
|
|
2120
|
-
|
|
2135
|
+
const { faces, imgWidth, imgHeight, containerAspect } = input;
|
|
2136
|
+
let box;
|
|
2137
|
+
let focal = input.focal;
|
|
2138
|
+
if (input.subject === "primary") {
|
|
2139
|
+
const p = primaryFaceBox(faces);
|
|
2140
|
+
box = p?.box ?? null;
|
|
2141
|
+
if (p) focal = p.focal;
|
|
2142
|
+
} else {
|
|
2143
|
+
box = unionFaceBox(faces);
|
|
2144
|
+
}
|
|
2121
2145
|
const objectPosition = `${(clamp01(focal.x) * 100).toFixed(1)}% ${(clamp01(focal.y) * 100).toFixed(1)}%`;
|
|
2122
2146
|
const base = { objectPosition, scale: 1, transformOrigin: objectPosition };
|
|
2123
|
-
const box = unionFaceBox(faces);
|
|
2124
2147
|
if (!box || imgWidth <= 0 || imgHeight <= 0 || !(containerAspect > 0)) return base;
|
|
2125
2148
|
const iar = imgWidth / imgHeight;
|
|
2126
2149
|
const car = containerAspect;
|
|
2127
|
-
const z = Math.max(
|
|
2128
|
-
const
|
|
2150
|
+
const z = input.zoom === "auto" ? AUTO_ZOOM : Math.max(0.01, input.zoom ?? 1);
|
|
2151
|
+
const grow = 1 + 2 * Math.max(0, input.padding ?? 0);
|
|
2152
|
+
const bw = box.w * grow;
|
|
2153
|
+
const bh = box.h * grow;
|
|
2154
|
+
const targetW = z * Math.max(bw, bh * car / iar);
|
|
2129
2155
|
const coverW = car >= iar ? 1 : car / iar;
|
|
2130
2156
|
const scale = Math.max(1, coverW / targetW);
|
|
2131
2157
|
return { objectPosition, scale: Math.round(scale * 1e3) / 1e3, transformOrigin: objectPosition };
|
|
@@ -2133,7 +2159,8 @@ function focalCssFrame(input) {
|
|
|
2133
2159
|
var transforms = {
|
|
2134
2160
|
keyFor,
|
|
2135
2161
|
focalCssFrame,
|
|
2136
|
-
unionFaceBox
|
|
2162
|
+
unionFaceBox,
|
|
2163
|
+
primaryFaceBox
|
|
2137
2164
|
};
|
|
2138
2165
|
|
|
2139
2166
|
// src/index.ts
|
|
@@ -2186,6 +2213,7 @@ export {
|
|
|
2186
2213
|
getPlatform,
|
|
2187
2214
|
keyFor,
|
|
2188
2215
|
offsetBefore,
|
|
2216
|
+
primaryFaceBox,
|
|
2189
2217
|
registerPush,
|
|
2190
2218
|
renFetch,
|
|
2191
2219
|
runWithRequest,
|