@popmelt.com/core 0.18.1 → 0.19.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/README.md +34 -0
- package/codex-plugin/.codex-plugin/plugin.json +1 -1
- package/dist/adapter-react-three-fiber.d.mts +1 -1
- package/dist/adapter-three.d.mts +17 -0
- package/dist/bridge-entry.mjs +54 -54
- package/dist/{chunk-P2Y3NJ7A.mjs → chunk-MW7KZNBE.mjs} +1 -1
- package/dist/chunk-N2ZEZCHO.mjs +2 -0
- package/dist/cli.mjs +74 -74
- package/dist/index.d.mts +32 -5
- package/dist/index.mjs +40 -40
- package/dist/media.d.mts +3 -3
- package/dist/media.mjs +1 -1
- package/dist/plugin-astro.mjs +1 -1
- package/dist/plugin-vite.mjs +1 -1
- package/dist/{server-VX66FOQO.mjs → server-YFHA5O7M.mjs} +56 -56
- package/dist/server.d.mts +2 -2
- package/dist/server.mjs +56 -56
- package/dist/{subjects-CeqtFged.d.mts → subjects-C6Bu8uSX.d.mts} +18 -1
- package/dist/{video-adapter-Gq8saCDn.d.mts → video-adapter-UZ8OqP0O.d.mts} +39 -2
- package/package.json +1 -1
- package/dist/chunk-RS3XXK26.mjs +0 -2
|
@@ -345,6 +345,12 @@ type PopmeltSubjectTrackingAnchor = {
|
|
|
345
345
|
/** Vertical position normalized within the subject bounds. */
|
|
346
346
|
y: number;
|
|
347
347
|
};
|
|
348
|
+
type PopmeltSubjectOutlinePoint = {
|
|
349
|
+
/** Horizontal position normalized within the subject bounds. */
|
|
350
|
+
x: number;
|
|
351
|
+
/** Vertical position normalized within the subject bounds. */
|
|
352
|
+
y: number;
|
|
353
|
+
};
|
|
348
354
|
type PopmeltSubject = {
|
|
349
355
|
key: string;
|
|
350
356
|
label: string;
|
|
@@ -359,6 +365,8 @@ type PopmeltSubject = {
|
|
|
359
365
|
videoObject?: VideoObjectContext;
|
|
360
366
|
/** Optional provider-neutral foreground anchors used by motion tracking. */
|
|
361
367
|
trackingAnchors?: readonly PopmeltSubjectTrackingAnchor[];
|
|
368
|
+
/** Optional provider-neutral contour normalized within the subject bounds. */
|
|
369
|
+
outline?: readonly PopmeltSubjectOutlinePoint[];
|
|
362
370
|
};
|
|
363
371
|
type PopmeltSurfaceSnapshot = {
|
|
364
372
|
element: HTMLCanvasElement;
|
|
@@ -383,6 +391,13 @@ type PopmeltSubjectAdapter = {
|
|
|
383
391
|
surfaceKind?: 'image' | 'video';
|
|
384
392
|
/** Resolve once the adapter's persisted subject index is available. */
|
|
385
393
|
whenReady?(): Promise<void>;
|
|
394
|
+
/** Notify Core when asynchronous perception changes hit-testable subjects. */
|
|
395
|
+
subscribe?(listener: () => void): () => void;
|
|
396
|
+
/** Ordered hit candidates, innermost/most-specific first. */
|
|
397
|
+
hitTestAll?(clientPoint: {
|
|
398
|
+
x: number;
|
|
399
|
+
y: number;
|
|
400
|
+
}): readonly PopmeltSubject[];
|
|
386
401
|
hitTest(clientPoint: {
|
|
387
402
|
x: number;
|
|
388
403
|
y: number;
|
|
@@ -405,8 +420,10 @@ type PopmeltSubjectAdapter = {
|
|
|
405
420
|
updateSubjectBounds?(key: string, bounds: PopmeltSubjectBounds): PopmeltSubject | null;
|
|
406
421
|
/** Replace optional foreground anchors normalized within subject bounds. */
|
|
407
422
|
updateSubjectTrackingAnchors?(key: string, anchors: readonly PopmeltSubjectTrackingAnchor[]): PopmeltSubject | null;
|
|
423
|
+
/** Promote a transient perception candidate into a durable subject. */
|
|
424
|
+
promoteSubject?(key: string): PopmeltSubject | null;
|
|
408
425
|
/** Remove a user-created subject or hide an adapter-owned subject. */
|
|
409
426
|
removeSubject?(key: string): void;
|
|
410
427
|
};
|
|
411
428
|
|
|
412
|
-
export type { Annotation as A, BridgeStatus as B, ClaudeResponse as C, DomModification as D, ElementInfo as E, ImageObjectContext as I, OpaqueTargetReference as O, PopmeltSubjectAdapter as P, ReactSourceLocation as R, SubjectFeedbackAttachment as S, TextModification as T, VideoObjectContext as V, AnnotationAttachment as a, StyleModification as b, SpacingTokenChange as c, AnnotationType as d, Point as e, PopmeltSubject as f, PopmeltSubjectBounds as g, PopmeltSubjectCreationSession as h,
|
|
429
|
+
export type { Annotation as A, BridgeStatus as B, ClaudeResponse as C, DomModification as D, ElementInfo as E, ImageObjectContext as I, OpaqueTargetReference as O, PopmeltSubjectAdapter as P, ReactSourceLocation as R, SubjectFeedbackAttachment as S, TextModification as T, VideoObjectContext as V, AnnotationAttachment as a, StyleModification as b, SpacingTokenChange as c, AnnotationType as d, Point as e, PopmeltSubject as f, PopmeltSubjectBounds as g, PopmeltSubjectCreationSession as h, PopmeltSubjectOutlinePoint as i, PopmeltSubjectTrackingAnchor as j, PopmeltSurfaceSnapshot as k, StyleChange as l, ToolType as m };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { P as PopmeltSubjectAdapter, f as PopmeltSubject, E as ElementInfo, h as PopmeltSubjectCreationSession, g as PopmeltSubjectBounds, i as PopmeltSubjectTrackingAnchor } from './subjects-
|
|
1
|
+
import { P as PopmeltSubjectAdapter, f as PopmeltSubject, E as ElementInfo, h as PopmeltSubjectCreationSession, g as PopmeltSubjectBounds, i as PopmeltSubjectOutlinePoint, j as PopmeltSubjectTrackingAnchor } from './subjects-C6Bu8uSX.mjs';
|
|
2
2
|
|
|
3
3
|
/** Geometry is normalized against the loaded image, not its rendered size. */
|
|
4
4
|
type ImageObjectBox = {
|
|
@@ -142,6 +142,28 @@ type VideoTrackKeyframe = {
|
|
|
142
142
|
box: VideoObjectBox;
|
|
143
143
|
score: number;
|
|
144
144
|
source: 'manual' | 'tracked';
|
|
145
|
+
/** Optional contour normalized within this frame's box. */
|
|
146
|
+
outline?: readonly PopmeltSubjectOutlinePoint[];
|
|
147
|
+
};
|
|
148
|
+
type VideoSegmentationPoint = {
|
|
149
|
+
/** Horizontal position normalized within the uncropped video frame. */
|
|
150
|
+
x: number;
|
|
151
|
+
/** Vertical position normalized within the uncropped video frame. */
|
|
152
|
+
y: number;
|
|
153
|
+
};
|
|
154
|
+
type VideoSegmentationObservation = {
|
|
155
|
+
label?: string;
|
|
156
|
+
score: number;
|
|
157
|
+
box: VideoObjectBox;
|
|
158
|
+
/** Contour normalized within `box`. */
|
|
159
|
+
outline?: readonly PopmeltSubjectOutlinePoint[];
|
|
160
|
+
};
|
|
161
|
+
/** Optional point-prompted perception boundary. Core owns the resulting subject. */
|
|
162
|
+
type VideoSegmentationProvider = {
|
|
163
|
+
cacheKey: string;
|
|
164
|
+
configurationKey: string;
|
|
165
|
+
segment(video: HTMLVideoElement, time: number, point: VideoSegmentationPoint): Promise<VideoSegmentationObservation | null>;
|
|
166
|
+
dispose?(): void | Promise<void>;
|
|
145
167
|
};
|
|
146
168
|
type VideoTrackObservation = {
|
|
147
169
|
time: number;
|
|
@@ -255,6 +277,7 @@ type VideoSubjectStore = {
|
|
|
255
277
|
};
|
|
256
278
|
|
|
257
279
|
type VideoSubjectAdapterOptions = {
|
|
280
|
+
segmentation?: VideoSegmentationProvider;
|
|
258
281
|
tracking?: VideoTrackingProvider;
|
|
259
282
|
selector?: string;
|
|
260
283
|
root?: Document | Element;
|
|
@@ -281,16 +304,27 @@ declare class VideoSubjectAdapter implements PopmeltSubjectAdapter {
|
|
|
281
304
|
private refreshQueued;
|
|
282
305
|
private destroyed;
|
|
283
306
|
private manualSequence;
|
|
307
|
+
private detectedSequence;
|
|
284
308
|
private activeTrackingKey;
|
|
309
|
+
private segmentationGeneration;
|
|
310
|
+
private readonly transientKeys;
|
|
311
|
+
private readonly segmentationRequestSignatures;
|
|
312
|
+
private readonly changeListeners;
|
|
285
313
|
private readyPromise;
|
|
286
314
|
constructor(options?: VideoSubjectAdapterOptions);
|
|
287
315
|
whenReady(): Promise<void>;
|
|
316
|
+
subscribe(listener: () => void): () => void;
|
|
288
317
|
listSubjects(): readonly PopmeltSubject[];
|
|
289
318
|
refresh(): Promise<void>;
|
|
290
319
|
hitTest(point: {
|
|
291
320
|
x: number;
|
|
292
321
|
y: number;
|
|
293
322
|
}): PopmeltSubject | null;
|
|
323
|
+
hitTestAll(point: {
|
|
324
|
+
x: number;
|
|
325
|
+
y: number;
|
|
326
|
+
}): readonly PopmeltSubject[];
|
|
327
|
+
promoteSubject(key: string): PopmeltSubject | null;
|
|
294
328
|
resolve(key: string): PopmeltSubject | null;
|
|
295
329
|
captureSubject(key: string): Promise<Blob | null>;
|
|
296
330
|
beginCreate(point: {
|
|
@@ -302,6 +336,9 @@ declare class VideoSubjectAdapter implements PopmeltSubjectAdapter {
|
|
|
302
336
|
updateSubjectTrackingAnchors(key: string, anchors: readonly PopmeltSubjectTrackingAnchor[]): PopmeltSubject | null;
|
|
303
337
|
removeSubject(key: string): void;
|
|
304
338
|
destroy(): Promise<void>;
|
|
339
|
+
private scheduleSegmentation;
|
|
340
|
+
private addDetectedSubject;
|
|
341
|
+
private clearTransientSubjects;
|
|
305
342
|
private analyze;
|
|
306
343
|
private addVideoListeners;
|
|
307
344
|
private removeVideoListeners;
|
|
@@ -336,4 +373,4 @@ declare class VideoSubjectAdapter implements PopmeltSubjectAdapter {
|
|
|
336
373
|
}
|
|
337
374
|
declare function createVideoSubjectAdapter(options?: VideoSubjectAdapterOptions): VideoSubjectAdapter;
|
|
338
375
|
|
|
339
|
-
export { type
|
|
376
|
+
export { type VideoTrackSmoother as A, type BrowserImageSubjectStoreOptions as B, type VideoTrackingAnchor as C, type VideoTrackingAttempt as D, type VideoTrackingSeed as E, type VideoTrackingSession as F, createBrowserImageSubjectStore as G, createImageSubjectAdapter as H, type ImageRecognitionProvider as I, createMemoryImageSubjectStore as J, createVideoSubjectAdapter as K, type PersistedImageAnalysis as P, type VideoTrackingProvider as V, type VideoSegmentationProvider as a, type ImageSubjectAdapterOptions as b, type VideoSubjectAdapterOptions as c, type ImageObjectBox as d, type VideoSubjectStore as e, type VideoObjectBox as f, type ImageContentHasher as g, type ImageObjectObservation as h, ImageSubjectAdapter as i, type ImageSubjectStore as j, type PersistedImageSubject as k, type PersistedImageSuppression as l, type PersistedVideoAnalysis as m, type PersistedVideoTrack as n, type VideoBackwardAnalysisOptions as o, type VideoBackwardAnalysisResult as p, type VideoMotionAttempt as q, type VideoMotionPolicy as r, type VideoMotionPresenceDecision as s, type VideoMotionState as t, type VideoSegmentationObservation as u, type VideoSegmentationPoint as v, VideoSubjectAdapter as w, type VideoTrackKeyframe as x, type VideoTrackObservation as y, type VideoTrackSegment as z };
|
package/package.json
CHANGED
package/dist/chunk-RS3XXK26.mjs
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
var S=(n,e=0,i=1)=>Math.min(i,Math.max(e,n));function ie(n){let{width:e,height:i}=n.rect,t=Math.max(1,n.naturalWidth),s=Math.max(1,n.naturalHeight),r=Math.min(e/t,i/s),o=Math.max(e/t,i/s);switch(n.objectFit){case"contain":return{width:t*r,height:s*r};case"cover":return{width:t*o,height:s*o};case"none":return{width:t,height:s};case"scale-down":{let a=Math.min(1,r);return{width:t*a,height:s*a}}default:return{width:e,height:i}}}function D(n,e){let i=n.trim().toLowerCase();if(i.endsWith("%")){let t=Number.parseFloat(i);return Number.isFinite(t)?e*(t/100):0}if(i.endsWith("px")){let t=Number.parseFloat(i);return Number.isFinite(t)?t:0}return i==="center"?e/2:i==="right"||i==="bottom"?e:0}function se(n,e,i){let t=n.objectPosition.trim().split(/\s+/),s=t[0]||"50%",r=t[1]||"50%";return{x:D(s,n.rect.width-e),y:D(r,n.rect.height-i)}}function L(n){let e=n.getBoundingClientRect();if(e.width<=0||e.height<=0||n.naturalWidth<=0||n.naturalHeight<=0)return null;let i=n.ownerDocument.defaultView?.getComputedStyle(n)??getComputedStyle(n),t={rect:e,naturalWidth:n.naturalWidth,naturalHeight:n.naturalHeight,objectFit:i.objectFit||"fill",objectPosition:i.objectPosition||"50% 50%"},s=ie(t);return{layout:t,rendered:s,position:se(t,s.width,s.height)}}function E(n,e){let i=L(n);if(!i)return null;let{layout:t,rendered:s,position:r}=i;if(e.x<t.rect.left||e.x>t.rect.left+t.rect.width||e.y<t.rect.top||e.y>t.rect.top+t.rect.height)return null;let o=(e.x-t.rect.left-r.x)/s.width,a=(e.y-t.rect.top-r.y)/s.height;return o>=0&&o<=1&&a>=0&&a<=1?{x:o,y:a}:null}function N(n,e){let i=L(n);if(!i)return null;let{layout:t,rendered:s,position:r}=i,o=(e.left-t.rect.left-r.x)/s.width,a=(e.top-t.rect.top-r.y)/s.height,l=(e.left+e.width-t.rect.left-r.x)/s.width,d=(e.top+e.height-t.rect.top-r.y)/s.height,c=S(Math.min(o,l)),u=S(Math.min(a,d)),m=S(Math.max(o,l)),h=S(Math.max(a,d));return m<=c||h<=u?null:{left:c,top:u,width:m-c,height:h-u}}function H(n,e){if(![e.left,e.top,e.width,e.height].every(Number.isFinite))return null;let i=L(n);if(!i)return null;let{layout:t,rendered:s,position:r}=i,{rect:o}=t,a=o.left+r.x+S(e.left)*s.width,l=o.top+r.y+S(e.top)*s.height,d=o.left+r.x+S(e.left+Math.max(0,e.width))*s.width,c=o.top+r.y+S(e.top+Math.max(0,e.height))*s.height,u=Math.max(o.left,a),m=Math.max(o.top,l),h=Math.min(o.left+o.width,d),g=Math.min(o.top+o.height,c);return h<=u||g<=m?null:{left:u,top:m,width:h-u,height:g-m}}var ne="popmelt:see:v1";function K(n){if(!n||typeof n!="object")return!1;let e=n;return["left","top","width","height"].every(i=>typeof e[i]=="number"&&Number.isFinite(e[i]))}function re(n){if(!n||typeof n!="object")return!1;let e=n;return typeof e.id=="string"&&typeof e.label=="string"&&typeof e.score=="number"&&(e.origin==="detected"||e.origin==="manual")&&K(e.box)&&(e.detectedBox===void 0||K(e.detectedBox))}function oe(n){if(!n||typeof n!="object")return!1;let e=n;return typeof e.detectedLabel=="string"&&K(e.detectedBox)}function _(n){if(!n||typeof n!="object")return!1;let e=n;return e.schemaVersion===1&&typeof e.source=="string"&&typeof e.imageHash=="string"&&typeof e.inferenceKey=="string"&&typeof e.dedupeKey=="string"&&typeof e.updatedAt=="number"&&Array.isArray(e.subjects)&&e.subjects.every(re)&&(e.suppressions===void 0||Array.isArray(e.suppressions)&&e.suppressions.every(oe))}function Ie(n={}){let e=n.namespace??ne,i=()=>n.storage??window.localStorage,t=a=>`${e}:${a}`,s=a=>`${t(a)}:history`,r=a=>{try{let l=i().getItem(t(a));if(!l)return null;let d=JSON.parse(l);return _(d)?d:null}catch{return null}},o=a=>{try{let l=i().getItem(s(a));if(!l)return[];let d=JSON.parse(l);return Array.isArray(d)?d.filter(_).slice(0,10):[]}catch{return[]}};return{load:r,save(a,l){let d=r(a);if(d&&d.imageHash!==l.imageHash){let c=o(a).filter(u=>u.imageHash!==d.imageHash||u.updatedAt!==d.updatedAt);i().setItem(s(a),JSON.stringify([d,...c].slice(0,10)))}i().setItem(t(a),JSON.stringify(l))},remove(a){i().removeItem(t(a)),i().removeItem(s(a))},loadHistory:o}}function je(){let n=new Map,e=new Map;return{load:i=>n.get(i)??null,save:(i,t)=>{let s=n.get(i);if(s&&s.imageHash!==t.imageHash){let r=e.get(i)??[];e.set(i,[s,...r.filter(o=>o.imageHash!==s.imageHash||o.updatedAt!==s.updatedAt)].slice(0,10))}n.set(i,t)},remove:i=>{n.delete(i),e.delete(i)},loadHistory:i=>e.get(i)??[]}}function U(n){return{label:n.label,score:n.score,box:{...n.box}}}var R="img";function j(n){let e=2166136261;for(let i=0;i<n.length;i+=1)e^=n.charCodeAt(i),e=Math.imul(e,16777619);return(e>>>0).toString(36)}function B(n){return new URL(y(n),n.ownerDocument.baseURI).href}async function ae(n){let e=B(n);try{let i=await fetch(e,{cache:"force-cache",credentials:"same-origin"});if(!i.ok)throw new Error(`Unable to hash image (${i.status})`);let t=await i.arrayBuffer();if(!globalThis.crypto?.subtle)throw new Error("SubtleCrypto unavailable");let s=await globalThis.crypto.subtle.digest("SHA-256",t);return Array.from(new Uint8Array(s),r=>r.toString(16).padStart(2,"0")).join("")}catch{return`source:${j(e)}:${n.naturalWidth}x${n.naturalHeight}`}}function y(n){return n.currentSrc||n.src||n.getAttribute("src")||""}function de(n){return n.complete&&n.naturalWidth>0&&n.naturalHeight>0?Promise.resolve():new Promise((e,i)=>{let t=()=>{r(),e()},s=()=>{r(),i(new Error(`Unable to load image: ${y(n)}`))},r=()=>{n.removeEventListener("load",t),n.removeEventListener("error",s)};n.addEventListener("load",t,{once:!0}),n.addEventListener("error",s,{once:!0})})}function ce(n,e){return{id:e.id,image:n,detection:U(e),detectedLabel:e.detectedLabel,detectedBox:e.detectedBox?{...e.detectedBox}:void 0,boundsOverridden:e.boundsOverridden,manual:e.origin==="manual"}}function le(n){return{id:n.id,label:n.detection.label,detectedLabel:n.detectedLabel,score:n.detection.score,box:{...n.detection.box},detectedBox:n.detectedBox?{...n.detectedBox}:void 0,origin:n.manual?"manual":"detected",boundsOverridden:n.boundsOverridden}}function ue(n){return n.origin==="manual"||n.boundsOverridden===!0||!!(n.detectedLabel&&n.label!==n.detectedLabel)}function me(n,e){return e.x>=n.left&&e.x<=n.left+n.width&&e.y>=n.top&&e.y<=n.top+n.height}var O=class{constructor(e={}){this.options=e;this.surfaceKind="image";this.records=new Map;this.imageKeys=new Map;this.analyzedSources=new WeakMap;this.pending=new WeakMap;this.analysisMetadata=new WeakMap;this.suppressions=new WeakMap;this.writeChains=new WeakMap;this.pendingWrites=new Set;this.refreshQueued=!1;this.destroyed=!1;this.manualSequence=0;this.id=e.id??"see:image",this.readyPromise=this.refresh();let i=e.root??document;this.observer=e.observe!==!1&&typeof MutationObserver<"u"?new MutationObserver(()=>this.queueRefresh()):null,this.observer?.observe(i,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["src","srcset","sizes"]})}whenReady(){return this.readyPromise}listSubjects(){let e=[];for(let i of this.records.keys()){let t=this.resolve(i);t&&e.push(t)}return e}async refresh(){if(this.destroyed)return;let e=this.options.root??document,i=this.options.selector??R,t=new Set;e instanceof HTMLImageElement&&e.matches(i)&&t.add(e);for(let s of e.querySelectorAll(i))s instanceof HTMLImageElement&&t.add(s);for(let s of this.imageKeys.keys())(!t.has(s)||!s.isConnected)&&this.removeImage(s);if(this.options.recognition)for(let s of t)await this.analyze(s);else await Promise.all(Array.from(t,s=>this.analyze(s)))}hitTest(e){let i=null;for(let t of this.records.keys()){let s=this.resolve(t),r=this.records.get(t);if(!s||!r||!me(s.bounds,e))continue;let o=s.bounds.width*s.bounds.height;(!i||o<i.area||o===i.area&&r.detection.score>i.score)&&(i={subject:s,area:o,score:r.detection.score})}return i?.subject??null}resolve(e){let i=this.records.get(e);if(!i||!i.image.isConnected)return null;let t=H(i.image,i.detection.box);if(!t)return null;let s=i.image.getBoundingClientRect(),r=Math.round(i.detection.score*1e3)/1e3;return{key:e,label:i.detection.label,sourceElement:i.image,imageObject:this.imageObjectContext(i),bounds:t,surfaceBounds:{left:s.left,top:s.top,width:s.width,height:s.height},context:`${i.detection.label} ${i.manual?"labelled":"detected"} in ${i.image.alt||"image"}`,data:{kind:"image-object",label:i.detection.label,origin:i.manual?"manual":"detected",...i.detectedLabel?{detectedLabel:i.detectedLabel}:{},score:String(r),imageSrc:y(i.image)}}}restoreSubject(e,i){if(this.records.has(e))return this.resolve(e);let t=i.imageObject;if(!t)return null;let s=i.sourceElement?.dataAttributes,r=s?.["data-popmelt-media-id"]??s?.["data-popmelt-see-id"],o=this.matchingImages().find(p=>{let f=y(p),b=this.imageIdentity(p,f);return!(!e.startsWith(`${b}:`)||r&&b!==r)});if(!o)return null;let a=this.imageIdentity(o,y(o)),l=e.slice(a.length+1),d={left:t.normalizedBox.x,top:t.normalizedBox.y,width:t.normalizedBox.width,height:t.normalizedBox.height};if(!l||!Object.values(d).every(p=>Number.isFinite(p)&&p>=0&&p<=1))return null;let c=i.dataAttributes,u=i.subjectLabel??c?.label??i.textContent;if(!u)return null;let m=Number(c?.score),h=c?.origin==="manual";this.records.set(e,{id:l,image:o,detection:{label:u,score:Number.isFinite(m)?m:1,box:d},detectedLabel:c?.detectedLabel,detectedBox:h?void 0:{...d},boundsOverridden:!0,manual:h});let g=this.imageKeys.get(o)??new Set;if(g.add(e),this.imageKeys.set(o,g),!this.analysisMetadata.has(o)){let p=B(o);this.analysisMetadata.set(o,{storeKey:`${this.id}:${a}`,source:p,imageHash:`recovered:${j(p)}`,inferenceKey:"",dedupeKey:""}),this.suppressions.set(o,[])}return this.persistImage(o),this.resolve(e)}imageObjectContext(e){let{image:i,detection:{box:t}}=e;return{src:y(i),alt:i.alt,width:i.naturalWidth,height:i.naturalHeight,normalizedBox:{x:t.left,y:t.top,width:t.width,height:t.height},box:{x:t.left*i.naturalWidth,y:t.top*i.naturalHeight,width:t.width*i.naturalWidth,height:t.height*i.naturalHeight}}}async captureSubject(e){let i=this.records.get(e);if(!i?.image.isConnected||!i.image.complete)return null;let{box:t}=this.imageObjectContext(i);if(t.width<=0||t.height<=0)return null;let s=Math.min(1,1024/Math.max(t.width,t.height)),r=document.createElement("canvas");r.width=Math.max(1,Math.round(t.width*s)),r.height=Math.max(1,Math.round(t.height*s));let o=r.getContext("2d");return o?(o.drawImage(i.image,t.x,t.y,t.width,t.height,0,0,r.width,r.height),new Promise((a,l)=>{try{r.toBlob(a,"image/webp",.95)}catch(d){l(d)}})):null}beginCreate(e){let i=this.matchingImages();for(let t=i.length-1;t>=0;t-=1){let s=i[t];if(!s)continue;let r=E(s,e);if(!r)continue;let o=y(s),a=this.imageIdentity(s,o),l=`manual:${this.newObjectId()}`,d=`${a}:${l}`,c={label:"object",score:1,box:{left:r.x,top:r.y,width:0,height:0}},u=!1,m=!1,h=()=>{if(m)return;m=!0,this.records.set(d,{id:l,image:s,detection:c,manual:!0});let g=this.imageKeys.get(s)??new Set;g.add(d),this.imageKeys.set(s,g)};return{key:d,update:g=>{if(u)return null;h();let p=this.clampedImagePoint(s,g);return p?(c.box={left:Math.min(r.x,p.x),top:Math.min(r.y,p.y),width:Math.abs(p.x-r.x),height:Math.abs(p.y-r.y)},this.resolve(d)):this.resolve(d)},commit:()=>u?null:(h(),this.persistImage(s),this.resolve(d)),cancel:()=>{u||(u=!0,m&&this.removeSubject(d))}}}return null}renameSubject(e,i){let t=this.records.get(e),s=i.trim();return!t||!s?null:(!t.manual&&!t.detectedLabel&&(t.detectedLabel=t.detection.label),t.detection.label=s,this.persistImage(t.image),this.resolve(e))}updateSubjectBounds(e,i){let t=this.records.get(e);if(!t)return null;let s=N(t.image,i);return s?(t.detection.box=s,t.boundsOverridden=!0,this.persistImage(t.image),this.resolve(e)):null}removeSubject(e){let i=this.records.get(e);if(!i)return;if(!i.manual){let s=this.suppressions.get(i.image)??[];s.push({detectedLabel:i.detectedLabel??i.detection.label,detectedBox:{...i.detectedBox??i.detection.box}}),this.suppressions.set(i.image,s)}this.records.delete(e);let t=this.imageKeys.get(i.image);t?.delete(e),t?.size===0&&this.imageKeys.delete(i.image),this.persistImage(i.image)}async destroy(){this.destroyed||(this.destroyed=!0,this.observer?.disconnect(),this.records.clear(),this.imageKeys.clear(),await Promise.allSettled(this.pendingWrites),await this.options.recognition?.dispose?.())}queueRefresh(){this.refreshQueued||this.destroyed||(this.refreshQueued=!0,queueMicrotask(()=>{this.refreshQueued=!1,this.readyPromise=this.refresh()}))}async analyze(e){let i=y(e);if(!i||this.analyzedSources.get(e)===i)return;let t=this.pending.get(e);if(t)return t.source===i?t.promise:(await t.promise,this.analyze(e));this.analyzedSources.has(e)&&this.removeImage(e);let s={source:i,promise:Promise.resolve()},r=(async()=>{try{if(await de(e),this.destroyed)return;let o=B(e),a=this.imageIdentity(e,i),l=`${this.id}:${a}`,d=this.options.recognition,c=this.options.store?await this.options.store.load(l):null;if(this.destroyed||y(e)!==i)return;let u=d?.cacheKey??c?.inferenceKey??"",m=d?.configurationKey??c?.dedupeKey??"",h=c?.source===o,g=!!(e.dataset.popmeltMediaId||e.dataset.popmeltSeeId),p=h||g;if(c&&p){let I=new Map(c.subjects.map(T=>[T.id,T]));for(let T of this.imageSubjects(e))I.set(T.id,T);this.replaceImageRecords(e,a,[...I.values()]),this.suppressions.set(e,[...c.suppressions??[]]),this.analysisMetadata.set(e,{storeKey:l,source:o,imageHash:c.imageHash,inferenceKey:c.inferenceKey,dedupeKey:c.dedupeKey})}if(this.options.hydrateOnly){this.analyzedSources.set(e,i);return}let f=this.options.store?await(this.options.imageHasher??ae)(e):"ephemeral";if(this.destroyed||y(e)!==i)return;if(!!(c&&p&&c.imageHash===f&&(!d||c.inferenceKey===u&&c.dedupeKey===m))){this.analysisMetadata.set(e,{storeKey:l,source:o,imageHash:f,inferenceKey:u,dedupeKey:m}),this.analyzedSources.set(e,i),await this.saveImage(e);return}let V=p&&c?.imageHash===f;if(c&&!V){let I=new Set(c.subjects.map(A=>A.id)),T=c.subjects.filter(ue);this.replaceImageRecords(e,a,[...T,...this.imageSubjects(e).filter(A=>!I.has(A.id))]),this.suppressions.set(e,[])}if(this.analysisMetadata.set(e,{storeKey:l,source:o,imageHash:f,inferenceKey:V?c.inferenceKey:"",dedupeKey:V?c.dedupeKey:""}),!d){this.analyzedSources.set(e,i),await this.saveImage(e);return}let ee=await d.detect(e);if(this.destroyed||y(e)!==i)return;let W=this.suppressions.get(e)??[],te=d.reconcile(ee,this.imageSubjects(e),W);this.replaceImageRecords(e,a,te),this.suppressions.set(e,[...W]),this.analysisMetadata.set(e,{storeKey:l,source:o,imageHash:f,inferenceKey:u,dedupeKey:m}),this.analyzedSources.set(e,i),await this.saveImage(e)}catch(o){this.options.onError?.(o,e)}finally{this.pending.get(e)===s&&this.pending.delete(e)}})();return s.promise=r,this.pending.set(e,s),r}replaceImageRecords(e,i,t){this.removeImage(e);let s=new Set;for(let r of t){let o=`${i}:${r.id}`;s.add(o),this.records.set(o,ce(e,r))}this.imageKeys.set(e,s)}imageIdentity(e,i){if(e.dataset.popmeltMediaId)return e.dataset.popmeltMediaId;if(e.dataset.popmeltSeeId)return e.dataset.popmeltSeeId;let t=new URL(i,e.ownerDocument.baseURI).href,s=this.options.root??e.ownerDocument,r=this.options.selector??R,o=Array.from(s.querySelectorAll(r)).filter(l=>y(l)===i),a=Math.max(0,o.indexOf(e));return`${j(t)}:${a}`}matchingImages(){let e=this.options.root??document,i=this.options.selector??R,t=[];e instanceof HTMLImageElement&&e.matches(i)&&t.push(e);for(let s of e.querySelectorAll(i))s instanceof HTMLImageElement&&t.push(s);return t}clampedImagePoint(e,i){let t=H(e,{left:0,top:0,width:1,height:1});return t?E(e,{x:Math.max(t.left,Math.min(t.left+t.width,i.x)),y:Math.max(t.top,Math.min(t.top+t.height,i.y))}):null}newObjectId(){let e=globalThis.crypto?.randomUUID?.();return e||j(`${Date.now()}:${this.manualSequence++}:${Math.random().toString(36)}`)}persistImage(e){let i=this.persistencePayload(e);if(!i)return Promise.resolve();let s=(this.writeChains.get(e)??Promise.resolve()).catch(()=>{}).then(()=>i.store.save(i.key,i.analysis)).catch(r=>{this.options.onError?.(r,e)});return this.writeChains.set(e,s),this.pendingWrites.add(s),s.finally(()=>this.pendingWrites.delete(s)),s}async saveImage(e){await this.persistImage(e)}imageSubjects(e){return Array.from(this.imageKeys.get(e)??[]).map(i=>this.records.get(i)).filter(i=>!!i).map(le)}persistencePayload(e){let i=this.options.store,t=this.analysisMetadata.get(e);if(!i||!t)return null;let s=this.imageSubjects(e),r={schemaVersion:1,source:t.source,imageHash:t.imageHash,inferenceKey:t.inferenceKey,dedupeKey:t.dedupeKey,subjects:s,suppressions:this.suppressions.get(e)??[],updatedAt:Date.now()};return{store:i,key:t.storeKey,analysis:r}}removeImage(e){for(let i of this.imageKeys.get(e)??[])this.records.delete(i);this.imageKeys.delete(e),this.analyzedSources.delete(e),this.analysisMetadata.delete(e),this.suppressions.delete(e)}};function Le(n={}){return new O(n)}var w=(n,e=0,i=1)=>Math.min(i,Math.max(e,n));function F(n){let e=n.getBoundingClientRect();if(e.width<=0||e.height<=0||n.videoWidth<=0||n.videoHeight<=0)return null;let i=n.ownerDocument.defaultView?.getComputedStyle(n)??getComputedStyle(n),t=i.objectFit||"fill",s=Math.min(e.width/n.videoWidth,e.height/n.videoHeight),r=Math.max(e.width/n.videoWidth,e.height/n.videoHeight),o=t==="contain"?s:t==="cover"?r:t==="none"?1:t==="scale-down"?Math.min(1,s):null,a=o?{width:n.videoWidth*o,height:n.videoHeight*o}:{width:e.width,height:e.height},l=(i.objectPosition||"50% 50%").split(/\s+/),d=(c,u)=>c.endsWith("%")?u*(Number.parseFloat(c)/100):c.endsWith("px")?Number.parseFloat(c):c==="center"?u/2:c==="right"||c==="bottom"?u:0;return{rect:e,rendered:a,position:{x:d(l[0]||"50%",e.width-a.width),y:d(l[1]||"50%",e.height-a.height)}}}function z(n,e){let i=F(n);if(!i)return null;let{rect:t,rendered:s,position:r}=i;if(e.x<t.left||e.x>t.right||e.y<t.top||e.y>t.bottom)return null;let o=(e.x-t.left-r.x)/s.width,a=(e.y-t.top-r.y)/s.height;return o>=0&&o<=1&&a>=0&&a<=1?{x:o,y:a}:null}function q(n,e){let i=F(n);if(!i)return null;let{rect:t,rendered:s,position:r}=i,o=t.left+r.x+w(e.left)*s.width,a=t.top+r.y+w(e.top)*s.height,l=t.left+r.x+w(e.left+Math.max(0,e.width))*s.width,d=t.top+r.y+w(e.top+Math.max(0,e.height))*s.height,c=Math.max(t.left,o),u=Math.max(t.top,a),m=Math.min(t.right,l),h=Math.min(t.bottom,d);return m<=c||h<=u?null:{left:c,top:u,width:m-c,height:h-u}}function Q(n,e){let i=F(n);if(!i)return null;let{rect:t,rendered:s,position:r}=i,o=(e.left-t.left-r.x)/s.width,a=(e.top-t.top-r.y)/s.height,l=(e.left+e.width-t.left-r.x)/s.width,d=(e.top+e.height-t.top-r.y)/s.height,c=w(Math.min(o,l)),u=w(Math.min(a,d)),m=w(Math.max(o,l)),h=w(Math.max(a,d));return m<=c||h<=u?null:{left:c,top:u,width:m-c,height:h-u}}var he="video",pe=1/60,Y=30,ge=.9,fe=250,M=.001;function J(n){let e=2166136261;for(let i=0;i<n.length;i+=1)e^=n.charCodeAt(i),e=Math.imul(e,16777619);return(e>>>0).toString(36)}function v(n){return n.currentSrc||n.src||n.querySelector("source")?.src||n.getAttribute("src")||""}function ye(n){return n.readyState>=1&&n.videoWidth>0&&n.videoHeight>0?Promise.resolve():new Promise((e,i)=>{let t=()=>{r(),e()},s=()=>{r(),i(new Error(`Unable to load video: ${v(n)}`))},r=()=>{n.removeEventListener("loadedmetadata",t),n.removeEventListener("error",s)};n.addEventListener("loadedmetadata",t,{once:!0}),n.addEventListener("error",s,{once:!0})})}function be(n,e,i){let t=(s,r)=>s+(r-s)*i;return{left:t(n.left,e.left),top:t(n.top,e.top),width:t(n.width,e.width),height:t(n.height,e.height)}}function x(n,e){return n.find(i=>e>=i.start-.001&&(i.end===void 0||e<=i.end+.001))??null}function C(n){return!x(n.segments,n.video.currentTime)}function k(n){return n?.motion.createSmoother()??{smooth(e){return{...e,box:{...e.box}}}}}function X(n){return{visible:!C(n),misses:n.misses,hits:n.hits,lostAt:n.lostAt}}function ve(n,e){n.misses=e.misses,n.hits=e.hits,n.lostAt=e.lostAt}function Se(n,e){if(e?.length)return e.map(t=>({...t})).sort((t,s)=>t.start-s.start);let i=n.reduce((t,s)=>Math.min(t,s.time),Number.POSITIVE_INFINITY);return Number.isFinite(i)?[{start:i}]:[]}function P(n,e,i){if(n.length===0||i&&!x(i,e))return null;let t=[...n].sort((d,c)=>d.time-c.time),s=t.findIndex(d=>d.time>=e);if(s<=0)return{...t[0],box:{...t[0].box}};if(s<0){let d=t[t.length-1];return{...d,box:{...d.box}}}let r=t[s-1],o=t[s],a=Math.max(Number.EPSILON,o.time-r.time),l=Math.max(0,Math.min(1,(e-r.time)/a));return{time:e,box:be(r.box,o.box,l),score:r.score+(o.score-r.score)*l,source:r.source==="manual"||o.source==="manual"?"manual":"tracked"}}function G(n){return!n.video.paused&&n.liveFrame?{...n.liveFrame,box:{...n.liveFrame.box}}:P(n.presentationKeyframes,n.video.currentTime,n.segments)}function we(n,e){return e.x>=n.left&&e.x<=n.left+n.width&&e.y>=n.top&&e.y<=n.top+n.height}var $=class{constructor(e={}){this.options=e;this.surfaceKind="video";this.records=new Map;this.videoKeys=new Map;this.metadata=new WeakMap;this.analyzedSources=new WeakMap;this.listeners=new Map;this.frameHandles=new Map;this.persistTimers=new Map;this.writeChains=new WeakMap;this.pendingWrites=new Set;this.refreshQueued=!1;this.destroyed=!1;this.manualSequence=0;this.activeTrackingKey=null;this.id=e.id??"see:video",this.readyPromise=this.refresh();let i=e.root??document;this.observer=e.observe!==!1&&typeof MutationObserver<"u"?new MutationObserver(()=>this.queueRefresh()):null,this.observer?.observe(i,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["src"]})}whenReady(){return this.readyPromise}listSubjects(){return Array.from(this.records.keys(),e=>this.resolve(e)).filter(e=>!!e)}async refresh(){if(this.destroyed)return;let e=new Set(this.matchingVideos());for(let i of this.videoKeys.keys())(!e.has(i)||!i.isConnected)&&this.removeVideo(i);await Promise.all(Array.from(e,i=>this.analyze(i)))}hitTest(e){let i=null;for(let t of this.records.keys()){let s=this.resolve(t);if(!s||!we(s.bounds,e))continue;let r=s.bounds.width*s.bounds.height;(!i||r<i.area)&&(i={subject:s,area:r})}return i?.subject??null}resolve(e){let i=this.records.get(e);if(!i?.video.isConnected)return null;let t=G(i);if(!t)return null;let s=q(i.video,t.box);if(!s)return null;let r=i.video.getBoundingClientRect();return{key:e,label:i.label,sourceElement:i.video,videoObject:this.videoObjectContext(i,t),trackingAnchors:i.anchors.map(o=>({...o})),bounds:s,surfaceBounds:{left:r.left,top:r.top,width:r.width,height:r.height},context:`${i.label} tracked in video at ${i.video.currentTime.toFixed(2)}s`,data:{kind:"video-object",label:i.label,origin:i.origin,score:String(Math.round(t.score*1e3)/1e3),videoSrc:v(i.video),currentTime:String(i.video.currentTime)}}}async captureSubject(e){let i=this.records.get(e);if(!i||i.video.readyState<2)return null;let t=G(i);if(!t)return null;let{video:s}=i,r={x:t.box.left*s.videoWidth,y:t.box.top*s.videoHeight,width:t.box.width*s.videoWidth,height:t.box.height*s.videoHeight},o=Math.min(1,1024/Math.max(r.width,r.height)),a=document.createElement("canvas");a.width=Math.max(1,Math.round(r.width*o)),a.height=Math.max(1,Math.round(r.height*o));let l=a.getContext("2d");return l?(l.drawImage(s,r.x,r.y,r.width,r.height,0,0,a.width,a.height),new Promise((d,c)=>{try{a.toBlob(d,"image/webp",.95)}catch(u){c(u)}})):null}beginCreate(e){let i=this.matchingVideos();for(let t=i.length-1;t>=0;t-=1){let s=i[t];if(!s)continue;let r=z(s,e);if(!r)continue;let o=this.videoIdentity(s),a=`manual:${this.newObjectId()}`,l=`${o}:${a}`,d=Date.now(),c={time:s.currentTime,box:{left:r.x,top:r.y,width:0,height:0},score:1,source:"manual"},u=k(this.options.tracking),m={key:l,id:a,video:s,label:"object",origin:"manual",keyframes:[c],segments:[{start:s.currentTime}],anchors:[],presentationKeyframes:[u.smooth(c)],smoother:u,createdAt:d,updatedAt:d,misses:0,hits:0,analyzedThrough:c.time},h=!1,g=!1,p=()=>{if(g)return;g=!0,this.records.set(l,m);let f=this.videoKeys.get(s)??new Set;f.add(l),this.videoKeys.set(s,f)};return{key:l,update:f=>{if(h)return null;p();let b=z(s,f);return b&&(c.box={left:Math.min(r.x,b.x),top:Math.min(r.y,b.y),width:Math.abs(b.x-r.x),height:Math.abs(b.y-r.y)},m.smoother=k(this.options.tracking),m.presentationKeyframes=[m.smoother.smooth(c)]),this.resolve(l)},commit:()=>h?null:(p(),m.backwardSeedTime=c.time,this.activateTrackingRecord(m),this.persistVideo(s),this.startSession(m,!0).then(()=>this.scheduleBackwardAnalysis(m)),this.resolve(l)),cancel:()=>{h||(h=!0,g&&this.removeSubject(l))}}}return null}renameSubject(e,i){let t=this.records.get(e),s=i.trim();return!t||!s?null:(t.label=s,t.updatedAt=Date.now(),this.activateTrackingRecord(t),this.persistVideo(t.video),this.resolve(e))}updateSubjectBounds(e,i){let t=this.records.get(e);if(!t)return null;let s=Q(t.video,i);if(!s)return null;this.openSegment(t,t.video.currentTime),this.insertKeyframe(t,{time:t.video.currentTime,box:s,score:1,source:"manual"}),t.liveFrame=void 0,t.trackingFailed=!1,t.misses=0,t.hits=0,t.lostAt=void 0,t.analyzedThrough=t.video.currentTime;let r=x(t.segments,t.video.currentTime);return r&&Math.abs(r.start-t.video.currentTime)<=.05&&(t.backwardSeedTime=t.video.currentTime,this.cancelBackwardAnalysis(t)),this.activateTrackingRecord(t),this.persistVideo(t.video),this.startSession(t,!0).then(()=>this.reseed(t)).then(()=>this.scheduleBackwardAnalysis(t)),this.resolve(e)}updateSubjectTrackingAnchors(e,i){let t=this.records.get(e);return t?(t.anchors=i.slice(0,3).map(s=>({x:Math.max(0,Math.min(1,s.x)),y:Math.max(0,Math.min(1,s.y))})),t.updatedAt=Date.now(),t.trackingFailed=!1,t.analyzedThrough=t.video.currentTime,t.backwardSeedTime!==void 0&&this.cancelBackwardAnalysis(t),this.activateTrackingRecord(t),this.persistVideo(t.video),this.startSession(t,!0).then(()=>this.reseed(t)).then(()=>this.scheduleBackwardAnalysis(t)),this.resolve(e)):null}removeSubject(e){let i=this.records.get(e);if(!i)return;this.cancelBackwardAnalysis(i),i.session?.dispose?.(),this.activeTrackingKey===e&&(this.activeTrackingKey=null),this.records.delete(e);let t=this.videoKeys.get(i.video);t?.delete(e),t?.size===0&&this.videoKeys.delete(i.video),this.persistVideo(i.video)}async destroy(){if(this.destroyed)return;this.destroyed=!0,this.observer?.disconnect();for(let i of this.listeners.keys())this.removeVideoListeners(i);await Promise.all(Array.from(this.persistTimers.keys(),i=>this.flushScheduledPersistence(i)));let e=Array.from(this.records.values(),i=>i.backwardAnalysis?.promise).filter(i=>!!i);await Promise.allSettled(Array.from(this.records.values(),i=>(this.cancelBackwardAnalysis(i),i.session?.dispose?.()))),await Promise.allSettled(e),this.records.clear(),this.videoKeys.clear(),await Promise.allSettled(this.pendingWrites)}async analyze(e){let i=v(e);if(!(!i||this.analyzedSources.get(e)===i))try{if(await ye(e),this.destroyed||v(e)!==i)return;let t=this.videoIdentity(e),s=new URL(i,e.ownerDocument.baseURI).href,r=`${this.id}:${t}`,o=this.options.store?await this.options.store.load(r):null;if(this.destroyed||v(e)!==i)return;this.metadata.set(e,{storeKey:r,source:s,identity:t});let a=!!e.dataset.popmeltMediaId;o&&(o.source===s||a)?this.replaceVideoRecords(e,t,o.tracks):this.videoKeys.has(e)||this.videoKeys.set(e,new Set),this.analyzedSources.set(e,i),this.addVideoListeners(e)}catch(t){this.options.onError?.(t,e)}}addVideoListeners(e){if(this.listeners.has(e))return;let i=()=>{this.clearLiveFrames(e),this.activateMostRecentRecord(e);let o=this.activeRecordFor(e);if(this.options.tracking&&o&&!o.session&&(o.analyzedThrough===void 0||o.analyzedThrough<e.duration-M)){let a=this.startSession(o,!0);e.pause(),a.then(()=>{!this.destroyed&&o.session&&e.play()});return}o&&this.scheduleBackwardAnalysis(o),this.scheduleFrame(e)},t=()=>{this.clearLiveFrames(e);let o=this.activeRecordFor(e);o&&this.scheduleBackwardAnalysis(o),this.flushScheduledPersistence(e)},s=()=>{let o=this.activeRecordFor(e);o?.lastTrackedMediaTime!==void 0&&(o.analyzedThrough=e.duration,o.lastTrackedMediaTime=void 0,o.session?.dispose?.(),o.session=void 0,this.schedulePersistence(e)),t()},r=()=>{let o=this.activeRecordFor(e);if(this.clearLiveFrames(e),!o)return;let a=o.lastTrackedMediaTime;if(e.loop&&a!==void 0&&a>=e.duration-.25&&e.currentTime+.25<a&&(o.analyzedThrough??0)>=a-.25){o.analyzedThrough=e.duration,o.lastTrackedMediaTime=void 0;let l=o.session;o.session=void 0,Promise.resolve(o.tracking).finally(()=>l?.dispose?.()),this.schedulePersistence(e);return}o.session&&this.reseed(o)};e.addEventListener("play",i),e.addEventListener("pause",t),e.addEventListener("ended",s),e.addEventListener("seeked",r),this.listeners.set(e,()=>{e.removeEventListener("play",i),e.removeEventListener("pause",t),e.removeEventListener("ended",s),e.removeEventListener("seeked",r)}),e.paused||(this.activateMostRecentRecord(e),this.scheduleFrame(e))}removeVideoListeners(e){this.listeners.get(e)?.(),this.listeners.delete(e);let i=e,t=this.frameHandles.get(e);t!==void 0&&(i.cancelVideoFrameCallback?.(t),cancelAnimationFrame(t)),this.frameHandles.delete(e)}scheduleFrame(e){if(this.destroyed||e.paused||this.frameHandles.has(e))return;let i=e,t=(s,r)=>{this.frameHandles.delete(e),this.trackVideo(e,r.mediaTime),this.scheduleFrame(e)};i.requestVideoFrameCallback?this.frameHandles.set(e,i.requestVideoFrameCallback(t)):this.frameHandles.set(e,requestAnimationFrame(()=>t(performance.now(),{mediaTime:e.currentTime})))}async trackVideo(e,i){let t=this.activeRecordFor(e);if(!t||t.tracking||t.trackingFailed||t.analyzedThrough!==void 0&&i<=t.analyzedThrough+M)return;let s=this.options.tracking?.motion;if(!s)return;let r=s.attempt({state:X(t),time:i,maximumFramesPerSecond:Math.max(1,this.options.maxTrackingFramesPerSecond??Y)});t.lastTrackedMediaTime!==void 0&&Math.abs(i-t.lastTrackedMediaTime)<ge/r.framesPerSecond||(t.session||await this.startSession(t),!(!t.session||this.activeTrackingKey!==t.key)&&(t.lastTrackedMediaTime=i,t.tracking=t.session.track(e,i,r.tracking).then(o=>{if(this.destroyed||this.activeTrackingKey!==t.key)return;t.analyzedThrough=Math.max(t.analyzedThrough??i,i);let a=s.observe({state:X(t),time:i,observation:o});ve(t,a.state),o&&a.action==="reopen"&&this.openSegment(t,i),o&&(a.action==="accept"||a.action==="reopen")?this.acceptObservation(t,{...o,source:"tracked"}):a.action==="close"&&(t.liveFrame=void 0,this.closeSegment(t,t.keyframes[t.keyframes.length-1]?.time??i)),this.schedulePersistence(e)}).catch(o=>this.failTracking(t,o)).finally(()=>{t.tracking=void 0}),await t.tracking))}async startSession(e,i=!1){if(e.initializing){await e.initializing;return}if(!this.options.tracking||e.session||e.trackingFailed||this.activeTrackingKey!==e.key||e.video.paused&&!i)return;let t=P(e.keyframes,e.video.currentTime,e.segments);!t||e.video.readyState<2||(e.initializing=this.options.tracking.createSession({video:e.video,time:e.video.currentTime,box:t.box,anchors:e.anchors}).then(s=>{this.destroyed||this.activeTrackingKey!==e.key?s.dispose?.():e.session=s}).catch(s=>this.failTracking(e,s)).finally(()=>{e.initializing=void 0}),await e.initializing)}async reseed(e){let i=P(e.keyframes,e.video.currentTime,e.segments);if(!i){e.session?.dispose?.(),e.session=void 0,e.lostAt=e.video.currentTime,e.liveFrame=void 0,e.misses=0,e.hits=0;return}e.lostAt=void 0,e.misses=0,e.hits=0;try{e.session?.reseed&&await e.session.reseed({video:e.video,time:e.video.currentTime,box:i.box,anchors:e.anchors})}catch(t){this.failTracking(e,t)}}failTracking(e,i){e.trackingFailed=!0,e.liveFrame=void 0,e.session?.dispose?.(),e.session=void 0,this.options.onError?.(i,e.video)}activeRecordFor(e){if(!this.activeTrackingKey)return null;let i=this.records.get(this.activeTrackingKey);return i?.video===e?i:null}activateMostRecentRecord(e){if(this.activeRecordFor(e))return;let t=Array.from(this.videoKeys.get(e)??[]).map(s=>this.records.get(s)).filter(s=>!!s).sort((s,r)=>r.updatedAt-s.updatedAt)[0];t&&this.activateTrackingRecord(t)}activateTrackingRecord(e){if(this.activeTrackingKey===e.key)return;let i=this.activeTrackingKey?this.records.get(this.activeTrackingKey):void 0;this.activeTrackingKey=e.key,i&&(this.cancelBackwardAnalysis(i),i.session?.dispose?.(),i.session=void 0,i.lastTrackedMediaTime=void 0,i.liveFrame=void 0),e.liveFrame=void 0,e.trackingFailed=!1,e.lastTrackedMediaTime=void 0,e.misses=0,e.hits=0,e.lostAt=C(e)?e.video.currentTime:void 0}scheduleBackwardAnalysis(e){if(this.destroyed||!this.options.tracking||e.backwardSeedTime===void 0||e.backwardSeedTime<=M||e.backwardAnalysis||e.initializing||this.activeTrackingKey!==e.key)return;let i={cancelled:!1,promise:Promise.resolve()};e.backwardAnalysis=i,i.promise=this.runBackwardAnalysis(e,i).catch(t=>{i.cancelled||this.options.onError?.(t,e.video)}).finally(()=>{e.backwardAnalysis===i&&(e.backwardAnalysis=void 0,!i.cancelled&&e.backwardSeedTime!==void 0&&(e.backwardSeedTime=void 0),i.cancelled&&!this.destroyed&&this.activeTrackingKey===e.key&&queueMicrotask(()=>this.scheduleBackwardAnalysis(e)))})}cancelBackwardAnalysis(e){let i=e.backwardAnalysis;i&&(i.cancelled=!0)}async runBackwardAnalysis(e,i){let t=e.backwardSeedTime;if(t===void 0)return;let s=await this.options.tracking.motion.analyzeBackward({source:e.video,seedTime:t,keyframes:e.keyframes,anchors:e.anchors,maximumFramesPerSecond:this.options.maxTrackingFramesPerSecond??Y,cancelled:()=>i.cancelled||this.destroyed,forwardWork:()=>e.initializing??e.tracking});if(i.cancelled||this.destroyed)return;let r=x(e.segments,t);r&&(e.keyframes=s.keyframes,r.start=Math.min(r.start,s.earliestTime),e.updatedAt=Date.now(),this.rebuildPresentationTrack(e),this.schedulePersistence(e.video))}acceptObservation(e,i){let t=this.insertKeyframe(e,i);return e.video.paused||(e.liveFrame={...t,box:{...t.box}}),!0}openSegment(e,i){if(x(e.segments,i))return!1;let t=e.segments[e.segments.length-1];return t&&t.end===void 0&&i>=t.start?!1:(e.segments.push({start:i}),e.segments.sort((s,r)=>s.start-r.start),e.smoother=k(this.options.tracking),!0)}closeSegment(e,i){let t=[...e.segments].reverse().find(s=>s.end===void 0);return t?(t.end=Math.max(t.start,i),e.updatedAt=Date.now(),!0):!1}insertKeyframe(e,i){let t={...i,box:{...i.box}},s=e.keyframes.findIndex(o=>Math.abs(o.time-i.time)<.001),r=!1;if(s>=0)e.keyframes[s]=t;else{let o=e.keyframes[e.keyframes.length-1];if(i.source==="tracked"&&o&&Math.abs(i.time-o.time)<pe)e.keyframes[e.keyframes.length-1]=t;else if(!o||i.time>o.time){e.keyframes.push(t);let a=e.smoother.smooth(t);e.presentationKeyframes.push(a),r=!0}else e.keyframes.push(t)}return r||this.rebuildPresentationTrack(e),e.updatedAt=Date.now(),P(e.presentationKeyframes,i.time)??{...t,box:{...t.box}}}rebuildPresentationTrack(e){e.keyframes.sort((s,r)=>s.time-r.time);let i=k(this.options.tracking),t=null;e.presentationKeyframes=e.keyframes.map(s=>{let r=x(e.segments,s.time);return r&&r!==t&&(i=k(this.options.tracking),t=r),i.smooth(s)}),e.smoother=i}clearLiveFrames(e){for(let i of this.videoKeys.get(e)??[]){let t=this.records.get(i);t&&(t.liveFrame=void 0)}}videoObjectContext(e,i){let{video:t}=e,s=e.keyframes.map(r=>r.time);return{src:v(t),width:t.videoWidth,height:t.videoHeight,duration:t.duration,currentTime:t.currentTime,normalizedBox:{x:i.box.left,y:i.box.top,width:i.box.width,height:i.box.height},box:{x:i.box.left*t.videoWidth,y:i.box.top*t.videoHeight,width:i.box.width*t.videoWidth,height:i.box.height*t.videoHeight},trackStart:Math.min(...s),trackEnd:Math.max(...s)}}replaceVideoRecords(e,i,t){this.removeVideoRecords(e);let s=new Set;for(let r of t){let o=`${i}:${r.id}`,a=r.keyframes.map(m=>({...m,box:{...m.box}})),l=Se(a,r.segments),d=a[0],c=k(this.options.tracking);s.add(o);let u={key:o,id:r.id,video:e,label:r.label,origin:r.origin,keyframes:a,segments:l,anchors:(r.anchors??[]).map(m=>({...m})),presentationKeyframes:[],smoother:c,createdAt:r.createdAt,updatedAt:r.updatedAt,misses:0,hits:0,analyzedThrough:r.analyzedThrough,backwardSeedTime:d?.source==="manual"&&d.time>M&&(l[0]?.start??-1)>=d.time-M?d.time:void 0};C(u)&&(u.lostAt=e.currentTime),this.rebuildPresentationTrack(u),r.presentationKeyframes?.length&&(u.presentationKeyframes=r.presentationKeyframes.map(m=>({...m,box:{...m.box}}))),this.records.set(o,u)}this.videoKeys.set(e,s)}persistVideo(e){let i=this.persistTimers.get(e);i!==void 0&&clearTimeout(i),this.persistTimers.delete(e);let t=this.options.store,s=this.metadata.get(e);if(!t||!s)return Promise.resolve();let r=Array.from(this.videoKeys.get(e)??[]).map(d=>this.records.get(d)).filter(d=>!!d).map(d=>({id:d.id,label:d.label,origin:d.origin,keyframes:d.keyframes.map(c=>({...c,box:{...c.box}})),presentationKeyframes:d.presentationKeyframes.map(c=>({...c,box:{...c.box}})),anchors:d.anchors.map(c=>({...c})),segments:d.segments.map(c=>({...c})),analyzedThrough:d.analyzedThrough,createdAt:d.createdAt,updatedAt:d.updatedAt})),o={schemaVersion:3,source:s.source,duration:Number.isFinite(e.duration)?e.duration:0,tracks:r,updatedAt:Date.now()},l=(this.writeChains.get(e)??Promise.resolve()).catch(()=>{}).then(()=>t.save(s.storeKey,o)).catch(d=>this.options.onError?.(d,e));return this.writeChains.set(e,l),this.pendingWrites.add(l),l.finally(()=>this.pendingWrites.delete(l)),l}schedulePersistence(e){!this.options.store||this.persistTimers.has(e)||this.persistTimers.set(e,setTimeout(()=>{this.persistTimers.delete(e),this.persistVideo(e)},fe))}flushScheduledPersistence(e){return this.persistTimers.has(e)?this.persistVideo(e):Promise.resolve()}matchingVideos(){let e=this.options.root??document,i=this.options.selector??he,t=[];e instanceof HTMLVideoElement&&e.matches(i)&&t.push(e);for(let s of e.querySelectorAll(i))s instanceof HTMLVideoElement&&t.push(s);return t}videoIdentity(e){if(e.dataset.popmeltMediaId)return e.dataset.popmeltMediaId;let i=new URL(v(e),e.ownerDocument.baseURI).href,t=this.matchingVideos().filter(s=>v(s)===v(e));return`${J(i)}:${Math.max(0,t.indexOf(e))}`}newObjectId(){return globalThis.crypto?.randomUUID?.()??J(`${Date.now()}:${this.manualSequence++}:${Math.random()}`)}removeVideoRecords(e){for(let i of this.videoKeys.get(e)??[]){let t=this.records.get(i);t&&this.cancelBackwardAnalysis(t),t?.session?.dispose?.(),this.activeTrackingKey===i&&(this.activeTrackingKey=null),this.records.delete(i)}this.videoKeys.delete(e)}removeVideo(e){this.removeVideoListeners(e),this.flushScheduledPersistence(e),this.removeVideoRecords(e),this.metadata.delete(e),this.analyzedSources.delete(e)}queueRefresh(){this.refreshQueued||this.destroyed||(this.refreshQueued=!0,queueMicrotask(()=>{this.refreshQueued=!1,this.readyPromise=this.refresh()}))}};function Re(n={}){return new $(n)}var Te="popmelt:media:video:v1";function Z(n){if(!n||typeof n!="object")return!1;let e=n;return["left","top","width","height"].every(i=>typeof e[i]=="number"&&Number.isFinite(e[i]))}function ke(n){if(!n||typeof n!="object")return!1;let e=n;return typeof e.start=="number"&&Number.isFinite(e.start)&&(e.end===void 0||typeof e.end=="number"&&Number.isFinite(e.end)&&e.end>=e.start)}function xe(n){if(!n||typeof n!="object")return!1;let e=n;return(e.schemaVersion===1||e.schemaVersion===2||e.schemaVersion===3)&&typeof e.source=="string"&&typeof e.duration=="number"&&typeof e.updatedAt=="number"&&Array.isArray(e.tracks)&&e.tracks.every(i=>{if(!i||typeof i!="object")return!1;let t=i;return typeof t.id=="string"&&typeof t.label=="string"&&(t.origin==="manual"||t.origin==="detected")&&typeof t.createdAt=="number"&&typeof t.updatedAt=="number"&&(t.analyzedThrough===void 0||typeof t.analyzedThrough=="number"&&Number.isFinite(t.analyzedThrough))&&(t.segments===void 0||Array.isArray(t.segments)&&t.segments.every(ke))&&Array.isArray(t.keyframes)&&t.keyframes.every(s=>{if(!s||typeof s!="object")return!1;let r=s;return typeof r.time=="number"&&typeof r.score=="number"&&(r.source==="manual"||r.source==="tracked")&&Z(r.box)})&&(t.presentationKeyframes===void 0||Array.isArray(t.presentationKeyframes)&&t.presentationKeyframes.every(s=>{if(!s||typeof s!="object")return!1;let r=s;return typeof r.time=="number"&&typeof r.score=="number"&&(r.source==="manual"||r.source==="tracked")&&Z(r.box)}))})}function Oe(n={}){let e=n.namespace??Te,i=()=>n.storage??window.localStorage,t=s=>`${e}:${s}`;return{load(s){try{let r=i().getItem(t(s));if(!r)return null;let o=JSON.parse(r);return xe(o)?o:null}catch{return null}},save(s,r){i().setItem(t(s),JSON.stringify(r))},remove(s){i().removeItem(t(s))}}}function Fe(){let n=new Map;return{load:e=>n.get(e)??null,save:(e,i)=>{n.set(e,i)},remove:e=>{n.delete(e)}}}export{E as a,N as b,H as c,Ie as d,je as e,O as f,Le as g,z as h,q as i,Q as j,$ as k,Re as l,Oe as m,Fe as n};
|