@kubohiroya/turbowarp-realtime-motion-capture 0.2.1 → 0.4.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.ja.md CHANGED
@@ -14,13 +14,13 @@ multiview pose estimationを使うcamera/fusion application向けの複合Turb
14
14
  - WebGPU MoveNet MultiPoseで最大6人を追跡し、PoseFrame2D v1/v2 JSONを返します。
15
15
  - このpackageが所有するmultiview-pose JSON contractを検証します。
16
16
  - chessboardとOpenCV.jsで共有cameraをcalibrationします。
17
- - 外部PoseFrame3D v1を宣言的なA-Frame avatar rigへretargetします。
17
+ - 外部PoseFrame3D v1をA-FrameのVRMアバターへretargetします。
18
18
  - camera timingを計測し、同期した2D poseを3Dへ統合して、サイリウムで演者を識別します。
19
19
 
20
20
  ## 要件と安全性
21
21
 
22
22
  - 信頼できるunsandboxed custom extensionを利用できるTurboWarp
23
- - QR/時刻用WebRTC 0.3.0、video用Camera Source 0.5.0、avatar用A-Frame 0.3.0
23
+ - QR/時刻用WebRTC 0.3.0、video用Camera Source 0.5.0、avatar用A-Frame 0.4.0
24
24
  - 姿勢推定用TensorFlow.js WebGPUとcalibration用WebAssembly
25
25
 
26
26
  全機能は起動時固定・既定OFFです。MoveNetにCPU/WASM/WebGL fallbackはなく、初回model loadは
@@ -37,7 +37,7 @@ custom extensionとして読み込みます。通常の順序はCamera Source、
37
37
  version固定CDN URL:
38
38
 
39
39
  ```text
40
- https://cdn.jsdelivr.net/npm/@kubohiroya/turbowarp-realtime-motion-capture@0.2.0/dist/turbowarp-realtime-motion-capture.js
40
+ https://cdn.jsdelivr.net/npm/@kubohiroya/turbowarp-realtime-motion-capture@0.4.0/dist/turbowarp-realtime-motion-capture.js
41
41
  ```
42
42
 
43
43
  npm packageが公開するのはbrowser向けstandalone bundle、schema、文書です。Composition APIは
package/README.md CHANGED
@@ -14,13 +14,13 @@ Composite TurboWarp blocks for camera and fusion applications using multiview po
14
14
  - Runs WebGPU MoveNet MultiPose for up to six people and reports PoseFrame2D v1/v2 JSON.
15
15
  - Validates the owned multiview-pose JSON contracts.
16
16
  - Calibrates shared cameras with a chessboard and OpenCV.js.
17
- - Retargets external PoseFrame3D v1 data to declarative A-Frame avatar rigs.
17
+ - Retargets external PoseFrame3D v1 data to VRM avatars in A-Frame.
18
18
  - Measures camera timing, fuses synchronized 2D poses into 3D, and identifies performers by glow sticks.
19
19
 
20
20
  ## Requirements and safety
21
21
 
22
22
  - TurboWarp with trusted unsandboxed custom extensions enabled.
23
- - WebRTC 0.3.0 for QR/time, Camera Source 0.5.0 for video, and A-Frame 0.3.0 for avatars.
23
+ - WebRTC 0.3.0 for QR/time, Camera Source 0.5.0 for video, and A-Frame 0.4.0 for avatars.
24
24
  - TensorFlow.js WebGPU support for pose and WebAssembly support for calibration.
25
25
 
26
26
  All features are startup-fixed and OFF by default. MoveNet has no CPU, WASM, or WebGL fallback and
@@ -35,7 +35,7 @@ extension. The usual order is Camera Source, WebRTC, A-Frame, then Realtime Moti
35
35
  not used may be omitted. A version-pinned package URL is:
36
36
 
37
37
  ```text
38
- https://cdn.jsdelivr.net/npm/@kubohiroya/turbowarp-realtime-motion-capture@0.2.1/dist/turbowarp-realtime-motion-capture.js
38
+ https://cdn.jsdelivr.net/npm/@kubohiroya/turbowarp-realtime-motion-capture@0.4.0/dist/turbowarp-realtime-motion-capture.js
39
39
  ```
40
40
 
41
41
  The npm package distributes a standalone browser bundle, schemas, and documentation. It does not
@@ -5,6 +5,22 @@ export interface MultiviewPoseFeatureFlags {
5
5
  readonly cameraCalibrationV1: boolean;
6
6
  readonly avatarRetargetV1: boolean;
7
7
  readonly frameSyncPatternV1: boolean;
8
+ /**
9
+ * Hand the optical time path to turbowarp-time-space-sync.
10
+ *
11
+ * Independent of `cameraCalibrationV1` and its own delegation: during the
12
+ * move one path can be delegated while the other is not, and both states are
13
+ * legitimate.
14
+ */
15
+ readonly timeSpaceSyncDelegateV1: boolean;
16
+ /**
17
+ * Keep calibration profiles in Camera Source's shared registry.
18
+ *
19
+ * Only the profile half. Running a calibration stays here until
20
+ * turbowarp-camera-calibration publishes a way for another extension to ask
21
+ * it to.
22
+ */
23
+ readonly cameraCalibrationDelegateV1: boolean;
8
24
  readonly poseFusion3D: boolean;
9
25
  readonly glowStickMarkers: boolean;
10
26
  }
@@ -15,6 +31,43 @@ interface FeatureFlagGlobal {
15
31
 
16
32
  const overrides = (globalThis as FeatureFlagGlobal).__TWMP_FEATURE_FLAGS__;
17
33
 
34
+ /**
35
+ * Pairs where one flag runs the old path and the other hands it away.
36
+ *
37
+ * Turning both on runs two implementations of the same thing at once: two
38
+ * leases on one camera, two overlays covering the screen, two corrections
39
+ * applied to the same observation. None of those announce themselves -- a
40
+ * second lease is granted, a second overlay is drawn on top of the first, a
41
+ * doubled correction is a plausible number -- so the combination is refused
42
+ * before anything starts rather than diagnosed afterwards.
43
+ */
44
+ const exclusivePairs: ReadonlyArray<
45
+ readonly [keyof MultiviewPoseFeatureFlags, keyof MultiviewPoseFeatureFlags]
46
+ > = [
47
+ ["frameSyncPatternV1", "timeSpaceSyncDelegateV1"],
48
+ ["cameraCalibrationV1", "cameraCalibrationDelegateV1"],
49
+ ];
50
+
51
+ /**
52
+ * Refuses a combination that would run two implementations of one thing.
53
+ *
54
+ * Called when the extension is built rather than when this module loads: a
55
+ * throw during module evaluation gives TurboWarp nothing to show the operator,
56
+ * and the message is the only thing that explains what to change.
57
+ */
58
+ export function requireConsistentFeatureFlags(
59
+ flags: MultiviewPoseFeatureFlags = featureFlags,
60
+ ): MultiviewPoseFeatureFlags {
61
+ for (const [older, delegate] of exclusivePairs) {
62
+ if (flags[older] && flags[delegate]) {
63
+ throw new Error(
64
+ `${older} and ${delegate} are both on. One runs the path here and the other hands it to another extension; together they lease the same camera twice and draw two overlays. Turn off ${older} to delegate, or ${delegate} to keep the path here.`,
65
+ );
66
+ }
67
+ }
68
+ return flags;
69
+ }
70
+
18
71
  /** Startup-fixed flags. Experimental QR and pose paths stay independently opt-in. */
19
72
  export const featureFlags: MultiviewPoseFeatureFlags = Object.freeze({
20
73
  qrCourierPairing: overrides?.qrCourierPairing === true,
@@ -23,6 +76,8 @@ export const featureFlags: MultiviewPoseFeatureFlags = Object.freeze({
23
76
  cameraCalibrationV1: overrides?.cameraCalibrationV1 === true,
24
77
  avatarRetargetV1: overrides?.avatarRetargetV1 === true,
25
78
  frameSyncPatternV1: overrides?.frameSyncPatternV1 === true,
79
+ timeSpaceSyncDelegateV1: overrides?.timeSpaceSyncDelegateV1 === true,
80
+ cameraCalibrationDelegateV1: overrides?.cameraCalibrationDelegateV1 === true,
26
81
  poseFusion3D: overrides?.poseFusion3D === true,
27
82
  glowStickMarkers: overrides?.glowStickMarkers === true,
28
83
  });
@@ -2,6 +2,11 @@
2
2
  "formatVersion": 1,
3
3
  "id": "kubohiroyarealtimemotioncapture",
4
4
  "blocks": [
5
+ {
6
+ "opcode": "acknowledgeFrameSyncFlashing",
7
+ "blockType": "COMMAND",
8
+ "arguments": []
9
+ },
5
10
  {
6
11
  "opcode": "addCameraCalibrationSample",
7
12
  "blockType": "COMMAND",
@@ -312,6 +317,16 @@
312
317
  }
313
318
  ]
314
319
  },
320
+ {
321
+ "opcode": "inferPoseCameraAtFrameTime",
322
+ "blockType": "COMMAND",
323
+ "arguments": [
324
+ {
325
+ "id": "CAMERA_ID",
326
+ "type": "STRING"
327
+ }
328
+ ]
329
+ },
315
330
  {
316
331
  "opcode": "latestPoseFrame2D",
317
332
  "blockType": "REPORTER",
@@ -372,6 +387,26 @@
372
387
  "blockType": "REPORTER",
373
388
  "arguments": []
374
389
  },
390
+ {
391
+ "opcode": "poseCameraFrame2D",
392
+ "blockType": "REPORTER",
393
+ "arguments": [
394
+ {
395
+ "id": "CAMERA_ID",
396
+ "type": "STRING"
397
+ }
398
+ ]
399
+ },
400
+ {
401
+ "opcode": "poseCameraStatusJson",
402
+ "blockType": "REPORTER",
403
+ "arguments": [
404
+ {
405
+ "id": "CAMERA_ID",
406
+ "type": "STRING"
407
+ }
408
+ ]
409
+ },
375
410
  {
376
411
  "opcode": "poseError",
377
412
  "blockType": "REPORTER",
@@ -490,7 +525,7 @@
490
525
  "type": "STRING"
491
526
  },
492
527
  {
493
- "id": "TEMPLATE_JSON",
528
+ "id": "VRM_URL",
494
529
  "type": "STRING"
495
530
  }
496
531
  ]
@@ -500,6 +535,16 @@
500
535
  "blockType": "COMMAND",
501
536
  "arguments": []
502
537
  },
538
+ {
539
+ "opcode": "setFrameSyncDisplayRefresh",
540
+ "blockType": "COMMAND",
541
+ "arguments": [
542
+ {
543
+ "id": "REFRESH_US",
544
+ "type": "NUMBER"
545
+ }
546
+ ]
547
+ },
503
548
  {
504
549
  "opcode": "setPerformerGlowStick",
505
550
  "blockType": "COMMAND",
@@ -583,6 +628,24 @@
583
628
  }
584
629
  ]
585
630
  },
631
+ {
632
+ "opcode": "startPoseCamera",
633
+ "blockType": "COMMAND",
634
+ "arguments": [
635
+ {
636
+ "id": "CALIBRATION_ID",
637
+ "type": "STRING"
638
+ },
639
+ {
640
+ "id": "CAMERA_ID",
641
+ "type": "STRING"
642
+ },
643
+ {
644
+ "id": "PEER_ID",
645
+ "type": "STRING"
646
+ }
647
+ ]
648
+ },
586
649
  {
587
650
  "opcode": "startPoseFusion",
588
651
  "blockType": "COMMAND",
@@ -619,11 +682,26 @@
619
682
  }
620
683
  ]
621
684
  },
685
+ {
686
+ "opcode": "stopAllPoseCameras",
687
+ "blockType": "COMMAND",
688
+ "arguments": []
689
+ },
622
690
  {
623
691
  "opcode": "stopFrameSyncDecoder",
624
692
  "blockType": "COMMAND",
625
693
  "arguments": []
626
694
  },
695
+ {
696
+ "opcode": "stopPoseCamera",
697
+ "blockType": "COMMAND",
698
+ "arguments": [
699
+ {
700
+ "id": "CAMERA_ID",
701
+ "type": "STRING"
702
+ }
703
+ ]
704
+ },
627
705
  {
628
706
  "opcode": "stopPoseFusion",
629
707
  "blockType": "COMMAND",