@vizor-vr/player 0.2.0 → 0.2.1

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.
Files changed (184) hide show
  1. package/README.md +4 -0
  2. package/dist/__tests__/autoplay.test.d.ts +2 -0
  3. package/dist/__tests__/autoplay.test.d.ts.map +1 -0
  4. package/dist/__tests__/chapter-logic.test.d.ts +2 -0
  5. package/dist/__tests__/chapter-logic.test.d.ts.map +1 -0
  6. package/dist/__tests__/chapter-manager.test.d.ts +2 -0
  7. package/dist/__tests__/chapter-manager.test.d.ts.map +1 -0
  8. package/dist/__tests__/chapter-menu.test.d.ts +2 -0
  9. package/dist/__tests__/chapter-menu.test.d.ts.map +1 -0
  10. package/dist/__tests__/dom-drm.test.d.ts +2 -0
  11. package/dist/__tests__/dom-drm.test.d.ts.map +1 -0
  12. package/dist/__tests__/drm-gate.test.d.ts +2 -0
  13. package/dist/__tests__/drm-gate.test.d.ts.map +1 -0
  14. package/dist/__tests__/fairplay.test.d.ts +2 -0
  15. package/dist/__tests__/fairplay.test.d.ts.map +1 -0
  16. package/dist/__tests__/hub-controller.test.d.ts +2 -0
  17. package/dist/__tests__/hub-controller.test.d.ts.map +1 -0
  18. package/dist/__tests__/hub-layout.test.d.ts +2 -0
  19. package/dist/__tests__/hub-layout.test.d.ts.map +1 -0
  20. package/dist/__tests__/hub-model.test.d.ts +2 -0
  21. package/dist/__tests__/hub-model.test.d.ts.map +1 -0
  22. package/dist/__tests__/hub-panel-renderer.test.d.ts +2 -0
  23. package/dist/__tests__/hub-panel-renderer.test.d.ts.map +1 -0
  24. package/dist/__tests__/lens-angle.test.d.ts +2 -0
  25. package/dist/__tests__/lens-angle.test.d.ts.map +1 -0
  26. package/dist/__tests__/media-element-drm-gate.test.d.ts +2 -0
  27. package/dist/__tests__/media-element-drm-gate.test.d.ts.map +1 -0
  28. package/dist/__tests__/media-element-gating.test.d.ts +2 -0
  29. package/dist/__tests__/media-element-gating.test.d.ts.map +1 -0
  30. package/dist/__tests__/player-version-lock.test.d.ts +2 -0
  31. package/dist/__tests__/player-version-lock.test.d.ts.map +1 -0
  32. package/dist/__tests__/source-manager-drm.test.d.ts +2 -0
  33. package/dist/__tests__/source-manager-drm.test.d.ts.map +1 -0
  34. package/dist/__tests__/vz-chapter.test.d.ts +2 -0
  35. package/dist/__tests__/vz-chapter.test.d.ts.map +1 -0
  36. package/dist/__tests__/vz-cinema-gating.test.d.ts +2 -0
  37. package/dist/__tests__/vz-cinema-gating.test.d.ts.map +1 -0
  38. package/dist/__tests__/vz-hub-item.test.d.ts +2 -0
  39. package/dist/__tests__/vz-hub-item.test.d.ts.map +1 -0
  40. package/dist/__tests__/vz-tour-gating.test.d.ts +2 -0
  41. package/dist/__tests__/vz-tour-gating.test.d.ts.map +1 -0
  42. package/dist/__tests__/watch-time.test.d.ts +2 -0
  43. package/dist/__tests__/watch-time.test.d.ts.map +1 -0
  44. package/dist/analytics/index.d.ts.map +1 -1
  45. package/dist/annotations/annotation-popup.d.ts.map +1 -1
  46. package/dist/{annotations-C0ugfCn4.js → annotations-Du6ZWrqC.js} +82 -13
  47. package/dist/annotations-Du6ZWrqC.js.map +1 -0
  48. package/dist/captions/caption-renderer.d.ts.map +1 -1
  49. package/dist/{captions-BP0H2E03.js → captions-YvnHAwLY.js} +4 -4
  50. package/dist/captions-YvnHAwLY.js.map +1 -0
  51. package/dist/chapters/chapter-logic.d.ts +47 -0
  52. package/dist/chapters/chapter-logic.d.ts.map +1 -0
  53. package/dist/chapters/chapter-manager.d.ts +42 -0
  54. package/dist/chapters/chapter-manager.d.ts.map +1 -0
  55. package/dist/chapters/chapter-menu.d.ts +24 -0
  56. package/dist/chapters/chapter-menu.d.ts.map +1 -0
  57. package/dist/{collab-BXPomrS0.js → collab-BLpllHtb.js} +20 -14
  58. package/dist/collab-BLpllHtb.js.map +1 -0
  59. package/dist/collaborative/chat-button.d.ts.map +1 -1
  60. package/dist/collaborative/voice-button.d.ts.map +1 -1
  61. package/dist/controls/cc-button.d.ts.map +1 -1
  62. package/dist/controls/compass.d.ts.map +1 -1
  63. package/dist/controls/controls-overlay.d.ts.map +1 -1
  64. package/dist/controls/fullscreen-button.d.ts.map +1 -1
  65. package/dist/controls/icons.d.ts +1 -0
  66. package/dist/controls/icons.d.ts.map +1 -1
  67. package/dist/controls/live-indicator.d.ts.map +1 -1
  68. package/dist/controls/play-button.d.ts.map +1 -1
  69. package/dist/controls/playlist-controls.d.ts.map +1 -1
  70. package/dist/controls/quality-menu.d.ts.map +1 -1
  71. package/dist/controls/seek-bar.d.ts +9 -0
  72. package/dist/controls/seek-bar.d.ts.map +1 -1
  73. package/dist/controls/volume-control.d.ts.map +1 -1
  74. package/dist/controls/vr-button.d.ts.map +1 -1
  75. package/dist/core/base-element.d.ts +8 -0
  76. package/dist/core/base-element.d.ts.map +1 -1
  77. package/dist/core/media-element.d.ts +70 -1
  78. package/dist/core/media-element.d.ts.map +1 -1
  79. package/dist/{dash-adapter-tid9ZyhO.js → dash-adapter-BMpHWcBA.js} +9 -2
  80. package/dist/dash-adapter-BMpHWcBA.js.map +1 -0
  81. package/dist/delivery/__tests__/delivery-client.test.d.ts +2 -0
  82. package/dist/delivery/__tests__/delivery-client.test.d.ts.map +1 -0
  83. package/dist/delivery/__tests__/delivery-hydrate.test.d.ts +2 -0
  84. package/dist/delivery/__tests__/delivery-hydrate.test.d.ts.map +1 -0
  85. package/dist/delivery/delivery-client.d.ts +27 -0
  86. package/dist/delivery/delivery-client.d.ts.map +1 -0
  87. package/dist/delivery/delivery-hydrate.d.ts +18 -0
  88. package/dist/delivery/delivery-hydrate.d.ts.map +1 -0
  89. package/dist/delivery/dom-drm.d.ts +9 -0
  90. package/dist/delivery/dom-drm.d.ts.map +1 -0
  91. package/dist/elements/vz-chapter.d.ts +27 -0
  92. package/dist/elements/vz-chapter.d.ts.map +1 -0
  93. package/dist/elements/vz-cinema.d.ts +20 -0
  94. package/dist/elements/vz-cinema.d.ts.map +1 -1
  95. package/dist/elements/vz-hub-item.d.ts +23 -0
  96. package/dist/elements/vz-hub-item.d.ts.map +1 -0
  97. package/dist/elements/vz-hub.d.ts +57 -0
  98. package/dist/elements/vz-hub.d.ts.map +1 -0
  99. package/dist/elements/vz-playlist.d.ts +14 -0
  100. package/dist/elements/vz-playlist.d.ts.map +1 -1
  101. package/dist/elements/vz-tour.d.ts +16 -0
  102. package/dist/elements/vz-tour.d.ts.map +1 -1
  103. package/dist/hls-adapter-C_a65zia.js +161 -0
  104. package/dist/hls-adapter-C_a65zia.js.map +1 -0
  105. package/dist/hub/hub-controller.d.ts +31 -0
  106. package/dist/hub/hub-controller.d.ts.map +1 -0
  107. package/dist/hub/hub-layout.d.ts +23 -0
  108. package/dist/hub/hub-layout.d.ts.map +1 -0
  109. package/dist/hub/hub-model.d.ts +27 -0
  110. package/dist/hub/hub-model.d.ts.map +1 -0
  111. package/dist/hub/hub-panel-manager.d.ts +16 -0
  112. package/dist/hub/hub-panel-manager.d.ts.map +1 -0
  113. package/dist/hub/hub-panel-renderer.d.ts +26 -0
  114. package/dist/hub/hub-panel-renderer.d.ts.map +1 -0
  115. package/dist/license/__tests__/cache.test.d.ts +2 -0
  116. package/dist/license/__tests__/cache.test.d.ts.map +1 -0
  117. package/dist/license/__tests__/feature-gate.test.d.ts +2 -0
  118. package/dist/license/__tests__/feature-gate.test.d.ts.map +1 -0
  119. package/dist/license/__tests__/format-gate.test.d.ts +2 -0
  120. package/dist/license/__tests__/format-gate.test.d.ts.map +1 -0
  121. package/dist/license/__tests__/license-checker.test.d.ts.map +1 -0
  122. package/dist/license/__tests__/master-key.test.d.ts.map +1 -0
  123. package/dist/license/__tests__/verify-no-ed25519.test.d.ts +2 -0
  124. package/dist/license/__tests__/verify-no-ed25519.test.d.ts.map +1 -0
  125. package/dist/license/__tests__/verify.test.d.ts +2 -0
  126. package/dist/license/__tests__/verify.test.d.ts.map +1 -0
  127. package/dist/license/cache.d.ts +4 -0
  128. package/dist/license/cache.d.ts.map +1 -0
  129. package/dist/license/drm-gate.d.ts +15 -0
  130. package/dist/license/drm-gate.d.ts.map +1 -0
  131. package/dist/license/feature-gate.d.ts +27 -0
  132. package/dist/license/feature-gate.d.ts.map +1 -0
  133. package/dist/license/format-gate.d.ts +23 -0
  134. package/dist/license/format-gate.d.ts.map +1 -0
  135. package/dist/license/license-checker.d.ts.map +1 -1
  136. package/dist/license/master-key.d.ts +11 -7
  137. package/dist/license/master-key.d.ts.map +1 -1
  138. package/dist/license/trusted-key.d.ts +7 -0
  139. package/dist/license/trusted-key.d.ts.map +1 -0
  140. package/dist/license/verify.d.ts +7 -0
  141. package/dist/license/verify.d.ts.map +1 -0
  142. package/dist/{register-CwnmiGEs.js → register-BmZt_300.js} +1482 -163
  143. package/dist/register-BmZt_300.js.map +1 -0
  144. package/dist/register.d.ts.map +1 -1
  145. package/dist/register.js +1 -1
  146. package/dist/renderer/camera-controller.d.ts +1 -1
  147. package/dist/renderer/camera-controller.d.ts.map +1 -1
  148. package/dist/renderer/projections/fisheye-projection.d.ts +4 -0
  149. package/dist/renderer/projections/fisheye-projection.d.ts.map +1 -1
  150. package/dist/renderer/projections/spherical-projection.d.ts +26 -0
  151. package/dist/renderer/projections/spherical-projection.d.ts.map +1 -0
  152. package/dist/renderer/renderer.d.ts.map +1 -1
  153. package/dist/renderer/shaders/fisheye.glsl.d.ts +10 -1
  154. package/dist/renderer/shaders/fisheye.glsl.d.ts.map +1 -1
  155. package/dist/sri.json +8 -8
  156. package/dist/streaming/dash-adapter.d.ts +2 -2
  157. package/dist/streaming/dash-adapter.d.ts.map +1 -1
  158. package/dist/streaming/fairplay.d.ts +21 -0
  159. package/dist/streaming/fairplay.d.ts.map +1 -0
  160. package/dist/streaming/hls-adapter.d.ts +2 -2
  161. package/dist/streaming/hls-adapter.d.ts.map +1 -1
  162. package/dist/streaming/progressive-adapter.d.ts +2 -2
  163. package/dist/streaming/progressive-adapter.d.ts.map +1 -1
  164. package/dist/streaming/source-manager.d.ts +3 -1
  165. package/dist/streaming/source-manager.d.ts.map +1 -1
  166. package/dist/streaming/types.d.ts +9 -3
  167. package/dist/streaming/types.d.ts.map +1 -1
  168. package/dist/styles/controls.d.ts +1 -1
  169. package/dist/styles/controls.d.ts.map +1 -1
  170. package/dist/utils/static-html.d.ts +12 -0
  171. package/dist/utils/static-html.d.ts.map +1 -0
  172. package/dist/vizor.js +4 -4
  173. package/package.json +8 -5
  174. package/dist/__tests__/license-checker.test.d.ts.map +0 -1
  175. package/dist/__tests__/master-key.test.d.ts.map +0 -1
  176. package/dist/annotations-C0ugfCn4.js.map +0 -1
  177. package/dist/captions-BP0H2E03.js.map +0 -1
  178. package/dist/collab-BXPomrS0.js.map +0 -1
  179. package/dist/dash-adapter-tid9ZyhO.js.map +0 -1
  180. package/dist/hls-adapter-BivH46L_.js +0 -97
  181. package/dist/hls-adapter-BivH46L_.js.map +0 -1
  182. package/dist/register-CwnmiGEs.js.map +0 -1
  183. /package/dist/{__tests__ → license/__tests__}/license-checker.test.d.ts +0 -0
  184. /package/dist/{__tests__ → license/__tests__}/master-key.test.d.ts +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../src/register.ts"],"names":[],"mappings":"AAUA;;;GAGG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAYlC"}
1
+ {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../src/register.ts"],"names":[],"mappings":"AAaA;;;GAGG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAsBlC"}
package/dist/register.js CHANGED
@@ -1,4 +1,4 @@
1
- import { r } from "./register-CwnmiGEs.js";
1
+ import { r } from "./register-BmZt_300.js";
2
2
  export {
3
3
  r as registerAll
4
4
  };
@@ -1,4 +1,4 @@
1
- import { PerspectiveCamera } from 'three';
1
+ import { type PerspectiveCamera } from 'three';
2
2
  import type { PlayerState } from '../core/player-state.js';
3
3
  interface CameraConfig {
4
4
  startLat: number;
@@ -1 +1 @@
1
- {"version":3,"file":"camera-controller.d.ts","sourceRoot":"","sources":["../../src/renderer/camera-controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAA8B,MAAM,OAAO,CAAC;AAGtE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3D,UAAU,YAAY;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,OAAO,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,UAAU,CAAc;IAGhC,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,GAAG,CAAS;IAGpB,OAAO,CAAC,WAAW,CAAU;IAC7B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,IAAI,CAAS;IAGrB,OAAO,CAAC,OAAO,CAAQ;IAGvB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,WAAW,CAAiB;IAGpC,OAAO,CAAC,wBAAwB,CAAS;IACzC,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,WAAW,CAAK;IAGxB,OAAO,CAAC,aAAa,CAAmD;gBAE5D,MAAM,EAAE,iBAAiB,EAAE,UAAU,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY;IAyBxG,iEAAiE;IACjE,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAOlC,gFAAgF;IAChF,YAAY,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI;IAStC,uCAAuC;IACvC,MAAM,IAAI,IAAI;IA4Bd,8BAA8B;IAC9B,cAAc,IAAI;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE;IAQ3D,uCAAuC;IACvC,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,UAAQ,GAAG,IAAI;IAU5D,4CAA4C;IAC5C,uBAAuB,IAAI,IAAI;IAe/B,kCAAkC;IAClC,OAAO,IAAI,IAAI;IAOf,OAAO,CAAC,eAAe;IAmBvB,OAAO,CAAC,UAAU;IAKlB,OAAO,CAAC,aAAa;IAQrB,OAAO,CAAC,aAAa;IAYrB,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,OAAO;IAaf,OAAO,CAAC,SAAS;IAuBjB,OAAO,CAAC,sBAAsB;IAS9B,OAAO,CAAC,YAAY;CAarB"}
1
+ {"version":3,"file":"camera-controller.d.ts","sourceRoot":"","sources":["../../src/renderer/camera-controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAA8B,MAAM,OAAO,CAAC;AAG3E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3D,UAAU,YAAY;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,OAAO,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,UAAU,CAAc;IAGhC,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,GAAG,CAAS;IAGpB,OAAO,CAAC,WAAW,CAAU;IAC7B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,IAAI,CAAS;IAGrB,OAAO,CAAC,OAAO,CAAQ;IAGvB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,WAAW,CAAiB;IAGpC,OAAO,CAAC,wBAAwB,CAAS;IACzC,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,WAAW,CAAK;IAGxB,OAAO,CAAC,aAAa,CAAmD;gBAE5D,MAAM,EAAE,iBAAiB,EAAE,UAAU,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY;IAyBxG,iEAAiE;IACjE,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAOlC,gFAAgF;IAChF,YAAY,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI;IAStC,uCAAuC;IACvC,MAAM,IAAI,IAAI;IA4Bd,8BAA8B;IAC9B,cAAc,IAAI;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE;IAQ3D,uCAAuC;IACvC,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,UAAQ,GAAG,IAAI;IAU5D,4CAA4C;IAC5C,uBAAuB,IAAI,IAAI;IAe/B,kCAAkC;IAClC,OAAO,IAAI,IAAI;IAOf,OAAO,CAAC,eAAe;IAmBvB,OAAO,CAAC,UAAU;IAKlB,OAAO,CAAC,aAAa;IAQrB,OAAO,CAAC,aAAa;IAYrB,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,OAAO;IAaf,OAAO,CAAC,SAAS;IAuBjB,OAAO,CAAC,sBAAsB;IAS9B,OAAO,CAAC,YAAY;CAarB"}
@@ -17,8 +17,12 @@ import type { IProjection } from './projection.js';
17
17
  * For stereo content, two spheres are created on separate Three.js layers
18
18
  * with shader uniforms selecting the appropriate texture sub-region per eye.
19
19
  */
20
+ /** Clamp a capture-lens angle to the supported 120-250 deg range (default 180). */
21
+ export declare function clampLensAngle(deg: number | undefined | null): number;
20
22
  export declare class FisheyeProjection implements IProjection {
21
23
  private meshes;
24
+ private readonly lensFovRad;
25
+ constructor(lensAngleDeg?: number);
22
26
  createMeshes(texture: Texture, stereoMode: StereoMode): Mesh[];
23
27
  configureCamera(camera: PerspectiveCamera): void;
24
28
  update(_camera: PerspectiveCamera, _time: number): void;
@@ -1 +1 @@
1
- {"version":3,"file":"fisheye-projection.d.ts","sourceRoot":"","sources":["../../../src/renderer/projections/fisheye-projection.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,IAAI,EAEL,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAgDnD;;;;;;;;;;;;;;GAcG;AACH,qBAAa,iBAAkB,YAAW,WAAW;IACnD,OAAO,CAAC,MAAM,CAAc;IAE5B,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,GAAG,IAAI,EAAE;IAuB9D,eAAe,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI;IAQhD,MAAM,CAAC,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAIvD,OAAO,IAAI,IAAI;IAQf,OAAO,CAAC,YAAY;CA8BrB"}
1
+ {"version":3,"file":"fisheye-projection.d.ts","sourceRoot":"","sources":["../../../src/renderer/projections/fisheye-projection.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,IAAI,EAEL,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAgDnD;;;;;;;;;;;;;;GAcG;AACH,mFAAmF;AACnF,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,CAGrE;AAED,qBAAa,iBAAkB,YAAW,WAAW;IACnD,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;gBAExB,YAAY,CAAC,EAAE,MAAM;IAIjC,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,GAAG,IAAI,EAAE;IAuB9D,eAAe,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI;IAQhD,MAAM,CAAC,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAIvD,OAAO,IAAI,IAAI;IAQf,OAAO,CAAC,YAAY;CA+BrB"}
@@ -0,0 +1,26 @@
1
+ import { Mesh } from 'three';
2
+ import type { PerspectiveCamera, Texture } from 'three';
3
+ import type { StereoMode } from '@vizor-vr/shared';
4
+ import type { IProjection } from './projection.js';
5
+ /**
6
+ * True VR180 "spherical" projection (WS-F): one circular fisheye image per
7
+ * eye, optical axis forward, covering the capture lens angle (default 180°,
8
+ * supported 120–250°). This replaces the old silent equirect fallback that
9
+ * rendered real VR180-camera footage with wrong geometry.
10
+ *
11
+ * Texture layouts mirror the fisheye projection's stereo handling:
12
+ * mono — the full texture is one fisheye circle
13
+ * sbs — left eye in the left half, right eye in the right half
14
+ * tb — left eye in the TOP half, right eye in the bottom half
15
+ */
16
+ export declare class SphericalProjection implements IProjection {
17
+ private meshes;
18
+ private readonly lensFovRad;
19
+ constructor(lensAngleDeg?: number);
20
+ createMeshes(texture: Texture, stereoMode: StereoMode): Mesh[];
21
+ configureCamera(camera: PerspectiveCamera): void;
22
+ update(_camera: PerspectiveCamera, _time: number): void;
23
+ dispose(): void;
24
+ private createSphere;
25
+ }
26
+ //# sourceMappingURL=spherical-projection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spherical-projection.d.ts","sourceRoot":"","sources":["../../../src/renderer/projections/spherical-projection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkC,IAAI,EAAa,MAAM,OAAO,CAAC;AACxE,OAAO,KAAK,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAInD;;;;;;;;;;GAUG;AACH,qBAAa,mBAAoB,YAAW,WAAW;IACrD,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;gBAExB,YAAY,CAAC,EAAE,MAAM;IAIjC,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,GAAG,IAAI,EAAE;IA+B9D,eAAe,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI;IAQhD,MAAM,CAAC,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAIvD,OAAO,IAAI,IAAI;IAQf,OAAO,CAAC,YAAY;CAwBrB"}
@@ -1 +1 @@
1
- {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../src/renderer/renderer.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EACL,aAAa,EACb,iBAAiB,EAMlB,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAE,OAAO,EAAY,MAAM,OAAO,CAAC;AAC/C,OAAO,KAAK,EAAE,QAAQ,EAAc,MAAM,kBAAkB,CAAC;AAE7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAM/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAE9D;;;GAGG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,QAAQ,CAAgB;IAChC,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,gBAAgB,CAAmB;IAC3C,OAAO,CAAC,UAAU,CAA4B;IAC9C,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,oBAAoB,CAAqC;IACjE,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,UAAU,CAAgB;IAClC,OAAO,CAAC,aAAa,CAAK;gBAEd,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY;IA0DtG,4DAA4D;IAC5D,UAAU,CAAC,YAAY,EAAE,gBAAgB,EAAE,MAAM,EAAE,QAAQ,GAAG,IAAI;IAkBlE,qDAAqD;IACrD,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,GAAG,IAAI;IAUpD;;;OAGG;IACG,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBzE,+BAA+B;IAC/B,KAAK,IAAI,IAAI;IAMb,8BAA8B;IAC9B,IAAI,IAAI,IAAI;IAKZ,8BAA8B;IAC9B,MAAM,IAAI,IAAI;IAYd,qDAAqD;IACrD,gBAAgB,IAAI,aAAa;IAIjC,6CAA6C;IAC7C,SAAS,IAAI,iBAAiB;IAI9B,gCAAgC;IAChC,mBAAmB,IAAI,gBAAgB;IAIvC,uDAAuD;IACvD,QAAQ,IAAI,KAAK;IAIjB,kEAAkE;IAClE,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI;IAI5C,iCAAiC;IACjC,OAAO,IAAI,IAAI;IAef,gDAAgD;IAChD,mBAAmB,CAAC,UAAU,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,GAAG,IAAI;IAc5F,+DAA+D;IAC/D,OAAO,CAAC,oBAAoB;IAiC5B,OAAO,CAAC,aAAa;IAsBrB,OAAO,CAAC,gBAAgB;IAkBxB,OAAO,CAAC,IAAI;IA8BZ;;;OAGG;IACH,OAAO,CAAC,eAAe;CAuBxB"}
1
+ {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../src/renderer/renderer.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EACL,aAAa,EACb,iBAAiB,EAMlB,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAE,OAAO,EAAY,MAAM,OAAO,CAAC;AAC/C,OAAO,KAAK,EAAE,QAAQ,EAAc,MAAM,kBAAkB,CAAC;AAE7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAO/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAE9D;;;GAGG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,QAAQ,CAAgB;IAChC,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,gBAAgB,CAAmB;IAC3C,OAAO,CAAC,UAAU,CAA4B;IAC9C,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,oBAAoB,CAAqC;IACjE,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,UAAU,CAAgB;IAClC,OAAO,CAAC,aAAa,CAAK;gBAEd,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY;IAgEtG,4DAA4D;IAC5D,UAAU,CAAC,YAAY,EAAE,gBAAgB,EAAE,MAAM,EAAE,QAAQ,GAAG,IAAI;IAkBlE,qDAAqD;IACrD,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,GAAG,IAAI;IAUpD;;;OAGG;IACG,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBzE,+BAA+B;IAC/B,KAAK,IAAI,IAAI;IAMb,8BAA8B;IAC9B,IAAI,IAAI,IAAI;IAKZ,8BAA8B;IAC9B,MAAM,IAAI,IAAI;IAYd,qDAAqD;IACrD,gBAAgB,IAAI,aAAa;IAIjC,6CAA6C;IAC7C,SAAS,IAAI,iBAAiB;IAI9B,gCAAgC;IAChC,mBAAmB,IAAI,gBAAgB;IAIvC,uDAAuD;IACvD,QAAQ,IAAI,KAAK;IAIjB,kEAAkE;IAClE,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI;IAI5C,iCAAiC;IACjC,OAAO,IAAI,IAAI;IAef,gDAAgD;IAChD,mBAAmB,CAAC,UAAU,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,GAAG,IAAI;IAc5F,+DAA+D;IAC/D,OAAO,CAAC,oBAAoB;IAiC5B,OAAO,CAAC,aAAa;IAsBrB,OAAO,CAAC,gBAAgB;IAqBxB,OAAO,CAAC,IAAI;IA8BZ;;;OAGG;IACH,OAAO,CAAC,eAAe;CAuBxB"}
@@ -18,5 +18,14 @@ export declare const fisheyeVertexShader = "\nvarying vec3 vWorldPosition;\n\nvo
18
18
  * - uScaleX / uScaleY: scale factor applied to the final UV (1.0 = full, 0.5 = half)
19
19
  * - uOffsetX / uOffsetY: offset added after scaling (0.0 or 0.5 for stereo halves)
20
20
  */
21
- export declare const fisheyeFragmentShader = "\nuniform sampler2D map;\nuniform float uScaleX;\nuniform float uScaleY;\nuniform float uOffsetX;\nuniform float uOffsetY;\n\nvarying vec3 vWorldPosition;\n\nconst float PI = 3.14159265359;\n\nvoid main() {\n vec3 dir = normalize(vWorldPosition);\n\n // Determine which hemisphere: front (z >= 0) or back (z < 0)\n bool isFront = dir.z >= 0.0;\n float faceSign = isFront ? 1.0 : -1.0;\n\n // Polar angle from the hemisphere pole (0 at pole, PI/2 at equator)\n float theta = acos(clamp(abs(dir.z), -1.0, 1.0));\n\n // Azimuthal angle around the hemisphere pole\n float phi = atan(dir.y, dir.x * faceSign);\n\n // Map to circular fisheye UV using equidistant projection\n // r ranges from 0 (pole) to 1 (equator)\n float r = theta / (PI * 0.5);\n\n // Convert polar (r, phi) to cartesian circle coordinates, centered at (0.5, 0.5)\n vec2 circleUV = vec2(r * cos(phi), r * sin(phi)) * 0.5 + 0.5;\n\n // Place front hemisphere in left half of the dual-fisheye region,\n // back hemisphere in right half\n float xOffset = isFront ? 0.0 : 0.5;\n vec2 uv = vec2(circleUV.x * 0.5 + xOffset, circleUV.y);\n\n // Apply stereo region selection\n uv = vec2(uv.x * uScaleX + uOffsetX, uv.y * uScaleY + uOffsetY);\n\n gl_FragColor = texture2D(map, uv);\n}\n";
21
+ export declare const fisheyeFragmentShader = "\nuniform sampler2D map;\nuniform float uScaleX;\nuniform float uScaleY;\nuniform float uOffsetX;\nuniform float uOffsetY;\nuniform float uLensFov; // capture-lens angle in RADIANS (WS-F, 120-250 deg)\n\nvarying vec3 vWorldPosition;\n\nconst float PI = 3.14159265359;\n\nvoid main() {\n vec3 dir = normalize(vWorldPosition);\n\n // Determine which hemisphere: front (z >= 0) or back (z < 0)\n bool isFront = dir.z >= 0.0;\n float faceSign = isFront ? 1.0 : -1.0;\n\n // Polar angle from the hemisphere pole (0 at pole, PI/2 at equator)\n float theta = acos(clamp(abs(dir.z), -1.0, 1.0));\n\n // Azimuthal angle around the hemisphere pole\n float phi = atan(dir.y, dir.x * faceSign);\n\n // Map to circular fisheye UV using equidistant projection.\n // r = 1 at the lens edge (uLensFov/2 from the pole). For lenses wider than\n // 180 deg the hemisphere uses only the inner part of the circle; for\n // narrower lenses r can exceed 1 \u2014 clamp to the edge (looks better than\n // holes; decided by visual test).\n float r = min(theta / (uLensFov * 0.5), 1.0);\n\n // Convert polar (r, phi) to cartesian circle coordinates, centered at (0.5, 0.5)\n vec2 circleUV = vec2(r * cos(phi), r * sin(phi)) * 0.5 + 0.5;\n\n // Place front hemisphere in left half of the dual-fisheye region,\n // back hemisphere in right half\n float xOffset = isFront ? 0.0 : 0.5;\n vec2 uv = vec2(circleUV.x * 0.5 + xOffset, circleUV.y);\n\n // Apply stereo region selection\n uv = vec2(uv.x * uScaleX + uOffsetX, uv.y * uScaleY + uOffsetY);\n\n gl_FragColor = texture2D(map, uv);\n}\n";
22
+ /**
23
+ * Single-fisheye fragment shader (WS-F "spherical" / true VR180).
24
+ *
25
+ * Unlike the dual-fisheye shader there is NO hemisphere split: the texture
26
+ * (or per-eye sub-region for stereo) holds ONE circular fisheye image whose
27
+ * optical axis is the forward (+z after sphere inversion) direction, covering
28
+ * uLensFov degrees. Directions beyond the lens edge clamp to it.
29
+ */
30
+ export declare const sphericalFragmentShader = "\nuniform sampler2D map;\nuniform float uScaleX;\nuniform float uScaleY;\nuniform float uOffsetX;\nuniform float uOffsetY;\nuniform float uLensFov; // capture-lens angle in RADIANS\n\nvarying vec3 vWorldPosition;\n\nvoid main() {\n vec3 dir = normalize(vWorldPosition);\n\n // Angle from the forward optical axis (0 straight ahead). The camera\n // controller's default view (lat 0, lon 0) looks along +x, so that is the\n // content center for VR180 footage.\n float theta = acos(clamp(dir.x, -1.0, 1.0));\n\n // Azimuth around the axis: +z is screen-right at the default view, +y up.\n float phi = atan(dir.y, dir.z);\n\n // Equidistant mapping; clamp beyond the lens edge.\n float r = min(theta / (uLensFov * 0.5), 1.0);\n\n vec2 circleUV = vec2(r * cos(phi), r * sin(phi)) * 0.5 + 0.5;\n\n // Stereo region selection (full texture for mono).\n vec2 uv = vec2(circleUV.x * uScaleX + uOffsetX, circleUV.y * uScaleY + uOffsetY);\n\n gl_FragColor = texture2D(map, uv);\n}\n";
22
31
  //# sourceMappingURL=fisheye.glsl.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"fisheye.glsl.d.ts","sourceRoot":"","sources":["../../../src/renderer/shaders/fisheye.glsl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,wEAAwE;AACxE,eAAO,MAAM,mBAAmB,4NAQ/B,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB,ovCAyCjC,CAAC"}
1
+ {"version":3,"file":"fisheye.glsl.d.ts","sourceRoot":"","sources":["../../../src/renderer/shaders/fisheye.glsl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,wEAAwE;AACxE,eAAO,MAAM,mBAAmB,4NAQ/B,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB,sjDA6CjC,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,+9BA+BnC,CAAC"}
package/dist/sri.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
- "annotations-C0ugfCn4.js": "sha384-9DjwKv8po5gIDBHcBwt+TSgTYO/o10AkCAh/iNQVCP5VuLdPIbO5CfTzyo6Awbg5",
3
- "captions-BP0H2E03.js": "sha384-y6Iz8yboRE1mMSVAmIDjw1zk90owOOIiOIkKO6o06+yYYvHiN3SS0eAgfmrju5M0",
4
- "collab-BXPomrS0.js": "sha384-CCTDHN4a2l8g+NwuPET2SYrhBAa45IJ3TpjbzgWs+bJ648+jtIbir/KatUB0BL2n",
5
- "dash-adapter-tid9ZyhO.js": "sha384-U9b0p79ZVRck/PipwaHFr0eV3k1jZ7Syw8K+z9yrS3BkLi4TVmk077k63nUtYKQE",
6
- "hls-adapter-BivH46L_.js": "sha384-jOBukDUqYuL2pouXVqeORYwec9BaMTvoiLU7L6thrIhSCgypeCmENBbgfirRyoj7",
7
- "register-CwnmiGEs.js": "sha384-HxozDDmTD20UrMFcKn84HPEAuXFZVnf5in26XgJw4FkaiHoXOwH7a188VLhLQ4Tf",
8
- "register.js": "sha384-a/u1LFOR/riKc5C0xhFqdhS3p2SAGabZpidZlB0LB5PwJkSp227IbRbrI6npo37S",
2
+ "annotations-Du6ZWrqC.js": "sha384-VsdmbftxRqal6m8/EBLEwOA8Xjaw4O/4m7B112BwKrVbgxMoAtMs/mHZVDX9pr9H",
3
+ "captions-YvnHAwLY.js": "sha384-477Yd+ZnfjUuRqgEd3ss8Utbff7v1JeJc3omQQsz/drgTKj9PAI+bcYXyh8jmY7b",
4
+ "collab-BLpllHtb.js": "sha384-xKRBLTkgTKoqcDEW4euBKmJ/u1158G0W1Y00wpmNNJvM48qxxxwYJDT+mMsO/F7W",
5
+ "dash-adapter-BMpHWcBA.js": "sha384-QpuRqI0+CkF+JAI65kwVMYEUZaj8dO+/TIkFxZBOjpQtiJ/4NrOMDoYoSmjBQRAZ",
6
+ "hls-adapter-C_a65zia.js": "sha384-WYkvhcyauEfxwuo4mJiCLiEbHzS8+Vb7WNLRdoYzbKhrsM414RaD7PaSwOxP/rgp",
7
+ "register-BmZt_300.js": "sha384-sP6D71MNR+SGrOvPojew1bbhosV/Af3KKo7LrkaQgOt5oTJE7FL+LHDpiQBADYaV",
8
+ "register.js": "sha384-d3pJ293qTfyMKBljuELoNcbB7HHACKi+oyCF2XH1gc2+iCKWl9Un1UhQ7o/Zj5Dn",
9
9
  "spatial-BeadwNJA.js": "sha384-HZn7bAj2gWsXmVFl+w/IeQhzEBv5/Aj7XMhkuhnu5/GZ1Kd3RdhgTIU+RGQzc5fU",
10
10
  "three-Bci7aSeI.js": "sha384-WT17P68Bk5PWfaSGPpgMiYblkgoKrBcfOLZbjErgGMIvbwZrcWE7p/Fr9+FNR2Dy",
11
- "vizor.js": "sha384-amgJdCAcF1V7r/J1J6kaJPCMXFaMoDwApArfErpyRDqPenhfH2CochC3ztohkjip"
11
+ "vizor.js": "sha384-dmswREH8Vm72a1LQNCeTrZkH7nb+mFC6ZcR2r7vMvpxeSdBYmqvnU6TExpjRCjWU"
12
12
  }
@@ -1,5 +1,5 @@
1
1
  import type { QualityLevel } from '@vizor-vr/shared';
2
- import type { IStreamingAdapter } from './types.js';
2
+ import type { IStreamingAdapter, DrmContext } from './types.js';
3
3
  /**
4
4
  * DASH streaming adapter wrapping dashjs.
5
5
  * Lazy-loaded via dynamic import — only included in the bundle
@@ -13,7 +13,7 @@ export declare class DashAdapter implements IStreamingAdapter {
13
13
  get supportsABR(): boolean;
14
14
  get isAttached(): boolean;
15
15
  attach(videoElement: HTMLVideoElement): void;
16
- load(url: string): Promise<void>;
16
+ load(url: string, drm?: DrmContext): Promise<void>;
17
17
  getQualityLevels(): QualityLevel[];
18
18
  setQualityLevel(index: number): void;
19
19
  destroy(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"dash-adapter.d.ts","sourceRoot":"","sources":["../../src/streaming/dash-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpD;;;;GAIG;AACH,qBAAa,WAAY,YAAW,iBAAiB;IACnD,OAAO,CAAC,YAAY,CAAiC;IACrD,OAAO,CAAC,MAAM,CAAwB;IACtC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,MAAM,CAAsB;IAEpC,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED,IAAI,UAAU,IAAI,OAAO,CAExB;IAED,MAAM,CAAC,YAAY,EAAE,gBAAgB,GAAG,IAAI;IAKtC,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAsCtC,gBAAgB,IAAI,YAAY,EAAE;IAIlC,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAoBpC,OAAO,IAAI,IAAI;CAShB"}
1
+ {"version":3,"file":"dash-adapter.d.ts","sourceRoot":"","sources":["../../src/streaming/dash-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEhE;;;;GAIG;AACH,qBAAa,WAAY,YAAW,iBAAiB;IACnD,OAAO,CAAC,YAAY,CAAiC;IACrD,OAAO,CAAC,MAAM,CAAwB;IACtC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,MAAM,CAAsB;IAEpC,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED,IAAI,UAAU,IAAI,OAAO,CAExB;IAED,MAAM,CAAC,YAAY,EAAE,gBAAgB,GAAG,IAAI;IAKtC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IA+CxD,gBAAgB,IAAI,YAAY,EAAE;IAIlC,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAoBpC,OAAO,IAAI,IAAI;CAShB"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Native Safari FairPlay Streaming wiring. Safari plays HLS natively; FairPlay
3
+ * is set up manually via EME: fetch the certificate, on `encrypted` create a
4
+ * key session, on the SPC `message` POST it to the (Vizor-proxied) FairPlay
5
+ * license URL with the x-api-key header, then update the session with the CKC.
6
+ *
7
+ * The pure helpers are unit-tested; the EME calls are runtime-only (no EME in
8
+ * jsdom) and are documented for manual Safari verification. The exact EZDRM
9
+ * FairPlay SPC/CKC encoding is pinned against the vendor guide at live
10
+ * integration (isolated in buildSpcBody/parseCkc below).
11
+ */
12
+ import type { DeliveryDrm } from '@vizor-vr/shared';
13
+ export declare function skdToContentId(skd: string): string;
14
+ export declare function toBase64(bytes: Uint8Array): string;
15
+ export declare function fromBase64(b64: string): Uint8Array;
16
+ export interface FairPlayDeps {
17
+ fetch: typeof fetch;
18
+ requestMediaKeySystemAccess: typeof navigator.requestMediaKeySystemAccess;
19
+ }
20
+ export declare function setupFairPlay(video: HTMLVideoElement, drm: DeliveryDrm, apiKey: string | undefined, deps?: FairPlayDeps): Promise<void>;
21
+ //# sourceMappingURL=fairplay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fairplay.d.ts","sourceRoot":"","sources":["../../src/streaming/fairplay.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAIpD,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAIlD;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAKlD;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,OAAO,KAAK,CAAC;IACpB,2BAA2B,EAAE,OAAO,SAAS,CAAC,2BAA2B,CAAC;CAC3E;AAED,wBAAsB,aAAa,CACjC,KAAK,EAAE,gBAAgB,EACvB,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,IAAI,GAAE,YAGL,GACA,OAAO,CAAC,IAAI,CAAC,CA8Cf"}
@@ -1,5 +1,5 @@
1
1
  import type { QualityLevel } from '@vizor-vr/shared';
2
- import type { IStreamingAdapter } from './types.js';
2
+ import type { IStreamingAdapter, DrmContext } from './types.js';
3
3
  /**
4
4
  * HLS streaming adapter wrapping hls.js.
5
5
  * Lazy-loaded via dynamic import — only included in the bundle
@@ -18,7 +18,7 @@ export declare class HlsAdapter implements IStreamingAdapter {
18
18
  get supportsABR(): boolean;
19
19
  get isAttached(): boolean;
20
20
  attach(videoElement: HTMLVideoElement): void;
21
- load(url: string): Promise<void>;
21
+ load(url: string, drm?: DrmContext): Promise<void>;
22
22
  getQualityLevels(): QualityLevel[];
23
23
  setQualityLevel(index: number): void;
24
24
  destroy(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"hls-adapter.d.ts","sourceRoot":"","sources":["../../src/streaming/hls-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpD;;;;;;GAMG;AACH,qBAAa,UAAW,YAAW,iBAAiB;IAClD,OAAO,CAAC,YAAY,CAAiC;IACrD,OAAO,CAAC,GAAG,CAAwB;IACnC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,MAAM,CAAsB;IAEpC,+CAA+C;IAC/C,cAAc,UAAS;IAEvB,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED,IAAI,UAAU,IAAI,OAAO,CAExB;IAED,MAAM,CAAC,YAAY,EAAE,gBAAgB,GAAG,IAAI;IAKtC,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAsEtC,gBAAgB,IAAI,YAAY,EAAE;IAIlC,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAMpC,OAAO,IAAI,IAAI;CAUhB"}
1
+ {"version":3,"file":"hls-adapter.d.ts","sourceRoot":"","sources":["../../src/streaming/hls-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAGhE;;;;;;GAMG;AACH,qBAAa,UAAW,YAAW,iBAAiB;IAClD,OAAO,CAAC,YAAY,CAAiC;IACrD,OAAO,CAAC,GAAG,CAAwB;IACnC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,MAAM,CAAsB;IAEpC,+CAA+C;IAC/C,cAAc,UAAS;IAEvB,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED,IAAI,UAAU,IAAI,OAAO,CAExB;IAED,MAAM,CAAC,YAAY,EAAE,gBAAgB,GAAG,IAAI;IAKtC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAmFxD,gBAAgB,IAAI,YAAY,EAAE;IAIlC,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAMpC,OAAO,IAAI,IAAI;CAUhB"}
@@ -1,5 +1,5 @@
1
1
  import type { QualityLevel } from '@vizor-vr/shared';
2
- import type { IStreamingAdapter } from './types.js';
2
+ import type { IStreamingAdapter, DrmContext } from './types.js';
3
3
  /**
4
4
  * Progressive MP4/WebM adapter.
5
5
  * Sets the video source directly — no adaptive bitrate.
@@ -10,7 +10,7 @@ export declare class ProgressiveAdapter implements IStreamingAdapter {
10
10
  get supportsABR(): boolean;
11
11
  get isAttached(): boolean;
12
12
  attach(videoElement: HTMLVideoElement): void;
13
- load(url: string): void;
13
+ load(url: string, _drm?: DrmContext): void;
14
14
  getQualityLevels(): QualityLevel[];
15
15
  setQualityLevel(_index: number): void;
16
16
  destroy(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"progressive-adapter.d.ts","sourceRoot":"","sources":["../../src/streaming/progressive-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpD;;;GAGG;AACH,qBAAa,kBAAmB,YAAW,iBAAiB;IAC1D,OAAO,CAAC,YAAY,CAAiC;IACrD,OAAO,CAAC,WAAW,CAAS;IAE5B,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED,IAAI,UAAU,IAAI,OAAO,CAExB;IAED,MAAM,CAAC,YAAY,EAAE,gBAAgB,GAAG,IAAI;IAK5C,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAKvB,gBAAgB,IAAI,YAAY,EAAE;IAIlC,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAIrC,OAAO,IAAI,IAAI;CAOhB"}
1
+ {"version":3,"file":"progressive-adapter.d.ts","sourceRoot":"","sources":["../../src/streaming/progressive-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEhE;;;GAGG;AACH,qBAAa,kBAAmB,YAAW,iBAAiB;IAC1D,OAAO,CAAC,YAAY,CAAiC;IACrD,OAAO,CAAC,WAAW,CAAS;IAE5B,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED,IAAI,UAAU,IAAI,OAAO,CAExB;IAED,MAAM,CAAC,YAAY,EAAE,gBAAgB,GAAG,IAAI;IAK5C,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,UAAU,GAAG,IAAI;IAK1C,gBAAgB,IAAI,YAAY,EAAE;IAIlC,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAIrC,OAAO,IAAI,IAAI;CAOhB"}
@@ -1,6 +1,7 @@
1
1
  import type { ParsedSource, QualityLevel } from '@vizor-vr/shared';
2
2
  import type { PlayerState } from '../core/player-state.js';
3
3
  import type { VzEventEmitter } from '../core/event-emitter.js';
4
+ import type { DrmContext } from './types.js';
4
5
  /**
5
6
  * Manages source selection and streaming adapter lifecycle.
6
7
  *
@@ -16,10 +17,11 @@ export declare class SourceManager {
16
17
  private state;
17
18
  private events;
18
19
  private sources;
20
+ private drm;
19
21
  /**
20
22
  * Load sources into the video element using the appropriate adapter.
21
23
  */
22
- loadSources(sources: ParsedSource[], videoElement: HTMLVideoElement, state: PlayerState, events: VzEventEmitter): Promise<void>;
24
+ loadSources(sources: ParsedSource[], videoElement: HTMLVideoElement, state: PlayerState, events: VzEventEmitter, drm?: DrmContext): Promise<void>;
23
25
  /** Get available quality levels from the current adapter */
24
26
  getQualityLevels(): QualityLevel[];
25
27
  /** Set quality level (-1 for auto) */
@@ -1 +1 @@
1
- {"version":3,"file":"source-manager.d.ts","sourceRoot":"","sources":["../../src/streaming/source-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACnE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAI/D;;;;;;;;GAQG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAAkC;IACjD,OAAO,CAAC,YAAY,CAAiC;IACrD,OAAO,CAAC,KAAK,CAA4B;IACzC,OAAO,CAAC,MAAM,CAA+B;IAC7C,OAAO,CAAC,OAAO,CAAsB;IAErC;;OAEG;IACG,WAAW,CACf,OAAO,EAAE,YAAY,EAAE,EACvB,YAAY,EAAE,gBAAgB,EAC9B,KAAK,EAAE,WAAW,EAClB,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,IAAI,CAAC;IAuBhB,4DAA4D;IAC5D,gBAAgB,IAAI,YAAY,EAAE;IAIlC,sCAAsC;IACtC,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAiBpC,+CAA+C;IAC/C,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED,gFAAgF;IAChF,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAiBjC,gDAAgD;IAChD,OAAO,IAAI,IAAI;IASf;;;OAGG;IACH,OAAO,CAAC,YAAY;IAapB,iEAAiE;IACjE,OAAO,CAAC,iBAAiB;IAmBzB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;CAoB1B"}
1
+ {"version":3,"file":"source-manager.d.ts","sourceRoot":"","sources":["../../src/streaming/source-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACnE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,KAAK,EAAkC,UAAU,EAAE,MAAM,YAAY,CAAC;AAG7E;;;;;;;;GAQG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAAkC;IACjD,OAAO,CAAC,YAAY,CAAiC;IACrD,OAAO,CAAC,KAAK,CAA4B;IACzC,OAAO,CAAC,MAAM,CAA+B;IAC7C,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,GAAG,CAAyB;IAEpC;;OAEG;IACG,WAAW,CACf,OAAO,EAAE,YAAY,EAAE,EACvB,YAAY,EAAE,gBAAgB,EAC9B,KAAK,EAAE,WAAW,EAClB,MAAM,EAAE,cAAc,EACtB,GAAG,CAAC,EAAE,UAAU,GACf,OAAO,CAAC,IAAI,CAAC;IAwBhB,4DAA4D;IAC5D,gBAAgB,IAAI,YAAY,EAAE;IAIlC,sCAAsC;IACtC,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAiBpC,+CAA+C;IAC/C,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED,gFAAgF;IAChF,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAiBjC,gDAAgD;IAChD,OAAO,IAAI,IAAI;IASf;;;OAGG;IACH,OAAO,CAAC,YAAY;IAapB,iEAAiE;IACjE,OAAO,CAAC,iBAAiB;IAmBzB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;CAoB1B"}
@@ -1,6 +1,12 @@
1
- import type { QualityLevel } from '@vizor-vr/shared';
1
+ import type { QualityLevel, DeliveryDrm } from '@vizor-vr/shared';
2
2
  /** Adapter type identifier */
3
3
  export type AdapterType = 'progressive' | 'hls' | 'dash';
4
+ /** DRM playback context threaded from the element to the adapter. */
5
+ export interface DrmContext {
6
+ config: DeliveryDrm;
7
+ /** api-key attached to license requests so the Vizor proxy can entitle them. */
8
+ apiKey?: string;
9
+ }
4
10
  /**
5
11
  * Common interface for all streaming adapters.
6
12
  * Each adapter wraps a specific playback technology
@@ -9,8 +15,8 @@ export type AdapterType = 'progressive' | 'hls' | 'dash';
9
15
  export interface IStreamingAdapter {
10
16
  /** Attach the adapter to a <video> element */
11
17
  attach(videoElement: HTMLVideoElement): void;
12
- /** Load a source URL */
13
- load(url: string): void;
18
+ /** Load a source URL (optionally with a DRM context for EME). */
19
+ load(url: string, drm?: DrmContext): void;
14
20
  /** Get available quality levels (empty for progressive) */
15
21
  getQualityLevels(): QualityLevel[];
16
22
  /** Set active quality level (-1 for auto ABR) */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/streaming/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAErD,8BAA8B;AAC9B,MAAM,MAAM,WAAW,GAAG,aAAa,GAAG,KAAK,GAAG,MAAM,CAAC;AAEzD;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,8CAA8C;IAC9C,MAAM,CAAC,YAAY,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAE7C,wBAAwB;IACxB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAExB,2DAA2D;IAC3D,gBAAgB,IAAI,YAAY,EAAE,CAAC;IAEnC,iDAAiD;IACjD,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAErC,wCAAwC;IACxC,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAE9B,gDAAgD;IAChD,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAE7B,gDAAgD;IAChD,OAAO,IAAI,IAAI,CAAC;CACjB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/streaming/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAElE,8BAA8B;AAC9B,MAAM,MAAM,WAAW,GAAG,aAAa,GAAG,KAAK,GAAG,MAAM,CAAC;AAEzD,qEAAqE;AACrE,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,WAAW,CAAC;IACpB,gFAAgF;IAChF,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,8CAA8C;IAC9C,MAAM,CAAC,YAAY,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAE7C,iEAAiE;IACjE,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAE1C,2DAA2D;IAC3D,gBAAgB,IAAI,YAAY,EAAE,CAAC;IAEnC,iDAAiD;IACjD,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAErC,wCAAwC;IACxC,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAE9B,gDAAgD;IAChD,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAE7B,gDAAgD;IAChD,OAAO,IAAI,IAAI,CAAC;CACjB"}
@@ -11,5 +11,5 @@
11
11
  * --vz-controls-transition Fade duration (default: 0.3s)
12
12
  * --vz-button-size Button hit-area size (default: 36px)
13
13
  */
14
- export declare const CONTROLS_CSS = "\n /* ------------------------------------------------------------------ */\n /* Layout \u2014 wrapper + seek above button row */\n /* ------------------------------------------------------------------ */\n\n .vz-controls-wrapper {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n z-index: 10;\n user-select: none;\n -webkit-user-select: none;\n transition: opacity var(--vz-controls-transition, 0.3s) ease,\n transform 0.2s ease;\n }\n\n .vz-controls-wrapper.hidden {\n opacity: 0;\n pointer-events: none;\n transform: translateY(4px);\n }\n\n /* Progress bar sits above the button row */\n .vz-seek-row {\n position: relative;\n width: 100%;\n padding: 0 12px;\n cursor: pointer;\n z-index: 11;\n }\n\n /* Button row */\n .vz-controls {\n display: flex;\n align-items: center;\n gap: 2px;\n padding: 4px 8px 6px;\n background: linear-gradient(transparent, var(--vz-controls-bg, rgba(0, 0, 0, 0.6)));\n backdrop-filter: blur(4px);\n -webkit-backdrop-filter: blur(4px);\n color: #fff;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 13px;\n }\n\n .vz-controls-left {\n display: flex;\n align-items: center;\n gap: 2px;\n flex-shrink: 0;\n }\n\n .vz-controls-center {\n flex: 1;\n min-width: 0;\n }\n\n .vz-controls-right {\n display: flex;\n align-items: center;\n gap: 2px;\n flex-shrink: 0;\n }\n\n /* ------------------------------------------------------------------ */\n /* Buttons */\n /* ------------------------------------------------------------------ */\n\n .vz-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: var(--vz-button-size, 36px);\n height: var(--vz-button-size, 36px);\n padding: 0;\n border: none;\n border-radius: 50%;\n background: transparent;\n color: #fff;\n cursor: pointer;\n flex-shrink: 0;\n transition: opacity 0.15s, transform 0.15s;\n opacity: 0.9;\n }\n\n .vz-btn:hover {\n opacity: 1;\n transform: scale(1.1);\n }\n\n .vz-btn:active {\n transform: scale(0.95);\n }\n\n .vz-btn:focus-visible {\n outline: 2px solid var(--vz-primary, #f43f5e);\n outline-offset: 2px;\n }\n\n .vz-btn svg {\n width: 20px;\n height: 20px;\n fill: currentColor;\n }\n\n /* ------------------------------------------------------------------ */\n /* Seek / Progress bar */\n /* ------------------------------------------------------------------ */\n\n .vz-seek-container {\n position: relative;\n display: flex;\n align-items: center;\n width: 100%;\n height: 18px;\n cursor: pointer;\n }\n\n .vz-seek-track {\n position: relative;\n width: 100%;\n height: var(--vz-progress-height, 3px);\n background: rgba(255, 255, 255, 0.2);\n border-radius: 99px;\n overflow: visible;\n transition: height 0.15s ease;\n }\n\n .vz-seek-container:hover .vz-seek-track {\n height: 5px;\n }\n\n .vz-seek-buffered {\n position: absolute;\n top: 0;\n left: 0;\n height: 100%;\n background: linear-gradient(\n 90deg,\n rgba(255, 255, 255, 0.25),\n rgba(255, 255, 255, 0.35)\n );\n border-radius: 99px;\n }\n\n .vz-seek-played {\n position: absolute;\n top: 0;\n left: 0;\n height: 100%;\n background: var(--vz-progress-color, var(--vz-primary, #f43f5e));\n border-radius: 99px;\n box-shadow: 0 0 8px rgba(244, 63, 94, 0.4);\n box-shadow: 0 0 8px color-mix(in srgb, var(--vz-primary, #f43f5e) 40%, transparent);\n }\n\n .vz-seek-thumb {\n position: absolute;\n top: 50%;\n width: 13px;\n height: 13px;\n border-radius: 50%;\n background: #fff;\n box-shadow: 0 0 4px rgba(0, 0, 0, 0.3);\n transform: translate(-50%, -50%) scale(0);\n transition: transform 0.15s ease, box-shadow 0.15s ease;\n pointer-events: none;\n }\n\n .vz-seek-container:hover .vz-seek-thumb {\n transform: translate(-50%, -50%) scale(1);\n box-shadow: 0 0 6px rgba(244, 63, 94, 0.5);\n box-shadow: 0 0 6px color-mix(in srgb, var(--vz-primary, #f43f5e) 50%, transparent);\n }\n\n .vz-seek-input {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n margin: 0;\n padding: 0;\n opacity: 0;\n cursor: pointer;\n -webkit-appearance: none;\n appearance: none;\n }\n\n /* Hover time tooltip */\n .vz-seek-tooltip {\n position: absolute;\n bottom: 100%;\n margin-bottom: 6px;\n padding: 3px 7px;\n background: var(--vz-secondary, rgba(0, 0, 0, 0.85));\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n color: #fff;\n font-size: 12px;\n font-variant-numeric: tabular-nums;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n border-radius: 4px;\n white-space: nowrap;\n pointer-events: none;\n transform: translateX(-50%);\n opacity: 0;\n transition: opacity 0.12s;\n }\n\n .vz-seek-container:hover .vz-seek-tooltip {\n opacity: 1;\n }\n\n .vz-time {\n font-size: 12px;\n font-weight: 400;\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n padding: 0 6px;\n flex-shrink: 0;\n opacity: 0.9;\n letter-spacing: 0.02em;\n }\n\n /* ------------------------------------------------------------------ */\n /* Volume \u2014 horizontal slide-out on hover */\n /* ------------------------------------------------------------------ */\n\n .vz-volume {\n display: flex;\n align-items: center;\n gap: 0;\n overflow: hidden;\n }\n\n .vz-volume-slider-wrap {\n width: 0;\n overflow: hidden;\n transition: width 0.2s ease;\n }\n\n .vz-volume:hover .vz-volume-slider-wrap {\n width: 64px;\n }\n\n .vz-volume-slider {\n width: 60px;\n height: 4px;\n margin: 0 4px;\n -webkit-appearance: none;\n appearance: none;\n background: rgba(255, 255, 255, 0.3);\n border-radius: 99px;\n outline: none;\n cursor: pointer;\n }\n\n .vz-volume-slider::-webkit-slider-thumb {\n -webkit-appearance: none;\n width: 12px;\n height: 12px;\n border-radius: 50%;\n background: #fff;\n cursor: pointer;\n box-shadow: 0 0 3px rgba(0, 0, 0, 0.2);\n }\n\n .vz-volume-slider::-moz-range-thumb {\n width: 12px;\n height: 12px;\n border: none;\n border-radius: 50%;\n background: #fff;\n cursor: pointer;\n box-shadow: 0 0 3px rgba(0, 0, 0, 0.2);\n }\n\n /* ------------------------------------------------------------------ */\n /* Quality menu */\n /* ------------------------------------------------------------------ */\n\n .vz-quality-menu {\n position: relative;\n }\n\n .vz-quality-dropdown {\n position: absolute;\n bottom: 100%;\n right: 0;\n margin-bottom: 8px;\n background: var(--vz-secondary, rgba(20, 20, 30, 0.95));\n backdrop-filter: blur(16px) saturate(1.3);\n -webkit-backdrop-filter: blur(16px) saturate(1.3);\n border: 1px solid rgba(255, 255, 255, 0.06);\n border-radius: 8px;\n padding: 4px 0;\n min-width: 120px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.04);\n display: none;\n z-index: 20;\n }\n\n .vz-quality-dropdown.open {\n display: block;\n }\n\n .vz-quality-option {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n cursor: pointer;\n font-size: 13px;\n color: rgba(255, 255, 255, 0.7);\n white-space: nowrap;\n transition: color 0.12s, background 0.12s;\n }\n\n .vz-quality-option:hover {\n background: rgba(244, 63, 94, 0.08);\n background: color-mix(in srgb, var(--vz-primary, #f43f5e) 8%, transparent);\n color: #fff;\n }\n\n .vz-quality-option.active {\n color: var(--vz-primary, #f43f5e);\n }\n\n .vz-quality-check {\n width: 16px;\n font-size: 14px;\n }\n\n /* ------------------------------------------------------------------ */\n /* Compass */\n /* ------------------------------------------------------------------ */\n\n .vz-compass {\n position: relative;\n }\n\n .vz-compass svg {\n fill: none;\n stroke: currentColor;\n transition: transform 0.1s ease-out;\n }\n\n /* ------------------------------------------------------------------ */\n /* Loading spinner \u2014 CSS ring */\n /* ------------------------------------------------------------------ */\n\n .vz-loading {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 44px;\n height: 44px;\n z-index: 5;\n pointer-events: none;\n }\n\n .vz-loading-spinner {\n width: 100%;\n height: 100%;\n border: 2.5px solid rgba(255, 255, 255, 0.15);\n border-top-color: var(--vz-primary, #f43f5e);\n border-radius: 50%;\n animation: vz-spin 0.75s linear infinite;\n }\n\n .vz-loading.hidden {\n display: none;\n }\n\n @keyframes vz-spin {\n to { transform: rotate(360deg); }\n }\n\n /* ------------------------------------------------------------------ */\n /* Big play button \u2014 frosted glass */\n /* ------------------------------------------------------------------ */\n\n .vz-big-play {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 68px;\n height: 68px;\n border: 1px solid rgba(255, 255, 255, 0.08);\n border-radius: 50%;\n background: rgba(15, 10, 20, 0.4);\n backdrop-filter: blur(12px) saturate(1.2);\n -webkit-backdrop-filter: blur(12px) saturate(1.2);\n color: #fff;\n cursor: pointer;\n z-index: 5;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background-color 0.25s ease, transform 0.25s ease, opacity 0.25s ease, box-shadow 0.25s ease;\n opacity: 1;\n box-shadow: 0 0 20px rgba(244, 63, 94, 0.15);\n box-shadow: 0 0 20px color-mix(in srgb, var(--vz-primary, #f43f5e) 15%, transparent);\n }\n\n .vz-big-play:hover {\n background: rgba(15, 10, 20, 0.55);\n transform: translate(-50%, -50%) scale(1.08);\n box-shadow: 0 0 30px rgba(244, 63, 94, 0.25);\n box-shadow: 0 0 30px color-mix(in srgb, var(--vz-primary, #f43f5e) 25%, transparent);\n }\n\n .vz-big-play.hidden {\n opacity: 0;\n pointer-events: none;\n transform: translate(-50%, -50%) scale(0.85);\n }\n\n .vz-big-play svg {\n width: 30px;\n height: 30px;\n fill: currentColor;\n margin-left: 3px; /* visual centering for play triangle */\n }\n\n /* ------------------------------------------------------------------ */\n /* Watermark */\n /* ------------------------------------------------------------------ */\n\n .vz-watermark {\n position: absolute;\n bottom: 48px;\n right: 12px;\n z-index: 15;\n pointer-events: auto;\n }\n\n /* ------------------------------------------------------------------ */\n /* Controls behavior variants */\n /* ------------------------------------------------------------------ */\n\n /* \"always\" mode \u2014 never hide */\n :host([controls-behavior=\"always\"]) .vz-controls-wrapper {\n opacity: 1 !important;\n pointer-events: auto !important;\n transform: none !important;\n }\n\n /* \"minimal\" mode \u2014 only thin progress bar always visible */\n :host([controls-behavior=\"minimal\"]) .vz-controls-wrapper.hidden .vz-controls {\n opacity: 0;\n pointer-events: none;\n }\n\n :host([controls-behavior=\"minimal\"]) .vz-controls-wrapper.hidden .vz-seek-row {\n opacity: 1;\n pointer-events: auto;\n }\n\n :host([controls-behavior=\"minimal\"]) .vz-controls-wrapper.hidden {\n opacity: 1;\n pointer-events: auto;\n transform: none;\n }\n\n /* ------------------------------------------------------------------ */\n /* Live indicator */\n /* ------------------------------------------------------------------ */\n\n .vz-live-indicator {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 0 8px;\n cursor: pointer;\n flex-shrink: 0;\n transition: opacity 0.2s;\n user-select: none;\n }\n\n .vz-live-indicator:hover {\n opacity: 1;\n }\n\n .vz-live-dot {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 12px;\n height: 12px;\n }\n\n .vz-live-dot svg {\n width: 10px;\n height: 10px;\n }\n\n .vz-live-dot.at-edge {\n color: #ef4444;\n animation: vz-live-pulse 2s ease-in-out infinite;\n }\n\n .vz-live-dot.behind {\n color: #6b7280;\n animation: none;\n }\n\n .vz-live-label {\n font-size: 11px;\n font-weight: 700;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: rgba(255, 255, 255, 0.9);\n }\n\n @keyframes vz-live-pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n }\n\n /* ------------------------------------------------------------------ */\n /* Caption overlay (HUD) */\n /* ------------------------------------------------------------------ */\n\n .vz-caption-overlay {\n position: absolute;\n bottom: 60px;\n left: 50%;\n transform: translateX(-50%);\n max-width: 80%;\n padding: 4px 12px;\n background: rgba(0, 0, 0, 0.75);\n border-radius: 4px;\n color: #fff;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 16px;\n line-height: 1.4;\n text-align: center;\n z-index: 12;\n pointer-events: none;\n opacity: 0;\n transition: opacity 0.15s ease;\n white-space: pre-wrap;\n word-wrap: break-word;\n }\n\n .vz-caption-overlay.visible {\n opacity: 1;\n }\n\n /* ------------------------------------------------------------------ */\n /* CC button & dropdown */\n /* ------------------------------------------------------------------ */\n\n .vz-cc-menu {\n position: relative;\n }\n\n .vz-cc-btn.active {\n color: var(--vz-primary, #f43f5e);\n opacity: 1;\n }\n\n .vz-cc-dropdown {\n position: absolute;\n bottom: 100%;\n right: 0;\n margin-bottom: 8px;\n background: var(--vz-secondary, rgba(20, 20, 30, 0.95));\n backdrop-filter: blur(16px) saturate(1.3);\n -webkit-backdrop-filter: blur(16px) saturate(1.3);\n border: 1px solid rgba(255, 255, 255, 0.06);\n border-radius: 8px;\n padding: 4px 0;\n min-width: 120px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.04);\n display: none;\n z-index: 20;\n }\n\n .vz-cc-dropdown.open {\n display: block;\n }\n\n .vz-cc-option {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n cursor: pointer;\n font-size: 13px;\n color: rgba(255, 255, 255, 0.7);\n white-space: nowrap;\n transition: color 0.12s, background 0.12s;\n }\n\n .vz-cc-option:hover {\n background: rgba(244, 63, 94, 0.08);\n background: color-mix(in srgb, var(--vz-primary, #f43f5e) 8%, transparent);\n color: #fff;\n }\n\n .vz-cc-option.active {\n color: var(--vz-primary, #f43f5e);\n }\n\n .vz-cc-check {\n width: 16px;\n font-size: 14px;\n }\n\n /* ------------------------------------------------------------------ */\n /* Chat badge */\n /* ------------------------------------------------------------------ */\n\n .vz-chat-badge {\n position: absolute;\n top: 2px;\n right: 2px;\n min-width: 16px;\n height: 16px;\n border-radius: 8px;\n background: #ef4444;\n color: #fff;\n font-size: 10px;\n font-weight: 700;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0 4px;\n pointer-events: none;\n line-height: 1;\n }\n\n /* ------------------------------------------------------------------ */\n /* Responsive */\n /* ------------------------------------------------------------------ */\n\n @media (max-width: 400px) {\n .vz-volume-slider-wrap,\n .vz-volume-slider {\n display: none;\n }\n }\n";
14
+ export declare const CONTROLS_CSS = "\n /* ------------------------------------------------------------------ */\n /* Layout \u2014 wrapper + seek above button row */\n /* ------------------------------------------------------------------ */\n\n .vz-controls-wrapper {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n z-index: 10;\n user-select: none;\n -webkit-user-select: none;\n transition: opacity var(--vz-controls-transition, 0.3s) ease,\n transform 0.2s ease;\n }\n\n .vz-controls-wrapper.hidden {\n opacity: 0;\n pointer-events: none;\n transform: translateY(4px);\n }\n\n /* Progress bar sits above the button row */\n .vz-seek-row {\n position: relative;\n width: 100%;\n padding: 0 12px;\n cursor: pointer;\n z-index: 11;\n }\n\n /* Button row */\n .vz-controls {\n display: flex;\n align-items: center;\n gap: 2px;\n padding: 4px 8px 6px;\n background: linear-gradient(transparent, var(--vz-controls-bg, rgba(0, 0, 0, 0.6)));\n backdrop-filter: blur(4px);\n -webkit-backdrop-filter: blur(4px);\n color: #fff;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 13px;\n }\n\n .vz-controls-left {\n display: flex;\n align-items: center;\n gap: 2px;\n flex-shrink: 0;\n }\n\n .vz-controls-center {\n flex: 1;\n min-width: 0;\n }\n\n .vz-controls-right {\n display: flex;\n align-items: center;\n gap: 2px;\n flex-shrink: 0;\n }\n\n /* ------------------------------------------------------------------ */\n /* Buttons */\n /* ------------------------------------------------------------------ */\n\n .vz-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: var(--vz-button-size, 36px);\n height: var(--vz-button-size, 36px);\n padding: 0;\n border: none;\n border-radius: 50%;\n background: transparent;\n color: #fff;\n cursor: pointer;\n flex-shrink: 0;\n transition: opacity 0.15s, transform 0.15s;\n opacity: 0.9;\n }\n\n .vz-btn:hover {\n opacity: 1;\n transform: scale(1.1);\n }\n\n .vz-btn:active {\n transform: scale(0.95);\n }\n\n .vz-btn:focus-visible {\n outline: 2px solid var(--vz-primary, #f43f5e);\n outline-offset: 2px;\n }\n\n .vz-btn svg {\n width: 20px;\n height: 20px;\n fill: currentColor;\n }\n\n /* ------------------------------------------------------------------ */\n /* Seek / Progress bar */\n /* ------------------------------------------------------------------ */\n\n .vz-seek-container {\n position: relative;\n display: flex;\n align-items: center;\n width: 100%;\n height: 18px;\n cursor: pointer;\n }\n\n .vz-seek-track {\n position: relative;\n width: 100%;\n height: var(--vz-progress-height, 3px);\n background: rgba(255, 255, 255, 0.2);\n border-radius: 99px;\n overflow: visible;\n transition: height 0.15s ease;\n }\n\n .vz-seek-container:hover .vz-seek-track {\n height: 5px;\n }\n\n .vz-seek-chapters {\n position: absolute;\n inset: 0;\n pointer-events: none;\n z-index: 3;\n }\n\n .vz-seek-chapter-marker {\n position: absolute;\n top: 50%;\n width: 2px;\n height: 100%;\n transform: translate(-50%, -50%);\n background: rgba(0, 0, 0, 0.55);\n box-shadow: 0 0 0 0.5px rgba(255, 255, 255, 0.5);\n pointer-events: none;\n }\n\n .vz-seek-buffered {\n position: absolute;\n top: 0;\n left: 0;\n height: 100%;\n background: linear-gradient(\n 90deg,\n rgba(255, 255, 255, 0.25),\n rgba(255, 255, 255, 0.35)\n );\n border-radius: 99px;\n }\n\n .vz-seek-played {\n position: absolute;\n top: 0;\n left: 0;\n height: 100%;\n background: var(--vz-progress-color, var(--vz-primary, #f43f5e));\n border-radius: 99px;\n box-shadow: 0 0 8px rgba(244, 63, 94, 0.4);\n box-shadow: 0 0 8px color-mix(in srgb, var(--vz-primary, #f43f5e) 40%, transparent);\n }\n\n .vz-seek-thumb {\n position: absolute;\n top: 50%;\n width: 13px;\n height: 13px;\n border-radius: 50%;\n background: #fff;\n box-shadow: 0 0 4px rgba(0, 0, 0, 0.3);\n transform: translate(-50%, -50%) scale(0);\n transition: transform 0.15s ease, box-shadow 0.15s ease;\n pointer-events: none;\n }\n\n .vz-seek-container:hover .vz-seek-thumb {\n transform: translate(-50%, -50%) scale(1);\n box-shadow: 0 0 6px rgba(244, 63, 94, 0.5);\n box-shadow: 0 0 6px color-mix(in srgb, var(--vz-primary, #f43f5e) 50%, transparent);\n }\n\n .vz-seek-input {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n margin: 0;\n padding: 0;\n opacity: 0;\n cursor: pointer;\n -webkit-appearance: none;\n appearance: none;\n }\n\n /* Hover time tooltip */\n .vz-seek-tooltip {\n position: absolute;\n bottom: 100%;\n margin-bottom: 6px;\n padding: 3px 7px;\n background: var(--vz-secondary, rgba(0, 0, 0, 0.85));\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n color: #fff;\n font-size: 12px;\n font-variant-numeric: tabular-nums;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n border-radius: 4px;\n white-space: nowrap;\n pointer-events: none;\n transform: translateX(-50%);\n opacity: 0;\n transition: opacity 0.12s;\n }\n\n .vz-seek-container:hover .vz-seek-tooltip {\n opacity: 1;\n }\n\n .vz-time {\n font-size: 12px;\n font-weight: 400;\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n padding: 0 6px;\n flex-shrink: 0;\n opacity: 0.9;\n letter-spacing: 0.02em;\n }\n\n /* ------------------------------------------------------------------ */\n /* Volume \u2014 horizontal slide-out on hover */\n /* ------------------------------------------------------------------ */\n\n .vz-volume {\n display: flex;\n align-items: center;\n gap: 0;\n overflow: hidden;\n }\n\n .vz-volume-slider-wrap {\n width: 0;\n overflow: hidden;\n transition: width 0.2s ease;\n }\n\n .vz-volume:hover .vz-volume-slider-wrap {\n width: 64px;\n }\n\n .vz-volume-slider {\n width: 60px;\n height: 4px;\n margin: 0 4px;\n -webkit-appearance: none;\n appearance: none;\n background: rgba(255, 255, 255, 0.3);\n border-radius: 99px;\n outline: none;\n cursor: pointer;\n }\n\n .vz-volume-slider::-webkit-slider-thumb {\n -webkit-appearance: none;\n width: 12px;\n height: 12px;\n border-radius: 50%;\n background: #fff;\n cursor: pointer;\n box-shadow: 0 0 3px rgba(0, 0, 0, 0.2);\n }\n\n .vz-volume-slider::-moz-range-thumb {\n width: 12px;\n height: 12px;\n border: none;\n border-radius: 50%;\n background: #fff;\n cursor: pointer;\n box-shadow: 0 0 3px rgba(0, 0, 0, 0.2);\n }\n\n /* ------------------------------------------------------------------ */\n /* Quality menu */\n /* ------------------------------------------------------------------ */\n\n .vz-quality-menu {\n position: relative;\n }\n\n .vz-quality-dropdown {\n position: absolute;\n bottom: 100%;\n right: 0;\n margin-bottom: 8px;\n background: var(--vz-secondary, rgba(20, 20, 30, 0.95));\n backdrop-filter: blur(16px) saturate(1.3);\n -webkit-backdrop-filter: blur(16px) saturate(1.3);\n border: 1px solid rgba(255, 255, 255, 0.06);\n border-radius: 8px;\n padding: 4px 0;\n min-width: 120px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.04);\n display: none;\n z-index: 20;\n }\n\n .vz-quality-dropdown.open {\n display: block;\n }\n\n .vz-quality-option {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n cursor: pointer;\n font-size: 13px;\n color: rgba(255, 255, 255, 0.7);\n white-space: nowrap;\n transition: color 0.12s, background 0.12s;\n }\n\n .vz-quality-option:hover {\n background: rgba(244, 63, 94, 0.08);\n background: color-mix(in srgb, var(--vz-primary, #f43f5e) 8%, transparent);\n color: #fff;\n }\n\n .vz-quality-option.active {\n color: var(--vz-primary, #f43f5e);\n }\n\n .vz-quality-check {\n width: 16px;\n font-size: 14px;\n }\n\n /* ------------------------------------------------------------------ */\n /* Compass */\n /* ------------------------------------------------------------------ */\n\n .vz-compass {\n position: relative;\n }\n\n .vz-compass svg {\n fill: none;\n stroke: currentColor;\n transition: transform 0.1s ease-out;\n }\n\n /* ------------------------------------------------------------------ */\n /* Loading spinner \u2014 CSS ring */\n /* ------------------------------------------------------------------ */\n\n .vz-loading {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 44px;\n height: 44px;\n z-index: 5;\n pointer-events: none;\n }\n\n .vz-loading-spinner {\n width: 100%;\n height: 100%;\n border: 2.5px solid rgba(255, 255, 255, 0.15);\n border-top-color: var(--vz-primary, #f43f5e);\n border-radius: 50%;\n animation: vz-spin 0.75s linear infinite;\n }\n\n .vz-loading.hidden {\n display: none;\n }\n\n @keyframes vz-spin {\n to { transform: rotate(360deg); }\n }\n\n /* ------------------------------------------------------------------ */\n /* Big play button \u2014 frosted glass */\n /* ------------------------------------------------------------------ */\n\n .vz-big-play {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 68px;\n height: 68px;\n border: 1px solid rgba(255, 255, 255, 0.08);\n border-radius: 50%;\n background: rgba(15, 10, 20, 0.4);\n backdrop-filter: blur(12px) saturate(1.2);\n -webkit-backdrop-filter: blur(12px) saturate(1.2);\n color: #fff;\n cursor: pointer;\n z-index: 5;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background-color 0.25s ease, transform 0.25s ease, opacity 0.25s ease, box-shadow 0.25s ease;\n opacity: 1;\n box-shadow: 0 0 20px rgba(244, 63, 94, 0.15);\n box-shadow: 0 0 20px color-mix(in srgb, var(--vz-primary, #f43f5e) 15%, transparent);\n }\n\n .vz-big-play:hover {\n background: rgba(15, 10, 20, 0.55);\n transform: translate(-50%, -50%) scale(1.08);\n box-shadow: 0 0 30px rgba(244, 63, 94, 0.25);\n box-shadow: 0 0 30px color-mix(in srgb, var(--vz-primary, #f43f5e) 25%, transparent);\n }\n\n .vz-big-play.hidden {\n opacity: 0;\n pointer-events: none;\n transform: translate(-50%, -50%) scale(0.85);\n }\n\n .vz-big-play svg {\n width: 30px;\n height: 30px;\n fill: currentColor;\n margin-left: 3px; /* visual centering for play triangle */\n }\n\n /* ------------------------------------------------------------------ */\n /* Watermark */\n /* ------------------------------------------------------------------ */\n\n .vz-watermark {\n position: absolute;\n bottom: 48px;\n right: 12px;\n z-index: 15;\n pointer-events: auto;\n }\n\n /* ------------------------------------------------------------------ */\n /* Controls behavior variants */\n /* ------------------------------------------------------------------ */\n\n /* \"always\" mode \u2014 never hide */\n :host([controls-behavior=\"always\"]) .vz-controls-wrapper {\n opacity: 1 !important;\n pointer-events: auto !important;\n transform: none !important;\n }\n\n /* \"minimal\" mode \u2014 only thin progress bar always visible */\n :host([controls-behavior=\"minimal\"]) .vz-controls-wrapper.hidden .vz-controls {\n opacity: 0;\n pointer-events: none;\n }\n\n :host([controls-behavior=\"minimal\"]) .vz-controls-wrapper.hidden .vz-seek-row {\n opacity: 1;\n pointer-events: auto;\n }\n\n :host([controls-behavior=\"minimal\"]) .vz-controls-wrapper.hidden {\n opacity: 1;\n pointer-events: auto;\n transform: none;\n }\n\n /* ------------------------------------------------------------------ */\n /* Live indicator */\n /* ------------------------------------------------------------------ */\n\n .vz-live-indicator {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 0 8px;\n cursor: pointer;\n flex-shrink: 0;\n transition: opacity 0.2s;\n user-select: none;\n }\n\n .vz-live-indicator:hover {\n opacity: 1;\n }\n\n .vz-live-dot {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 12px;\n height: 12px;\n }\n\n .vz-live-dot svg {\n width: 10px;\n height: 10px;\n }\n\n .vz-live-dot.at-edge {\n color: #ef4444;\n animation: vz-live-pulse 2s ease-in-out infinite;\n }\n\n .vz-live-dot.behind {\n color: #6b7280;\n animation: none;\n }\n\n .vz-live-label {\n font-size: 11px;\n font-weight: 700;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: rgba(255, 255, 255, 0.9);\n }\n\n @keyframes vz-live-pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n }\n\n /* ------------------------------------------------------------------ */\n /* Caption overlay (HUD) */\n /* ------------------------------------------------------------------ */\n\n .vz-caption-overlay {\n position: absolute;\n bottom: 60px;\n left: 50%;\n transform: translateX(-50%);\n max-width: 80%;\n padding: 4px 12px;\n background: rgba(0, 0, 0, 0.75);\n border-radius: 4px;\n color: #fff;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 16px;\n line-height: 1.4;\n text-align: center;\n z-index: 12;\n pointer-events: none;\n opacity: 0;\n transition: opacity 0.15s ease;\n white-space: pre-wrap;\n word-wrap: break-word;\n }\n\n .vz-caption-overlay.visible {\n opacity: 1;\n }\n\n /* ------------------------------------------------------------------ */\n /* CC button & dropdown */\n /* ------------------------------------------------------------------ */\n\n .vz-cc-menu {\n position: relative;\n }\n\n .vz-cc-btn.active {\n color: var(--vz-primary, #f43f5e);\n opacity: 1;\n }\n\n .vz-cc-dropdown {\n position: absolute;\n bottom: 100%;\n right: 0;\n margin-bottom: 8px;\n background: var(--vz-secondary, rgba(20, 20, 30, 0.95));\n backdrop-filter: blur(16px) saturate(1.3);\n -webkit-backdrop-filter: blur(16px) saturate(1.3);\n border: 1px solid rgba(255, 255, 255, 0.06);\n border-radius: 8px;\n padding: 4px 0;\n min-width: 120px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.04);\n display: none;\n z-index: 20;\n }\n\n .vz-cc-dropdown.open {\n display: block;\n }\n\n .vz-cc-option {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n cursor: pointer;\n font-size: 13px;\n color: rgba(255, 255, 255, 0.7);\n white-space: nowrap;\n transition: color 0.12s, background 0.12s;\n }\n\n .vz-cc-option:hover {\n background: rgba(244, 63, 94, 0.08);\n background: color-mix(in srgb, var(--vz-primary, #f43f5e) 8%, transparent);\n color: #fff;\n }\n\n .vz-cc-option.active {\n color: var(--vz-primary, #f43f5e);\n }\n\n .vz-cc-check {\n width: 16px;\n font-size: 14px;\n }\n\n /* ------------------------------------------------------------------ */\n /* Chapters menu */\n /* ------------------------------------------------------------------ */\n\n .vz-chapter-menu {\n position: relative;\n }\n\n .vz-chapter-dropdown {\n position: absolute;\n bottom: 100%;\n right: 0;\n margin-bottom: 8px;\n background: var(--vz-secondary, rgba(20, 20, 30, 0.95));\n backdrop-filter: blur(16px) saturate(1.3);\n -webkit-backdrop-filter: blur(16px) saturate(1.3);\n border: 1px solid rgba(255, 255, 255, 0.06);\n border-radius: 8px;\n padding: 4px 0;\n min-width: 200px;\n max-height: 260px;\n overflow-y: auto;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.04);\n display: none;\n z-index: 20;\n }\n\n .vz-chapter-dropdown.open {\n display: block;\n }\n\n .vz-chapter-option {\n display: flex;\n align-items: baseline;\n gap: 10px;\n padding: 8px 16px;\n cursor: pointer;\n font-size: 13px;\n color: rgba(255, 255, 255, 0.7);\n white-space: nowrap;\n transition: color 0.12s, background 0.12s;\n }\n\n .vz-chapter-option:hover {\n background: color-mix(in srgb, var(--vz-primary, #f43f5e) 8%, transparent);\n color: #fff;\n }\n\n .vz-chapter-option.active {\n color: var(--vz-primary, #f43f5e);\n }\n\n .vz-chapter-time {\n font-variant-numeric: tabular-nums;\n font-size: 12px;\n color: rgba(255, 255, 255, 0.45);\n flex-shrink: 0;\n }\n\n .vz-chapter-option.active .vz-chapter-time {\n color: var(--vz-primary, #f43f5e);\n }\n\n .vz-chapter-label {\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n /* ------------------------------------------------------------------ */\n /* Chat badge */\n /* ------------------------------------------------------------------ */\n\n .vz-chat-badge {\n position: absolute;\n top: 2px;\n right: 2px;\n min-width: 16px;\n height: 16px;\n border-radius: 8px;\n background: #ef4444;\n color: #fff;\n font-size: 10px;\n font-weight: 700;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0 4px;\n pointer-events: none;\n line-height: 1;\n }\n\n /* ------------------------------------------------------------------ */\n /* Responsive */\n /* ------------------------------------------------------------------ */\n\n @media (max-width: 400px) {\n .vz-volume-slider-wrap,\n .vz-volume-slider {\n display: none;\n }\n }\n";
15
15
  //# sourceMappingURL=controls.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"controls.d.ts","sourceRoot":"","sources":["../../src/styles/controls.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,YAAY,01gBAwoBxB,CAAC"}
1
+ {"version":3,"file":"controls.d.ts","sourceRoot":"","sources":["../../src/styles/controls.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,YAAY,s6kBA8tBxB,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * The player's single audited raw-`innerHTML` sink for compile-time-constant
3
+ * markup: control icons from `controls/icons.ts` and fixed scaffolding like
4
+ * the loading spinner. Callers MUST pass only module-level string constants —
5
+ * never user input, server responses, media metadata, or anything derived
6
+ * from them. Dynamic content goes through `sanitize.ts` (DOMPurify) instead.
7
+ *
8
+ * Centralizing the sink lets the semgrep `no-raw-innerhtml` rule run at ERROR
9
+ * with exactly one suppression in shipped player code.
10
+ */
11
+ export declare function setStaticHtml(el: Element, constantHtml: string): void;
12
+ //# sourceMappingURL=static-html.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"static-html.d.ts","sourceRoot":"","sources":["../../src/utils/static-html.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CAGrE"}
package/dist/vizor.js CHANGED
@@ -1,8 +1,8 @@
1
- import { C, a, H, K, P, S, V, b, c, d, e, f, g, h, i, j, k, l, m, X, n, o, p, r, q, s, t, u, v, w, x, y, z, A } from "./register-CwnmiGEs.js";
1
+ import { C, a, H, K, P, S, V, b, c, d, e, f, g, h, i, j, k, l, m, X, n, o, p, r, q, s, t, u, v, w, x, y, z, A } from "./register-BmZt_300.js";
2
2
  import { A as A2 } from "./spatial-BeadwNJA.js";
3
- import { C as C2, p as p2 } from "./captions-BP0H2E03.js";
4
- import { A as A3, c as c2, d as d2 } from "./annotations-C0ugfCn4.js";
5
- import { C as C3, a as a2, b as b2, G, c as c3, V as V2, d as d3 } from "./collab-BXPomrS0.js";
3
+ import { C as C2, p as p2 } from "./captions-YvnHAwLY.js";
4
+ import { A as A3, c as c2, d as d2 } from "./annotations-Du6ZWrqC.js";
5
+ import { C as C3, a as a2, b as b2, G, c as c3, V as V2, d as d3 } from "./collab-BLpllHtb.js";
6
6
  class QualitySelector {
7
7
  adapter = null;
8
8
  state;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vizor-vr/player",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "VR video player for the modern web — 360°, VR, live streaming, virtual tours",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -38,14 +38,17 @@
38
38
  ],
39
39
  "repository": {
40
40
  "type": "git",
41
- "url": "https://github.com/vizor-vr/player.git",
41
+ "url": "git+https://github.com/vizor-vr/vizor-vr.git",
42
42
  "directory": "packages/player"
43
43
  },
44
+ "bugs": {
45
+ "url": "https://github.com/vizor-vr/vizor-vr/issues"
46
+ },
44
47
  "homepage": "https://vizor.dev",
45
48
  "dependencies": {
46
- "dompurify": "^3.2.4",
49
+ "dompurify": "^3.4.12",
47
50
  "three": "^0.170.0",
48
- "@vizor-vr/shared": "0.1.0"
51
+ "@vizor-vr/shared": "0.2.1"
49
52
  },
50
53
  "devDependencies": {
51
54
  "@playwright/test": "^1.58.2",
@@ -55,7 +58,7 @@
55
58
  "@vitest/coverage-v8": "^2.1.0",
56
59
  "jsdom": "^25.0.0",
57
60
  "rimraf": "^6.0.0",
58
- "tsx": "^4.19.0",
61
+ "tsx": "^4.23.0",
59
62
  "typescript": "^5.7.0",
60
63
  "vite": "^6.0.0",
61
64
  "vitest": "^2.1.0",
@@ -1 +0,0 @@
1
- {"version":3,"file":"license-checker.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/license-checker.test.ts"],"names":[],"mappings":""}
@@ -1 +0,0 @@
1
- {"version":3,"file":"master-key.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/master-key.test.ts"],"names":[],"mappings":""}