@vosjs/studio-core 0.47.0 → 0.48.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/dist/index.d.ts CHANGED
@@ -404,12 +404,26 @@ interface RecordingMeta {
404
404
  pageUrl?: string;
405
405
  pageTitle?: string;
406
406
  /**
407
- * What the frame contains. Absent = 'tab' (back-compat). Non-tab surfaces use
408
- * CursorEvent.sx/sy + the geometry rects below to map cursor → capture px
409
- * (see normalizeCaptureSpace); tab-only studio features (browser-bar mock,
410
- * letterbox notice) are gated off for them.
407
+ * The application an `'app'` take recorded, where a page take says
408
+ * `pageUrl`: its name as the OS shows it, and its bundle id or executable
409
+ * name. Never a window title, which carries document and account names.
411
410
  */
412
- captureSurface?: 'tab' | 'window' | 'monitor';
411
+ app?: {
412
+ name: string;
413
+ id?: string;
414
+ };
415
+ /**
416
+ * What the frame contains. Absent = 'tab' (back-compat). `'window'` and
417
+ * `'monitor'` are a BROWSER's display captures: they use CursorEvent.sx/sy +
418
+ * the geometry rects below to map cursor → capture px (see
419
+ * normalizeCaptureSpace), and tab-only studio features (browser-bar mock,
420
+ * letterbox notice) are gated off for them. `'app'` is one application's
421
+ * window recorded by a desktop producer: the frame IS the window, the cursor
422
+ * is already in the frame's own space (`width × height` are the window's
423
+ * points, `captureWidth × captureHeight` its pixels), and the footage
424
+ * carries the window's own title bar, so no bar is drawn over it.
425
+ */
426
+ captureSurface?: 'tab' | 'window' | 'monitor' | 'app';
413
427
  /**
414
428
  * Target-tab browser-window bounds at record start, screen-coord CSS px
415
429
  * (window.screenX/Y + outerWidth/Height). Anchor for 'window' captures.
@@ -463,10 +477,12 @@ interface RecordingMeta {
463
477
  * track from automation (exact coords, fresh rects, coverage 1 by
464
478
  * construction) and encode WebM; `ingest` is someone else's recording
465
479
  * brought in as a take (`vos ingest`, or a file dropped on the studio),
466
- * whose cursor track, if any, came from a trace beside it; absent means
480
+ * whose cursor track, if any, came from a trace beside it; `desktop` is a
481
+ * capture helper recording an application's window, its cursor either
482
+ * sampled from the real pointer or synthesized from a script; absent means
467
483
  * the extension.
468
484
  */
469
- producer?: 'extension' | 'cli' | 'ingest';
485
+ producer?: 'extension' | 'cli' | 'ingest' | 'desktop';
470
486
  /**
471
487
  * The step timeline: when each actions.json step ran, in SOURCE
472
488
  * seconds. This is what makes a cut re-anchorable across re-records — a
@@ -3705,6 +3721,8 @@ interface DigestTakeFacts {
3705
3721
  producer: string;
3706
3722
  pageUrl: string | null;
3707
3723
  pageTitle: string | null;
3724
+ /** The recorded application's name, on an `'app'` take. */
3725
+ app: string | null;
3708
3726
  hasMic: boolean;
3709
3727
  hasSystemAudio: boolean;
3710
3728
  hasCursor: boolean;
package/dist/index.js CHANGED
@@ -506,7 +506,8 @@ function deriveViewportCrop(cursor, meta) {
506
506
  }
507
507
  function normalizeCaptureSpace(cursor, meta) {
508
508
  const surface = meta.captureSurface ?? "tab";
509
- if (surface === "tab") return { cursor, meta, coverage: 1 };
509
+ if (surface === "tab" || surface === "app")
510
+ return { cursor, meta, coverage: 1 };
510
511
  const anchor = surface === "window" ? meta.windowRect : meta.screenRect;
511
512
  const capW = meta.captureWidth ?? 0;
512
513
  const capH = meta.captureHeight ?? 0;
@@ -620,11 +621,12 @@ function projectFromArtifact(artifact, videoUrl, opts = {}) {
620
621
  const norm = normalizeCaptureSpace(artifact.cursor, artifact.meta);
621
622
  const { cursor, meta } = norm;
622
623
  const unfocused = surface === "window" && (artifact.meta.windowFocusedFrac ?? 1) < WINDOW_FOCUS_MIN;
623
- const coverage = surface === "monitor" || artifact.meta.windowMovedDuringTake || unfocused ? 0 : norm.coverage;
624
+ const movedAnchor = surface !== "app" && artifact.meta.windowMovedDuringTake === true;
625
+ const coverage = surface === "monitor" || movedAnchor || unfocused ? 0 : norm.coverage;
624
626
  if (artifact.cursor.length > 0 && coverage < CAPTURE_COVERAGE_MIN) {
625
627
  console.warn(
626
628
  "[studio] dropping cursor track \u2014",
627
- surface === "monitor" ? "entire-screen takes have no cursor effects (untrackable outside browser pages)" : artifact.meta.windowMovedDuringTake ? "window moved/resized during the take" : unfocused ? `browser window focused only ${Math.round((artifact.meta.windowFocusedFrac ?? 0) * 100)}% of the take \u2014 a different window was likely shared` : `coverage ${norm.coverage.toFixed(2)} (wrong surface shared, or unusable capture geometry)`
629
+ surface === "monitor" ? "entire-screen takes have no cursor effects (untrackable outside browser pages)" : movedAnchor ? "window moved/resized during the take" : unfocused ? `browser window focused only ${Math.round((artifact.meta.windowFocusedFrac ?? 0) * 100)}% of the take \u2014 a different window was likely shared` : `coverage ${norm.coverage.toFixed(2)} (wrong surface shared, or unusable capture geometry)`
628
630
  );
629
631
  }
630
632
  const doc = {
@@ -10774,6 +10776,7 @@ function buildDigest(input) {
10774
10776
  producer: meta.producer ?? "extension",
10775
10777
  pageUrl: meta.pageUrl ?? null,
10776
10778
  pageTitle: meta.pageTitle ?? null,
10779
+ app: meta.app?.name ?? null,
10777
10780
  hasMic: Boolean(doc.source.micKey) || meta.hasMic === true,
10778
10781
  hasSystemAudio: meta.hasAudio === true,
10779
10782
  hasCursor: doc.source.cursor.length > 0,