prismcast 1.12.0 → 1.13.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.
Files changed (631) hide show
  1. package/dist/app.d.ts +41 -1
  2. package/dist/app.js +164 -76
  3. package/dist/app.js.map +1 -1
  4. package/dist/browser/blockedPage.d.ts +0 -1
  5. package/dist/browser/browserSupervisor.d.ts +34 -5
  6. package/dist/browser/browserSupervisor.js +39 -12
  7. package/dist/browser/browserSupervisor.js.map +1 -1
  8. package/dist/browser/cdp.d.ts +58 -6
  9. package/dist/browser/cdp.js +147 -9
  10. package/dist/browser/cdp.js.map +1 -1
  11. package/dist/browser/channelSelection.d.ts +18 -6
  12. package/dist/browser/channelSelection.js +47 -36
  13. package/dist/browser/channelSelection.js.map +1 -1
  14. package/dist/browser/consent.d.ts +33 -4
  15. package/dist/browser/consent.js +87 -50
  16. package/dist/browser/consent.js.map +1 -1
  17. package/dist/browser/display.d.ts +0 -1
  18. package/dist/browser/hlsPlaylistObserver.d.ts +3 -2
  19. package/dist/browser/hlsPlaylistObserver.js +11 -6
  20. package/dist/browser/hlsPlaylistObserver.js.map +1 -1
  21. package/dist/browser/index.d.ts +273 -59
  22. package/dist/browser/index.js +768 -255
  23. package/dist/browser/index.js.map +1 -1
  24. package/dist/browser/launchGovernor.d.ts +0 -1
  25. package/dist/browser/login.d.ts +11 -10
  26. package/dist/browser/login.js +42 -33
  27. package/dist/browser/login.js.map +1 -1
  28. package/dist/browser/manifestInterceptor.d.ts +14 -5
  29. package/dist/browser/manifestInterceptor.js +26 -13
  30. package/dist/browser/manifestInterceptor.js.map +1 -1
  31. package/dist/browser/navigation.d.ts +28 -0
  32. package/dist/browser/navigation.js +57 -0
  33. package/dist/browser/navigation.js.map +1 -0
  34. package/dist/browser/pageStaleness.d.ts +1 -2
  35. package/dist/browser/pageStaleness.js +9 -9
  36. package/dist/browser/pageStaleness.js.map +1 -1
  37. package/dist/browser/precaching.d.ts +27 -13
  38. package/dist/browser/precaching.js +219 -73
  39. package/dist/browser/precaching.js.map +1 -1
  40. package/dist/browser/tabCapture.d.ts +97 -0
  41. package/dist/browser/tabCapture.js +314 -0
  42. package/dist/browser/tabCapture.js.map +1 -0
  43. package/dist/browser/tabNetworkObserver.d.ts +0 -1
  44. package/dist/browser/tabSelection.d.ts +117 -0
  45. package/dist/browser/tabSelection.js +547 -0
  46. package/dist/browser/tabSelection.js.map +1 -0
  47. package/dist/browser/tuning/cache.d.ts +0 -1
  48. package/dist/browser/tuning/comcastPolymer.d.ts +0 -1
  49. package/dist/browser/tuning/comcastPolymer.js +18 -19
  50. package/dist/browser/tuning/comcastPolymer.js.map +1 -1
  51. package/dist/browser/tuning/cox.d.ts +0 -1
  52. package/dist/browser/tuning/directv.d.ts +0 -1
  53. package/dist/browser/tuning/directv.js +12 -13
  54. package/dist/browser/tuning/directv.js.map +1 -1
  55. package/dist/browser/tuning/fox.d.ts +0 -1
  56. package/dist/browser/tuning/fox.js +2 -2
  57. package/dist/browser/tuning/fox.js.map +1 -1
  58. package/dist/browser/tuning/gridSearch.d.ts +0 -1
  59. package/dist/browser/tuning/hbo.d.ts +0 -1
  60. package/dist/browser/tuning/hbo.js +2 -2
  61. package/dist/browser/tuning/hbo.js.map +1 -1
  62. package/dist/browser/tuning/hulu.d.ts +14 -2
  63. package/dist/browser/tuning/hulu.js +150 -24
  64. package/dist/browser/tuning/hulu.js.map +1 -1
  65. package/dist/browser/tuning/shared.d.ts +1 -2
  66. package/dist/browser/tuning/shared.js +1 -1
  67. package/dist/browser/tuning/sling.d.ts +0 -1
  68. package/dist/browser/tuning/sling.js +17 -22
  69. package/dist/browser/tuning/sling.js.map +1 -1
  70. package/dist/browser/tuning/spectrum.d.ts +0 -1
  71. package/dist/browser/tuning/thumbnailRow.d.ts +0 -1
  72. package/dist/browser/tuning/tileClick.d.ts +0 -1
  73. package/dist/browser/tuning/xfinity.d.ts +0 -1
  74. package/dist/browser/tuning/youtubeTv.d.ts +0 -1
  75. package/dist/browser/tuning/youtubeTv.js +1 -2
  76. package/dist/browser/tuning/youtubeTv.js.map +1 -1
  77. package/dist/browser/video.d.ts +55 -33
  78. package/dist/browser/video.js +213 -169
  79. package/dist/browser/video.js.map +1 -1
  80. package/dist/browser/windowSync.d.ts +45 -0
  81. package/dist/browser/windowSync.js +153 -0
  82. package/dist/browser/windowSync.js.map +1 -0
  83. package/dist/channels/index.d.ts +7 -1
  84. package/dist/channels/index.js +24 -8
  85. package/dist/channels/index.js.map +1 -1
  86. package/dist/config/channelForm.d.ts +0 -1
  87. package/dist/config/channelIdentity.d.ts +27 -0
  88. package/dist/config/channelIdentity.js +72 -0
  89. package/dist/config/channelIdentity.js.map +1 -0
  90. package/dist/config/channelSort.d.ts +25 -0
  91. package/dist/config/channelSort.js +101 -0
  92. package/dist/config/channelSort.js.map +1 -0
  93. package/dist/config/consistencyProbe.d.ts +0 -1
  94. package/dist/config/consistencyProbe.js +1 -1
  95. package/dist/config/consistencyProbe.js.map +1 -1
  96. package/dist/config/health.d.ts +3 -2
  97. package/dist/config/health.js +41 -31
  98. package/dist/config/health.js.map +1 -1
  99. package/dist/config/index.d.ts +12 -1
  100. package/dist/config/index.js +77 -31
  101. package/dist/config/index.js.map +1 -1
  102. package/dist/config/paths.d.ts +17 -2
  103. package/dist/config/paths.js +21 -1
  104. package/dist/config/paths.js.map +1 -1
  105. package/dist/config/persistence.context.d.ts +0 -1
  106. package/dist/config/persistence.d.ts +8 -4
  107. package/dist/config/persistence.js +143 -82
  108. package/dist/config/persistence.js.map +1 -1
  109. package/dist/config/presets.d.ts +0 -1
  110. package/dist/config/profiles.d.ts +9 -4
  111. package/dist/config/profiles.js +39 -6
  112. package/dist/config/profiles.js.map +1 -1
  113. package/dist/config/providerLineups.d.ts +0 -1
  114. package/dist/config/providerLineups.js +0 -3
  115. package/dist/config/providerLineups.js.map +1 -1
  116. package/dist/config/reactivity.d.ts +0 -1
  117. package/dist/config/servicePacks.d.ts +0 -1
  118. package/dist/config/services.d.ts +1 -47
  119. package/dist/config/services.js +4 -135
  120. package/dist/config/services.js.map +1 -1
  121. package/dist/config/sites.d.ts +0 -9
  122. package/dist/config/sites.js +82 -98
  123. package/dist/config/sites.js.map +1 -1
  124. package/dist/config/userChannels.d.ts +22 -29
  125. package/dist/config/userChannels.js +47 -65
  126. package/dist/config/userChannels.js.map +1 -1
  127. package/dist/config/userConfig.d.ts +19 -4
  128. package/dist/config/userConfig.js +123 -25
  129. package/dist/config/userConfig.js.map +1 -1
  130. package/dist/config/userProfiles.d.ts +2 -3
  131. package/dist/config/userProfiles.js +16 -13
  132. package/dist/config/userProfiles.js.map +1 -1
  133. package/dist/hdhr/channelMap.d.ts +0 -1
  134. package/dist/hdhr/deviceId.d.ts +0 -1
  135. package/dist/hdhr/discover.d.ts +0 -1
  136. package/dist/hdhr/getHandlers.d.ts +0 -1
  137. package/dist/hdhr/identity.d.ts +0 -1
  138. package/dist/hdhr/index.d.ts +0 -1
  139. package/dist/hdhr/protocol.d.ts +1 -2
  140. package/dist/hdhr/protocol.js +1 -1
  141. package/dist/hdhr/tunerState.d.ts +0 -1
  142. package/dist/hdhr/udp.d.ts +0 -1
  143. package/dist/hdhr/udp.js +16 -4
  144. package/dist/hdhr/udp.js.map +1 -1
  145. package/dist/identity.d.ts +0 -1
  146. package/dist/index.d.ts +0 -1
  147. package/dist/index.js +10 -3
  148. package/dist/index.js.map +1 -1
  149. package/dist/native/codecInference.d.ts +5 -4
  150. package/dist/native/codecInference.js +12 -7
  151. package/dist/native/codecInference.js.map +1 -1
  152. package/dist/native/decrypt.d.ts +10 -3
  153. package/dist/native/decrypt.js +9 -5
  154. package/dist/native/decrypt.js.map +1 -1
  155. package/dist/native/index.d.ts +26 -24
  156. package/dist/native/index.js +26 -20
  157. package/dist/native/index.js.map +1 -1
  158. package/dist/native/probe.d.ts +7 -10
  159. package/dist/native/probe.js +41 -37
  160. package/dist/native/probe.js.map +1 -1
  161. package/dist/native/proxy.d.ts +3 -4
  162. package/dist/native/proxy.js +91 -69
  163. package/dist/native/proxy.js.map +1 -1
  164. package/dist/native/tokenExpiry.d.ts +0 -1
  165. package/dist/routes/assets.d.ts +0 -1
  166. package/dist/routes/auth.d.ts +0 -1
  167. package/dist/routes/auth.js +1 -1
  168. package/dist/routes/auth.js.map +1 -1
  169. package/dist/routes/cdp.d.ts +11 -5
  170. package/dist/routes/cdp.js +91 -63
  171. package/dist/routes/cdp.js.map +1 -1
  172. package/dist/routes/channels.d.ts +0 -1
  173. package/dist/routes/clientActions.d.ts +0 -1
  174. package/dist/routes/components.d.ts +0 -1
  175. package/dist/routes/config/channels/endpoints/browse.d.ts +0 -1
  176. package/dist/routes/config/channels/endpoints/bulk.d.ts +0 -1
  177. package/dist/routes/config/channels/endpoints/bulk.js +3 -3
  178. package/dist/routes/config/channels/endpoints/bulk.js.map +1 -1
  179. package/dist/routes/config/channels/endpoints/crud.d.ts +0 -1
  180. package/dist/routes/config/channels/endpoints/crud.js +4 -3
  181. package/dist/routes/config/channels/endpoints/crud.js.map +1 -1
  182. package/dist/routes/config/channels/endpoints/importExport.d.ts +0 -1
  183. package/dist/routes/config/channels/endpoints/importExport.js +7 -3
  184. package/dist/routes/config/channels/endpoints/importExport.js.map +1 -1
  185. package/dist/routes/config/channels/endpoints/predefined.d.ts +0 -1
  186. package/dist/routes/config/channels/endpoints/prefs.d.ts +0 -1
  187. package/dist/routes/config/channels/endpoints/prefs.js +1 -1
  188. package/dist/routes/config/channels/endpoints/prefs.js.map +1 -1
  189. package/dist/routes/config/channels/endpoints/service.d.ts +0 -1
  190. package/dist/routes/config/channels/endpoints/service.js +8 -5
  191. package/dist/routes/config/channels/endpoints/service.js.map +1 -1
  192. package/dist/routes/config/channels/endpoints/tags.d.ts +0 -1
  193. package/dist/routes/config/channels/endpoints/tags.js +3 -3
  194. package/dist/routes/config/channels/endpoints/tags.js.map +1 -1
  195. package/dist/routes/config/channels/healthBridge.d.ts +4 -1
  196. package/dist/routes/config/channels/healthBridge.js +9 -5
  197. package/dist/routes/config/channels/healthBridge.js.map +1 -1
  198. package/dist/routes/config/channels/http/handler.d.ts +0 -1
  199. package/dist/routes/config/channels/http/playlistHint.d.ts +0 -1
  200. package/dist/routes/config/channels/http/serviceWarning.d.ts +0 -1
  201. package/dist/routes/config/channels/http/serviceWarning.js +1 -1
  202. package/dist/routes/config/channels/http/serviceWarning.js.map +1 -1
  203. package/dist/routes/config/channels/index.d.ts +0 -1
  204. package/dist/routes/config/channels/setup.d.ts +0 -1
  205. package/dist/routes/config/channels/table.d.ts +0 -1
  206. package/dist/routes/config/channels/table.js +66 -134
  207. package/dist/routes/config/channels/table.js.map +1 -1
  208. package/dist/routes/config/http/envelope.d.ts +1 -2
  209. package/dist/routes/config/index.d.ts +5 -5
  210. package/dist/routes/config/index.js +7 -5
  211. package/dist/routes/config/index.js.map +1 -1
  212. package/dist/routes/config/services.d.ts +0 -1
  213. package/dist/routes/config/services.js +17 -19
  214. package/dist/routes/config/services.js.map +1 -1
  215. package/dist/routes/config/settings.d.ts +6 -15
  216. package/dist/routes/config/settings.js +16 -35
  217. package/dist/routes/config/settings.js.map +1 -1
  218. package/dist/routes/debug.d.ts +0 -1
  219. package/dist/routes/debug.js +1 -1
  220. package/dist/routes/debug.js.map +1 -1
  221. package/dist/routes/health.d.ts +16 -8
  222. package/dist/routes/health.js +27 -12
  223. package/dist/routes/health.js.map +1 -1
  224. package/dist/routes/hls.d.ts +0 -1
  225. package/dist/routes/icons.d.ts +0 -1
  226. package/dist/routes/index.d.ts +0 -1
  227. package/dist/routes/logs.d.ts +3 -2
  228. package/dist/routes/logs.js +54 -14
  229. package/dist/routes/logs.js.map +1 -1
  230. package/dist/routes/mpegts.d.ts +0 -1
  231. package/dist/routes/play.d.ts +0 -1
  232. package/dist/routes/playlist.d.ts +0 -1
  233. package/dist/routes/playlist.js +2 -1
  234. package/dist/routes/playlist.js.map +1 -1
  235. package/dist/routes/root/content.d.ts +0 -1
  236. package/dist/routes/root/content.js +32 -11
  237. package/dist/routes/root/content.js.map +1 -1
  238. package/dist/routes/root/index.d.ts +10 -1
  239. package/dist/routes/root/index.js +17 -7
  240. package/dist/routes/root/index.js.map +1 -1
  241. package/dist/routes/root/scripts/channels.d.ts +0 -1
  242. package/dist/routes/root/scripts/channels.js +10 -20
  243. package/dist/routes/root/scripts/channels.js.map +1 -1
  244. package/dist/routes/root/scripts/clientEscape.d.ts +0 -1
  245. package/dist/routes/root/scripts/clientEscape.js +1 -1
  246. package/dist/routes/root/scripts/clientUrl.d.ts +0 -1
  247. package/dist/routes/root/scripts/config.d.ts +0 -1
  248. package/dist/routes/root/scripts/config.js +8 -29
  249. package/dist/routes/root/scripts/config.js.map +1 -1
  250. package/dist/routes/root/scripts/index.d.ts +0 -1
  251. package/dist/routes/root/scripts/shared.d.ts +0 -1
  252. package/dist/routes/root/scripts/shared.js +16 -13
  253. package/dist/routes/root/scripts/shared.js.map +1 -1
  254. package/dist/routes/root/scripts/status.d.ts +0 -1
  255. package/dist/routes/root/scripts/status.handlers.d.ts +3 -1
  256. package/dist/routes/root/scripts/status.handlers.js +52 -26
  257. package/dist/routes/root/scripts/status.handlers.js.map +1 -1
  258. package/dist/routes/root/styles.d.ts +0 -1
  259. package/dist/routes/root/styles.js +10 -18
  260. package/dist/routes/root/styles.js.map +1 -1
  261. package/dist/routes/services.d.ts +0 -1
  262. package/dist/routes/services.js +1 -1
  263. package/dist/routes/services.js.map +1 -1
  264. package/dist/routes/sse.d.ts +3 -2
  265. package/dist/routes/sse.js +7 -3
  266. package/dist/routes/sse.js.map +1 -1
  267. package/dist/routes/streams.d.ts +4 -2
  268. package/dist/routes/streams.js +8 -5
  269. package/dist/routes/streams.js.map +1 -1
  270. package/dist/routes/theme.d.ts +0 -1
  271. package/dist/routes/theme.js +3 -3
  272. package/dist/routes/theme.js.map +1 -1
  273. package/dist/routes/ui.d.ts +0 -1
  274. package/dist/routes/ui.js +5 -5
  275. package/dist/routes/ui.js.map +1 -1
  276. package/dist/routes/upgrade.d.ts +0 -1
  277. package/dist/routes/upgrade.js +2 -1
  278. package/dist/routes/upgrade.js.map +1 -1
  279. package/dist/service/commands.context.d.ts +0 -1
  280. package/dist/service/commands.context.js +7 -1
  281. package/dist/service/commands.context.js.map +1 -1
  282. package/dist/service/commands.d.ts +0 -1
  283. package/dist/service/generators.context.d.ts +0 -1
  284. package/dist/service/generators.d.ts +0 -1
  285. package/dist/service/index.d.ts +0 -1
  286. package/dist/streaming/captureLock.d.ts +1 -2
  287. package/dist/streaming/captureLock.js +8 -7
  288. package/dist/streaming/captureLock.js.map +1 -1
  289. package/dist/streaming/captureSession.d.ts +0 -1
  290. package/dist/streaming/clients.d.ts +4 -3
  291. package/dist/streaming/clients.js +5 -4
  292. package/dist/streaming/clients.js.map +1 -1
  293. package/dist/streaming/codec.d.ts +0 -1
  294. package/dist/streaming/fmp4Segmenter.d.ts +11 -6
  295. package/dist/streaming/fmp4Segmenter.js +39 -17
  296. package/dist/streaming/fmp4Segmenter.js.map +1 -1
  297. package/dist/streaming/hls.d.ts +96 -3
  298. package/dist/streaming/hls.js +282 -171
  299. package/dist/streaming/hls.js.map +1 -1
  300. package/dist/streaming/hlsResume.d.ts +8 -5
  301. package/dist/streaming/hlsResume.js +10 -8
  302. package/dist/streaming/hlsResume.js.map +1 -1
  303. package/dist/streaming/hlsSegments.d.ts +11 -8
  304. package/dist/streaming/hlsSegments.js +38 -18
  305. package/dist/streaming/hlsSegments.js.map +1 -1
  306. package/dist/streaming/lifecycle.d.ts +5 -4
  307. package/dist/streaming/lifecycle.js +43 -13
  308. package/dist/streaming/lifecycle.js.map +1 -1
  309. package/dist/streaming/monitor.d.ts +14 -3
  310. package/dist/streaming/monitor.js +447 -234
  311. package/dist/streaming/monitor.js.map +1 -1
  312. package/dist/streaming/mp4Parser.d.ts +0 -1
  313. package/dist/streaming/mpegts.d.ts +11 -1
  314. package/dist/streaming/mpegts.js +92 -28
  315. package/dist/streaming/mpegts.js.map +1 -1
  316. package/dist/streaming/playlistBuilder.d.ts +0 -1
  317. package/dist/streaming/preroll.d.ts +34 -15
  318. package/dist/streaming/preroll.js +32 -30
  319. package/dist/streaming/preroll.js.map +1 -1
  320. package/dist/streaming/pretune.d.ts +2 -3
  321. package/dist/streaming/pretune.js +45 -45
  322. package/dist/streaming/pretune.js.map +1 -1
  323. package/dist/streaming/pretuneTimers.d.ts +16 -12
  324. package/dist/streaming/pretuneTimers.js +27 -37
  325. package/dist/streaming/pretuneTimers.js.map +1 -1
  326. package/dist/streaming/recovery.d.ts +97 -9
  327. package/dist/streaming/recovery.js +96 -18
  328. package/dist/streaming/recovery.js.map +1 -1
  329. package/dist/streaming/registry.d.ts +102 -15
  330. package/dist/streaming/registry.js +90 -5
  331. package/dist/streaming/registry.js.map +1 -1
  332. package/dist/streaming/setup.d.ts +90 -32
  333. package/dist/streaming/setup.js +379 -248
  334. package/dist/streaming/setup.js.map +1 -1
  335. package/dist/streaming/showInfo.d.ts +8 -4
  336. package/dist/streaming/showInfo.js +54 -45
  337. package/dist/streaming/showInfo.js.map +1 -1
  338. package/dist/streaming/statusEmitter.d.ts +5 -3
  339. package/dist/streaming/statusEmitter.js +20 -8
  340. package/dist/streaming/statusEmitter.js.map +1 -1
  341. package/dist/types/channels.d.ts +0 -1
  342. package/dist/types/channels.js +0 -4
  343. package/dist/types/channels.js.map +1 -1
  344. package/dist/types/config.d.ts +0 -1
  345. package/dist/types/index.d.ts +4 -4
  346. package/dist/types/index.js +2 -1
  347. package/dist/types/index.js.map +1 -1
  348. package/dist/types/profiles.d.ts +51 -9
  349. package/dist/types/profiles.js +35 -1
  350. package/dist/types/profiles.js.map +1 -1
  351. package/dist/types/selection.d.ts +10 -1
  352. package/dist/types/shared.d.ts +0 -1
  353. package/dist/types/streaming.d.ts +8 -1
  354. package/dist/types/streaming.js +7 -0
  355. package/dist/types/streaming.js.map +1 -1
  356. package/dist/upgrade/commands.context.d.ts +0 -1
  357. package/dist/upgrade/commands.d.ts +0 -1
  358. package/dist/upgrade/commands.js +1 -1
  359. package/dist/upgrade/commands.js.map +1 -1
  360. package/dist/upgrade/detection.context.d.ts +0 -1
  361. package/dist/upgrade/detection.d.ts +1 -2
  362. package/dist/upgrade/index.d.ts +0 -1
  363. package/dist/upgrade/lifecycle.context.d.ts +2 -1
  364. package/dist/upgrade/lifecycle.context.js +9 -4
  365. package/dist/upgrade/lifecycle.context.js.map +1 -1
  366. package/dist/upgrade/lifecycle.d.ts +0 -1
  367. package/dist/upgrade/pathHandle.d.ts +0 -1
  368. package/dist/utils/bootSession.context.d.ts +0 -1
  369. package/dist/utils/bootSession.context.js +3 -2
  370. package/dist/utils/bootSession.context.js.map +1 -1
  371. package/dist/utils/bootSession.d.ts +0 -1
  372. package/dist/utils/chromeFetch.d.ts +0 -1
  373. package/dist/utils/cliOutput.d.ts +0 -1
  374. package/dist/utils/debugFilter.d.ts +0 -1
  375. package/dist/utils/debugFilter.js +5 -3
  376. package/dist/utils/debugFilter.js.map +1 -1
  377. package/dist/utils/delay.d.ts +65 -13
  378. package/dist/utils/delay.js +96 -23
  379. package/dist/utils/delay.js.map +1 -1
  380. package/dist/utils/errors.d.ts +0 -11
  381. package/dist/utils/errors.js +3 -14
  382. package/dist/utils/errors.js.map +1 -1
  383. package/dist/utils/evaluate.d.ts +11 -3
  384. package/dist/utils/evaluate.js +4 -3
  385. package/dist/utils/evaluate.js.map +1 -1
  386. package/dist/utils/ffmpeg.context.d.ts +0 -1
  387. package/dist/utils/ffmpeg.d.ts +1 -1
  388. package/dist/utils/ffmpeg.js +2 -1
  389. package/dist/utils/ffmpeg.js.map +1 -1
  390. package/dist/utils/fileLogger.d.ts +26 -7
  391. package/dist/utils/fileLogger.js +241 -102
  392. package/dist/utils/fileLogger.js.map +1 -1
  393. package/dist/utils/format.d.ts +36 -4
  394. package/dist/utils/format.js +66 -12
  395. package/dist/utils/format.js.map +1 -1
  396. package/dist/utils/index.d.ts +1 -2
  397. package/dist/utils/index.js +1 -1
  398. package/dist/utils/index.js.map +1 -1
  399. package/dist/utils/logEmitter.d.ts +0 -1
  400. package/dist/utils/logger.d.ts +0 -1
  401. package/dist/utils/m3u.d.ts +0 -1
  402. package/dist/utils/markup.d.ts +0 -1
  403. package/dist/utils/memo.d.ts +0 -1
  404. package/dist/utils/morganStream.d.ts +2 -3
  405. package/dist/utils/morganStream.js +6 -8
  406. package/dist/utils/morganStream.js.map +1 -1
  407. package/dist/utils/network.d.ts +0 -1
  408. package/dist/utils/never.d.ts +8 -0
  409. package/dist/utils/never.js +20 -0
  410. package/dist/utils/never.js.map +1 -0
  411. package/dist/utils/pid.d.ts +0 -1
  412. package/dist/utils/platform.d.ts +0 -1
  413. package/dist/utils/processInspector.context.d.ts +32 -2
  414. package/dist/utils/processInspector.context.js +117 -1
  415. package/dist/utils/processInspector.context.js.map +1 -1
  416. package/dist/utils/processInspector.d.ts +0 -32
  417. package/dist/utils/processInspector.js +10 -117
  418. package/dist/utils/processInspector.js.map +1 -1
  419. package/dist/utils/retry.d.ts +5 -4
  420. package/dist/utils/retry.js +43 -33
  421. package/dist/utils/retry.js.map +1 -1
  422. package/dist/utils/runtimeIdentity.context.d.ts +0 -1
  423. package/dist/utils/runtimeIdentity.context.js +3 -1
  424. package/dist/utils/runtimeIdentity.context.js.map +1 -1
  425. package/dist/utils/runtimeIdentity.d.ts +1 -1
  426. package/dist/utils/runtimeIdentity.js +1 -1
  427. package/dist/utils/runtimeIdentity.js.map +1 -1
  428. package/dist/utils/sanitize.d.ts +8 -1
  429. package/dist/utils/sanitize.js +19 -0
  430. package/dist/utils/sanitize.js.map +1 -1
  431. package/dist/utils/streamContext.d.ts +0 -1
  432. package/dist/utils/timing.d.ts +3 -4
  433. package/dist/utils/timing.js +4 -4
  434. package/dist/utils/timing.js.map +1 -1
  435. package/dist/utils/version.d.ts +14 -8
  436. package/dist/utils/version.js +35 -24
  437. package/dist/utils/version.js.map +1 -1
  438. package/package.json +7 -7
  439. package/dist/app.d.ts.map +0 -1
  440. package/dist/browser/blockedPage.d.ts.map +0 -1
  441. package/dist/browser/browserSupervisor.d.ts.map +0 -1
  442. package/dist/browser/cdp.d.ts.map +0 -1
  443. package/dist/browser/channelSelection.d.ts.map +0 -1
  444. package/dist/browser/consent.d.ts.map +0 -1
  445. package/dist/browser/display.d.ts.map +0 -1
  446. package/dist/browser/hlsPlaylistObserver.d.ts.map +0 -1
  447. package/dist/browser/index.d.ts.map +0 -1
  448. package/dist/browser/launchGovernor.d.ts.map +0 -1
  449. package/dist/browser/login.d.ts.map +0 -1
  450. package/dist/browser/manifestInterceptor.d.ts.map +0 -1
  451. package/dist/browser/pageStaleness.d.ts.map +0 -1
  452. package/dist/browser/precaching.d.ts.map +0 -1
  453. package/dist/browser/tabNetworkObserver.d.ts.map +0 -1
  454. package/dist/browser/tuning/cache.d.ts.map +0 -1
  455. package/dist/browser/tuning/comcastPolymer.d.ts.map +0 -1
  456. package/dist/browser/tuning/cox.d.ts.map +0 -1
  457. package/dist/browser/tuning/directv.d.ts.map +0 -1
  458. package/dist/browser/tuning/fox.d.ts.map +0 -1
  459. package/dist/browser/tuning/gridSearch.d.ts.map +0 -1
  460. package/dist/browser/tuning/hbo.d.ts.map +0 -1
  461. package/dist/browser/tuning/hulu.d.ts.map +0 -1
  462. package/dist/browser/tuning/shared.d.ts.map +0 -1
  463. package/dist/browser/tuning/sling.d.ts.map +0 -1
  464. package/dist/browser/tuning/spectrum.d.ts.map +0 -1
  465. package/dist/browser/tuning/thumbnailRow.d.ts.map +0 -1
  466. package/dist/browser/tuning/tileClick.d.ts.map +0 -1
  467. package/dist/browser/tuning/xfinity.d.ts.map +0 -1
  468. package/dist/browser/tuning/youtubeTv.d.ts.map +0 -1
  469. package/dist/browser/video.d.ts.map +0 -1
  470. package/dist/channels/index.d.ts.map +0 -1
  471. package/dist/config/channelForm.d.ts.map +0 -1
  472. package/dist/config/consistencyProbe.d.ts.map +0 -1
  473. package/dist/config/health.d.ts.map +0 -1
  474. package/dist/config/index.d.ts.map +0 -1
  475. package/dist/config/paths.d.ts.map +0 -1
  476. package/dist/config/persistence.context.d.ts.map +0 -1
  477. package/dist/config/persistence.d.ts.map +0 -1
  478. package/dist/config/presets.d.ts.map +0 -1
  479. package/dist/config/profiles.d.ts.map +0 -1
  480. package/dist/config/providerLineups.d.ts.map +0 -1
  481. package/dist/config/reactivity.d.ts.map +0 -1
  482. package/dist/config/servicePacks.d.ts.map +0 -1
  483. package/dist/config/services.d.ts.map +0 -1
  484. package/dist/config/sites.d.ts.map +0 -1
  485. package/dist/config/userChannels.d.ts.map +0 -1
  486. package/dist/config/userConfig.d.ts.map +0 -1
  487. package/dist/config/userProfiles.d.ts.map +0 -1
  488. package/dist/hdhr/channelMap.d.ts.map +0 -1
  489. package/dist/hdhr/deviceId.d.ts.map +0 -1
  490. package/dist/hdhr/discover.d.ts.map +0 -1
  491. package/dist/hdhr/getHandlers.d.ts.map +0 -1
  492. package/dist/hdhr/identity.d.ts.map +0 -1
  493. package/dist/hdhr/index.d.ts.map +0 -1
  494. package/dist/hdhr/protocol.d.ts.map +0 -1
  495. package/dist/hdhr/tunerState.d.ts.map +0 -1
  496. package/dist/hdhr/udp.d.ts.map +0 -1
  497. package/dist/identity.d.ts.map +0 -1
  498. package/dist/index.d.ts.map +0 -1
  499. package/dist/native/codecInference.d.ts.map +0 -1
  500. package/dist/native/decrypt.d.ts.map +0 -1
  501. package/dist/native/index.d.ts.map +0 -1
  502. package/dist/native/probe.d.ts.map +0 -1
  503. package/dist/native/proxy.d.ts.map +0 -1
  504. package/dist/native/tokenExpiry.d.ts.map +0 -1
  505. package/dist/routes/assets.d.ts.map +0 -1
  506. package/dist/routes/auth.d.ts.map +0 -1
  507. package/dist/routes/cdp.d.ts.map +0 -1
  508. package/dist/routes/channels.d.ts.map +0 -1
  509. package/dist/routes/clientActions.d.ts.map +0 -1
  510. package/dist/routes/components.d.ts.map +0 -1
  511. package/dist/routes/config/channels/endpoints/browse.d.ts.map +0 -1
  512. package/dist/routes/config/channels/endpoints/bulk.d.ts.map +0 -1
  513. package/dist/routes/config/channels/endpoints/crud.d.ts.map +0 -1
  514. package/dist/routes/config/channels/endpoints/importExport.d.ts.map +0 -1
  515. package/dist/routes/config/channels/endpoints/predefined.d.ts.map +0 -1
  516. package/dist/routes/config/channels/endpoints/prefs.d.ts.map +0 -1
  517. package/dist/routes/config/channels/endpoints/service.d.ts.map +0 -1
  518. package/dist/routes/config/channels/endpoints/tags.d.ts.map +0 -1
  519. package/dist/routes/config/channels/healthBridge.d.ts.map +0 -1
  520. package/dist/routes/config/channels/http/handler.d.ts.map +0 -1
  521. package/dist/routes/config/channels/http/playlistHint.d.ts.map +0 -1
  522. package/dist/routes/config/channels/http/serviceWarning.d.ts.map +0 -1
  523. package/dist/routes/config/channels/index.d.ts.map +0 -1
  524. package/dist/routes/config/channels/setup.d.ts.map +0 -1
  525. package/dist/routes/config/channels/table.d.ts.map +0 -1
  526. package/dist/routes/config/http/envelope.d.ts.map +0 -1
  527. package/dist/routes/config/index.d.ts.map +0 -1
  528. package/dist/routes/config/services.d.ts.map +0 -1
  529. package/dist/routes/config/settings.d.ts.map +0 -1
  530. package/dist/routes/debug.d.ts.map +0 -1
  531. package/dist/routes/health.d.ts.map +0 -1
  532. package/dist/routes/hls.d.ts.map +0 -1
  533. package/dist/routes/icons.d.ts.map +0 -1
  534. package/dist/routes/index.d.ts.map +0 -1
  535. package/dist/routes/logs.d.ts.map +0 -1
  536. package/dist/routes/mpegts.d.ts.map +0 -1
  537. package/dist/routes/play.d.ts.map +0 -1
  538. package/dist/routes/playlist.d.ts.map +0 -1
  539. package/dist/routes/root/content.d.ts.map +0 -1
  540. package/dist/routes/root/index.d.ts.map +0 -1
  541. package/dist/routes/root/scripts/channels.d.ts.map +0 -1
  542. package/dist/routes/root/scripts/clientEscape.d.ts.map +0 -1
  543. package/dist/routes/root/scripts/clientUrl.d.ts.map +0 -1
  544. package/dist/routes/root/scripts/config.d.ts.map +0 -1
  545. package/dist/routes/root/scripts/index.d.ts.map +0 -1
  546. package/dist/routes/root/scripts/shared.d.ts.map +0 -1
  547. package/dist/routes/root/scripts/status.d.ts.map +0 -1
  548. package/dist/routes/root/scripts/status.handlers.d.ts.map +0 -1
  549. package/dist/routes/root/styles.d.ts.map +0 -1
  550. package/dist/routes/services.d.ts.map +0 -1
  551. package/dist/routes/sse.d.ts.map +0 -1
  552. package/dist/routes/streams.d.ts.map +0 -1
  553. package/dist/routes/theme.d.ts.map +0 -1
  554. package/dist/routes/ui.d.ts.map +0 -1
  555. package/dist/routes/upgrade.d.ts.map +0 -1
  556. package/dist/service/commands.context.d.ts.map +0 -1
  557. package/dist/service/commands.d.ts.map +0 -1
  558. package/dist/service/generators.context.d.ts.map +0 -1
  559. package/dist/service/generators.d.ts.map +0 -1
  560. package/dist/service/index.d.ts.map +0 -1
  561. package/dist/streaming/captureLock.d.ts.map +0 -1
  562. package/dist/streaming/captureSession.d.ts.map +0 -1
  563. package/dist/streaming/clients.d.ts.map +0 -1
  564. package/dist/streaming/codec.d.ts.map +0 -1
  565. package/dist/streaming/fmp4Segmenter.d.ts.map +0 -1
  566. package/dist/streaming/hls.d.ts.map +0 -1
  567. package/dist/streaming/hlsResume.d.ts.map +0 -1
  568. package/dist/streaming/hlsSegments.d.ts.map +0 -1
  569. package/dist/streaming/lifecycle.d.ts.map +0 -1
  570. package/dist/streaming/monitor.d.ts.map +0 -1
  571. package/dist/streaming/mp4Parser.d.ts.map +0 -1
  572. package/dist/streaming/mpegts.d.ts.map +0 -1
  573. package/dist/streaming/playlistBuilder.d.ts.map +0 -1
  574. package/dist/streaming/preroll.d.ts.map +0 -1
  575. package/dist/streaming/pretune.d.ts.map +0 -1
  576. package/dist/streaming/pretuneTimers.d.ts.map +0 -1
  577. package/dist/streaming/recovery.d.ts.map +0 -1
  578. package/dist/streaming/registry.d.ts.map +0 -1
  579. package/dist/streaming/setup.d.ts.map +0 -1
  580. package/dist/streaming/showInfo.d.ts.map +0 -1
  581. package/dist/streaming/statusEmitter.d.ts.map +0 -1
  582. package/dist/types/channels.d.ts.map +0 -1
  583. package/dist/types/config.d.ts.map +0 -1
  584. package/dist/types/index.d.ts.map +0 -1
  585. package/dist/types/profiles.d.ts.map +0 -1
  586. package/dist/types/selection.d.ts.map +0 -1
  587. package/dist/types/shared.d.ts.map +0 -1
  588. package/dist/types/streaming.d.ts.map +0 -1
  589. package/dist/upgrade/commands.context.d.ts.map +0 -1
  590. package/dist/upgrade/commands.d.ts.map +0 -1
  591. package/dist/upgrade/detection.context.d.ts.map +0 -1
  592. package/dist/upgrade/detection.d.ts.map +0 -1
  593. package/dist/upgrade/index.d.ts.map +0 -1
  594. package/dist/upgrade/lifecycle.context.d.ts.map +0 -1
  595. package/dist/upgrade/lifecycle.d.ts.map +0 -1
  596. package/dist/upgrade/pathHandle.d.ts.map +0 -1
  597. package/dist/utils/bootSession.context.d.ts.map +0 -1
  598. package/dist/utils/bootSession.d.ts.map +0 -1
  599. package/dist/utils/chromeFetch.d.ts.map +0 -1
  600. package/dist/utils/cliOutput.d.ts.map +0 -1
  601. package/dist/utils/clock.d.ts +0 -15
  602. package/dist/utils/clock.d.ts.map +0 -1
  603. package/dist/utils/clock.js +0 -31
  604. package/dist/utils/clock.js.map +0 -1
  605. package/dist/utils/debugFilter.d.ts.map +0 -1
  606. package/dist/utils/delay.d.ts.map +0 -1
  607. package/dist/utils/errors.d.ts.map +0 -1
  608. package/dist/utils/evaluate.d.ts.map +0 -1
  609. package/dist/utils/ffmpeg.context.d.ts.map +0 -1
  610. package/dist/utils/ffmpeg.d.ts.map +0 -1
  611. package/dist/utils/fileLogger.d.ts.map +0 -1
  612. package/dist/utils/format.d.ts.map +0 -1
  613. package/dist/utils/index.d.ts.map +0 -1
  614. package/dist/utils/logEmitter.d.ts.map +0 -1
  615. package/dist/utils/logger.d.ts.map +0 -1
  616. package/dist/utils/m3u.d.ts.map +0 -1
  617. package/dist/utils/markup.d.ts.map +0 -1
  618. package/dist/utils/memo.d.ts.map +0 -1
  619. package/dist/utils/morganStream.d.ts.map +0 -1
  620. package/dist/utils/network.d.ts.map +0 -1
  621. package/dist/utils/pid.d.ts.map +0 -1
  622. package/dist/utils/platform.d.ts.map +0 -1
  623. package/dist/utils/processInspector.context.d.ts.map +0 -1
  624. package/dist/utils/processInspector.d.ts.map +0 -1
  625. package/dist/utils/retry.d.ts.map +0 -1
  626. package/dist/utils/runtimeIdentity.context.d.ts.map +0 -1
  627. package/dist/utils/runtimeIdentity.d.ts.map +0 -1
  628. package/dist/utils/sanitize.d.ts.map +0 -1
  629. package/dist/utils/streamContext.d.ts.map +0 -1
  630. package/dist/utils/timing.d.ts.map +0 -1
  631. package/dist/utils/version.d.ts.map +0 -1
@@ -0,0 +1,97 @@
1
+ import { getExtensionPage, wss } from "puppeteer-stream";
2
+ import type { Clock } from "homebridge-plugin-utils";
3
+ import type { Page } from "puppeteer-core";
4
+ import type { Readable } from "node:stream";
5
+ import { withTabSelected } from "./tabSelection.ts";
6
+ export declare const EXTENSION_READY_EXPRESSION = "typeof START_RECORDING === 'function'";
7
+ export declare const ACTIVE_TAB_GRANT_PENDING_MESSAGE = "has not been invoked for the current page";
8
+ export declare const EXTENSION_NOT_READY_MESSAGE = "The capture extension is not ready on this browser.";
9
+ export declare const ACTIVE_TAB_GRANT_POLL_MS = 50;
10
+ export declare const ACTIVE_TAB_GRANT_CEILING_MS = 1000;
11
+ export declare const CAPTURE_FRAME_SIZE_MS = 20;
12
+ export declare const CAPTURE_STREAM_HIGH_WATER_MARK: number;
13
+ /**
14
+ * The dimension and frame-rate bounds a capture track is held to. Chrome reads these as tabCapture's mandatory media constraints, which is what holds the encoder
15
+ * to the surface the page was emulated at rather than to whatever the window happens to be showing.
16
+ */
17
+ export interface CaptureVideoConstraints {
18
+ readonly mandatory: {
19
+ readonly maxFrameRate: number;
20
+ readonly maxHeight: number;
21
+ readonly maxWidth: number;
22
+ readonly minFrameRate: number;
23
+ readonly minHeight: number;
24
+ readonly minWidth: number;
25
+ };
26
+ }
27
+ /**
28
+ * What a caller asks a capture for. videoConstraints is required rather than optional because every caller supplies one and it is the only thing tying the
29
+ * encoder to the emulated surface; a capture acquired without it would silently compose whatever the window was presenting.
30
+ */
31
+ export interface CaptureStreamOptions {
32
+ readonly audio: boolean;
33
+ readonly audioBitsPerSecond?: number;
34
+ readonly mimeType: string;
35
+ readonly video: boolean;
36
+ readonly videoBitsPerSecond?: number;
37
+ readonly videoConstraints: CaptureVideoConstraints;
38
+ }
39
+ /**
40
+ * The settings object the extension's START_RECORDING receives, mirroring the RecordingOptions type in the extension's own source field for field.
41
+ *
42
+ * One divergence is deliberate. The extension annotates audioBitsPerSecond, videoBitsPerSecond, and bitsPerSecond as required numbers, but it hands all three
43
+ * straight to MediaRecorder, where an absent value selects the recorder's own default - and the readiness probe passes none of them and captures perfectly well.
44
+ * So this type declares what the protocol tolerates rather than what the extension's annotation over-claims, and the settings-shape test asserts the field NAMES
45
+ * against the extension's source so a genuine protocol change still fails loudly.
46
+ */
47
+ export interface ExtensionRecordingSettings {
48
+ audio: boolean;
49
+ audioBitsPerSecond?: number;
50
+ audioConstraints?: CaptureVideoConstraints;
51
+ bitsPerSecond?: number;
52
+ delay?: number;
53
+ frameSize: number;
54
+ index: number;
55
+ mimeType: string;
56
+ tabId: number;
57
+ video: boolean;
58
+ videoBitsPerSecond?: number;
59
+ videoConstraints?: CaptureVideoConstraints;
60
+ }
61
+ /**
62
+ * A live capture: the readable stream of recorder chunks, plus the two members that let an owner end it and know when the ending is complete.
63
+ */
64
+ export interface CaptureStream extends Readable {
65
+ stop(): Promise<void>;
66
+ readonly stopped: Promise<void>;
67
+ }
68
+ /**
69
+ * The collaborators this module talks through, injected so a test can drive the whole acquisition without a browser or a listening socket: the two library values
70
+ * and the tab-selection primitive whose hold the acquisition runs inside.
71
+ */
72
+ export interface TabCaptureDeps {
73
+ readonly getExtensionPage: typeof getExtensionPage;
74
+ readonly withTabSelected: typeof withTabSelected;
75
+ readonly wss: typeof wss;
76
+ }
77
+ /**
78
+ * Per-call context for an acquisition: the clock its waits run on and the collaborators it talks through.
79
+ */
80
+ export interface AcquireCaptureStreamContext {
81
+ readonly clock?: Clock;
82
+ readonly deps?: TabCaptureDeps;
83
+ }
84
+ export declare const defaultTabCaptureDeps: TabCaptureDeps;
85
+ /**
86
+ * Acquires a tab capture for a page: one started recording, its chunks arriving as a readable stream, and the two controls that end it.
87
+ *
88
+ * Exactly one start is made. A start Chrome refuses with "Could not start video source" is logged once with the window's reported state and the selected tab, so
89
+ * the refusal explains itself, and then fails the acquisition unchanged; whether that refusal is the browser's fault and what should follow are the
90
+ * establishment's to decide from its capture probe. Every other rejection fails the acquisition the same way, with no log of its own.
91
+ * @param page - The page to capture.
92
+ * @param options - What the capture is asked for.
93
+ * @param context - The clock and collaborators. Defaults to the production collaborators on the real clock.
94
+ * @returns The started capture.
95
+ * @throws When the extension is not ready, its tab cannot be selected, or the start fails.
96
+ */
97
+ export declare function acquireCaptureStream(page: Page, options: CaptureStreamOptions, context?: AcquireCaptureStreamContext): Promise<CaptureStream>;
@@ -0,0 +1,314 @@
1
+ /* Copyright(C) 2024-2026, HJD (https://github.com/hjdhjd). All rights reserved.
2
+ *
3
+ * tabCapture.ts: PrismCast's own conversation with the capture extension.
4
+ *
5
+ * Starting a tab capture is four steps against the browser: select the page's tab through the capture extension and hold it, send the keyboard command that grants
6
+ * the extension its activeTab permission for that tab, hand the extension a settings object it turns into a MediaRecorder feeding a WebSocket, and give the tab
7
+ * that was selected before back. Every piece those steps need - the extension's options page, the WebSocket server, the browser launch - is exported by
8
+ * puppeteer-stream, so PrismCast speaks the protocol itself rather than through a convenience wrapper, and three things follow from that.
9
+ *
10
+ * There is one capture lock in this process, and streaming/setup.ts owns it. A wrapper that carries a lock of its own would serialize the same work twice, and a
11
+ * rejection escaping such a lock's unguarded section leaves it held for the life of the process - a condition no Chrome restart can clear, because the state is
12
+ * in Node rather than in the browser. Owning the start means the only serialization is the one whose deadline, abort signal, and wedge policy the caller already
13
+ * controls.
14
+ *
15
+ * A rejected start is reported rather than judged. Chrome answers a start it cannot serve with "Could not start video source", and the whole response here is one
16
+ * warning carrying the window and selected-tab state that explains it, read while that tab is still selected, with the rejection travelling to the caller
17
+ * unchanged. What such a refusal says about the browser is the establishment's question, settled by its capture probe, so this layer holds no retry policy of its
18
+ * own. The activeTab grant is the one wait that does belong here: rather than sleeping a fixed interval after the keyboard command and hoping the grant landed,
19
+ * the start is attempted and Chrome's own "has not been invoked for the current page" answer drives a short poll, so a grant that lands immediately costs nothing.
20
+ *
21
+ * The coupling this module takes on is the extension's protocol, and it is asserted rather than trusted: tabCapture.test.ts fingerprints the three library files
22
+ * this module was written against and derives the settings-object shape from the extension's own source, so a dependency bump that changes either fails the
23
+ * suite with instructions rather than failing a capture in the field.
24
+ */
25
+ import { LOG, formatError, pollUntil, startTimer } from "../utils/index.js";
26
+ import { getExtensionPage, wss } from "puppeteer-stream";
27
+ import { CAPTURE_SOURCE_UNAVAILABLE_MESSAGE } from "../types/index.js";
28
+ import { PassThrough } from "node:stream";
29
+ import { readWindowState } from "./cdp.js";
30
+ import { systemClock } from "homebridge-plugin-utils";
31
+ import { withTabSelected } from "./tabSelection.js";
32
+ // Constants.
33
+ // The extension's readiness predicate, stated once. The launch gate waits on it before publishing a browser, and the acquisition asserts it before preparing an
34
+ // attempt, so both ask the same question of the same page.
35
+ export const EXTENSION_READY_EXPRESSION = "typeof START_RECORDING === 'function'";
36
+ // Chrome's rejection text when the extension's activeTab grant has not landed for the page yet. The keyboard command that grants it is asynchronous, so this
37
+ // answer means "ask again shortly" rather than "this cannot work".
38
+ export const ACTIVE_TAB_GRANT_PENDING_MESSAGE = "has not been invoked for the current page";
39
+ // The failure when a browser is serving without a loaded capture extension. The launch gate establishes readiness before a browser is published, so reaching
40
+ // this means the extension went away underneath a published browser.
41
+ export const EXTENSION_NOT_READY_MESSAGE = "The capture extension is not ready on this browser.";
42
+ // The cadence between start attempts while Chrome is still reporting the activeTab grant pending, and the ceiling on that wait. A grant that lands with the
43
+ // keyboard command costs one attempt and no wait at all; the ceiling bounds the case where it never lands, so the caller sees Chrome's own message rather than
44
+ // a hang. One attempt is a handful of CDP round trips - the selection re-assert, the five key events, the start - taken inside a selection held across the whole
45
+ // poll, so the ceiling is sized to afford several of them rather than to a multiple of the cadence alone.
46
+ export const ACTIVE_TAB_GRANT_POLL_MS = 50;
47
+ export const ACTIVE_TAB_GRANT_CEILING_MS = 1000;
48
+ // The recorder's timeslice in milliseconds - how often the extension's MediaRecorder hands a chunk to its socket. A browser-side recorder setting rather than a
49
+ // wait of ours, at the value the capture pipeline was tuned against.
50
+ export const CAPTURE_FRAME_SIZE_MS = 20;
51
+ // The capture stream's buffer ceiling. Chrome delivers bursty multi-megabyte chunks on keyframes, so the buffer is sized to absorb a burst without the socket's
52
+ // writes backing up into the recorder.
53
+ export const CAPTURE_STREAM_HIGH_WATER_MARK = 8 * 1024 * 1024;
54
+ /**
55
+ * A start Chrome refused, carrying the state that explains the refusal. The state is read while the capture's tab is still selected, which is the only moment it
56
+ * describes the conditions the start actually ran under. Chrome's own refusal text is the message, so the capture-infrastructure classifier and the
57
+ * establishment's refusal test both keep matching on it.
58
+ *
59
+ * Module-private on purpose: the judgment "this is a capture-infrastructure failure" belongs to one mechanism, the pattern list in streaming/recovery.ts, which
60
+ * reads the message. This class is the internal typed carrier for the diagnostics that travel alongside it, not a second way to ask the same question.
61
+ */
62
+ class CaptureStartRefusedError extends Error {
63
+ diagnostics;
64
+ constructor(message, diagnostics) {
65
+ super(message);
66
+ this.diagnostics = diagnostics;
67
+ this.name = "CaptureStartRefusedError";
68
+ }
69
+ }
70
+ // The production collaborators.
71
+ export const defaultTabCaptureDeps = { getExtensionPage, withTabSelected, wss };
72
+ // The socket index each capture publishes under. It only ever moves forward, so no two captures in this process - including two attempts of the same
73
+ // acquisition - can be confused for one another on the shared server.
74
+ let nextCaptureIndex = 0;
75
+ // Acquisition.
76
+ /**
77
+ * Normalizes anything thrown into an Error. Puppeteer delivers a page-side exception that is not an Error object as the primitive itself, and the extension
78
+ * rejects its capture-start with a bare string, so a rethrow that assumed an Error would strip the only diagnostic there was.
79
+ * @param error - The thrown value.
80
+ * @returns The value itself when it is already an Error, otherwise an Error carrying its formatted text.
81
+ */
82
+ function toError(error) {
83
+ return (error instanceof Error) ? error : new Error(formatError(error));
84
+ }
85
+ /**
86
+ * Prepares one start attempt: a fresh socket index, a fresh stream, and a connection handler registered on the server BEFORE the extension is invoked. The
87
+ * ordering is required, not tidy - START_RECORDING opens its socket before it asks Chrome for the capture, so a handler registered afterwards would miss the
88
+ * connection, and a start that goes on to fail still connects a socket for its index.
89
+ * @param server - The WebSocket server the extension connects back to.
90
+ * @returns The prepared attempt.
91
+ */
92
+ function prepareAttempt(server) {
93
+ const index = nextCaptureIndex++;
94
+ const stream = new PassThrough({ highWaterMark: CAPTURE_STREAM_HIGH_WATER_MARK });
95
+ // eslint-disable-next-line @typescript-eslint/no-invalid-void-type -- Standard pattern for signal promises.
96
+ const stopped = Promise.withResolvers();
97
+ const attempt = {
98
+ index,
99
+ onConnection: (socket, request) => {
100
+ // The extension names the capture it is connecting for in the query string. Any other index belongs to another capture's handler.
101
+ if (new URL(request.url ?? "/", "http://localhost").searchParams.get("index") !== String(index)) {
102
+ return;
103
+ }
104
+ attempt.socket = socket;
105
+ socket.on("message", (data) => {
106
+ if (!stream.destroyed && !stream.writableEnded) {
107
+ stream.write(data);
108
+ }
109
+ });
110
+ socket.on("close", () => {
111
+ if (!stream.destroyed && !stream.writableEnded) {
112
+ stream.end();
113
+ }
114
+ // The extension closes its socket only after the recorder stopped and its pending sends drained, so this close is the completion signal an owner waits
115
+ // on before closing the page out from under it.
116
+ stopped.resolve();
117
+ server.off("connection", attempt.onConnection);
118
+ });
119
+ },
120
+ socket: null,
121
+ stopped,
122
+ stream
123
+ };
124
+ server.on("connection", attempt.onConnection);
125
+ return attempt;
126
+ }
127
+ /**
128
+ * Discards an attempt that did not start: its listener comes off the server, its socket is closed if the extension managed to open one, its stream is destroyed,
129
+ * and its completion signal settles. Nothing of a failed attempt outlives this call, which is what lets the next attempt begin from a clean server.
130
+ * @param server - The WebSocket server the attempt registered on.
131
+ * @param attempt - The attempt to discard.
132
+ */
133
+ function discardAttempt(server, attempt) {
134
+ server.off("connection", attempt.onConnection);
135
+ attempt.socket?.close();
136
+ attempt.stream.destroy();
137
+ attempt.stopped.resolve();
138
+ }
139
+ /**
140
+ * Sends the keyboard command the extension's manifest binds, which is the extension's documented way of being invoked and grants it activeTab permission for the
141
+ * selected tab. On current Chrome the allowlist flag the launch passes already grants what this grants - a capture with no command ever sent succeeded, measured
142
+ * 2026-08-30 - so this is kept as the documented path rather than as the thing that makes capture work, and it is only ever aimed at the tab the hold selected.
143
+ * @param page - The page the capture is being acquired for.
144
+ */
145
+ async function grantActiveTab(page) {
146
+ const modifier = (process.platform === "darwin") ? "Meta" : "Control";
147
+ await page.keyboard.down(modifier);
148
+ await page.keyboard.down("Shift");
149
+ await page.keyboard.press("KeyY");
150
+ await page.keyboard.up("Shift");
151
+ await page.keyboard.up(modifier);
152
+ }
153
+ /**
154
+ * Runs one START_RECORDING evaluate against the extension for a prepared attempt.
155
+ * @param extension - The extension's options page.
156
+ * @param attempt - The prepared attempt whose index and stream the recording feeds.
157
+ * @param options - What the caller asked the capture for.
158
+ * @param tabId - The tab Chrome will capture.
159
+ */
160
+ async function startRecording(extension, attempt, options, tabId) {
161
+ const settings = {
162
+ audio: options.audio,
163
+ audioBitsPerSecond: options.audioBitsPerSecond,
164
+ frameSize: CAPTURE_FRAME_SIZE_MS,
165
+ index: attempt.index,
166
+ mimeType: options.mimeType,
167
+ tabId,
168
+ video: options.video,
169
+ videoBitsPerSecond: options.videoBitsPerSecond,
170
+ videoConstraints: options.videoConstraints
171
+ };
172
+ await extension.evaluate((recording) => START_RECORDING(recording), settings);
173
+ }
174
+ /**
175
+ * Attempts one start, waiting out an activeTab grant that has not landed yet. The keyboard command that grants the permission is asynchronous, so rather than
176
+ * sleeping a fixed interval and hoping, this attempts the start and reads Chrome's own answer: "has not been invoked for the current page" means ask again on
177
+ * the cadence, anything else is this attempt's verdict. A grant already in place costs exactly one attempt and no wait.
178
+ *
179
+ * The whole poll runs inside ONE tab selection. Chrome records whichever tab is selected, so the selection has to hold across every attempt, and taking it once
180
+ * means the user's tab is handed back once rather than flickering per attempt. Each attempt re-asserts the selection before it acts, so a login page opening or a
181
+ * user's click between attempts is corrected rather than recorded.
182
+ *
183
+ * Each poll iteration prepares a wholly fresh attempt and discards it before the next, so no listener, socket, or index is ever reused across a refusal.
184
+ * @param page - The page to capture.
185
+ * @param options - What the caller asked the capture for.
186
+ * @param collaborators - The extension page, the socket server, the clock the cadence runs on, and the deps the selection is taken through.
187
+ * @param collaborators.clock - The clock driving the grant cadence.
188
+ * @param collaborators.deps - The injected collaborators, read for the tab-selection primitive.
189
+ * @param collaborators.extension - The extension's options page.
190
+ * @param collaborators.server - The WebSocket server the extension connects back to.
191
+ * @returns The attempt that started.
192
+ * @throws The last grant-pending rejection when the ceiling lapses, or the attempt's own rejection for any other failure.
193
+ */
194
+ async function acquireOnce(page, options, collaborators) {
195
+ const { clock, deps, extension, server } = collaborators;
196
+ return deps.withTabSelected(page, async (selected) => {
197
+ const runAttempt = async () => {
198
+ const attempt = prepareAttempt(server);
199
+ try {
200
+ await selected.reassert();
201
+ await grantActiveTab(page);
202
+ await startRecording(extension, attempt, options, selected.id);
203
+ return { attempt, kind: "started" };
204
+ }
205
+ catch (error) {
206
+ discardAttempt(server, attempt);
207
+ if (formatError(error).includes(ACTIVE_TAB_GRANT_PENDING_MESSAGE)) {
208
+ return { error, kind: "grant-pending" };
209
+ }
210
+ /* Every other rejection is this attempt's verdict, and the window state that explains it is only truthful while the capture's tab is still selected -
211
+ * which is here, inside the hold, rather than after it has been handed back. The read is best-effort by construction, so a diagnostic can never replace
212
+ * the failure it describes.
213
+ */
214
+ const windowState = await readWindowState(page);
215
+ throw new CaptureStartRefusedError(formatError(error), { activeTab: selected.url, windowState });
216
+ }
217
+ };
218
+ const outcome = await pollUntil({ cadenceMs: ACTIVE_TAB_GRANT_POLL_MS, ceilingMs: ACTIVE_TAB_GRANT_CEILING_MS, clock, read: runAttempt,
219
+ until: (result) => result.kind === "started" });
220
+ if (outcome.value.kind === "grant-pending") {
221
+ throw toError(outcome.value.error);
222
+ }
223
+ return outcome.value.attempt;
224
+ });
225
+ }
226
+ /**
227
+ * Attaches the two capture-control members to a started attempt's stream, producing the CaptureStream its owner holds.
228
+ * @param attempt - The attempt that started.
229
+ * @param extension - The extension's options page, which STOP_RECORDING is evaluated against.
230
+ * @param server - The WebSocket server the attempt registered on.
231
+ * @returns The owner-facing capture stream.
232
+ */
233
+ function attachCaptureControls(attempt, extension, server) {
234
+ let stopping = false;
235
+ const requestStop = async () => {
236
+ // The stop request has to reach a browser that is still listening. When it is already gone the recording is gone with it, so this is the one path where
237
+ // asking is pointless rather than merely best-effort.
238
+ if (!extension.isClosed() && extension.browser().connected) {
239
+ try {
240
+ await extension.evaluate((index) => STOP_RECORDING(index), attempt.index);
241
+ }
242
+ catch (error) {
243
+ LOG.debug("browser:lifecycle", "The capture extension did not accept the stop request: %s.", formatError(error));
244
+ }
245
+ }
246
+ server.off("connection", attempt.onConnection);
247
+ // A capture whose socket never connected has no close event coming, so its completion signal settles here rather than waiting for one that cannot arrive.
248
+ if (!attempt.socket) {
249
+ attempt.stopped.resolve();
250
+ }
251
+ };
252
+ /* stop() is deliberately not async: every call has to hand back the SAME promise object, because the completion an owner waits on is the capture's, not this
253
+ * call's. The request itself goes out once, guarded by the flag, and its own failures are swallowed inside requestStop so this promise never rejects.
254
+ */
255
+ const stop = () => {
256
+ if (!stopping) {
257
+ stopping = true;
258
+ void requestStop();
259
+ }
260
+ return attempt.stopped.promise;
261
+ };
262
+ return Object.assign(attempt.stream, { stop, stopped: attempt.stopped.promise });
263
+ }
264
+ /**
265
+ * Acquires a tab capture for a page: one started recording, its chunks arriving as a readable stream, and the two controls that end it.
266
+ *
267
+ * Exactly one start is made. A start Chrome refuses with "Could not start video source" is logged once with the window's reported state and the selected tab, so
268
+ * the refusal explains itself, and then fails the acquisition unchanged; whether that refusal is the browser's fault and what should follow are the
269
+ * establishment's to decide from its capture probe. Every other rejection fails the acquisition the same way, with no log of its own.
270
+ * @param page - The page to capture.
271
+ * @param options - What the capture is asked for.
272
+ * @param context - The clock and collaborators. Defaults to the production collaborators on the real clock.
273
+ * @returns The started capture.
274
+ * @throws When the extension is not ready, its tab cannot be selected, or the start fails.
275
+ */
276
+ export async function acquireCaptureStream(page, options, context = {}) {
277
+ const { clock = systemClock, deps = defaultTabCaptureDeps } = context;
278
+ const acquisitionElapsed = startTimer(clock);
279
+ const extension = await deps.getExtensionPage(page.browser());
280
+ const server = await deps.wss;
281
+ /* The launch gate already established the extension's readiness before this browser was published, so this asks once rather than retrying: reaching it means
282
+ * the extension went away underneath a published browser, which is a fault to report rather than a condition to wait out. It reads the same statement of the
283
+ * predicate the gate waits on.
284
+ */
285
+ const ready = await extension.evaluate(EXTENSION_READY_EXPRESSION);
286
+ if (ready !== true) {
287
+ throw new Error(EXTENSION_NOT_READY_MESSAGE);
288
+ }
289
+ try {
290
+ const started = await acquireOnce(page, options, { clock, deps, extension, server });
291
+ const stream = attachCaptureControls(started, extension, server);
292
+ /* Both close paths end the recording. The owner's disposer destroys the stream, which emits close; a page that dies takes its capture with it and fires
293
+ * the page's own close. Registering here rather than inside the socket handler means a capture whose socket never connected still stops cleanly.
294
+ */
295
+ page.once("close", () => { void stream.stop(); });
296
+ stream.once("close", () => { void stream.stop(); });
297
+ LOG.debug("timing:startup", "Capture acquired in %dms.", acquisitionElapsed());
298
+ return stream;
299
+ }
300
+ catch (error) {
301
+ /* Chrome's refusal earns a line of its own, because the state it was read under is recoverable nowhere else: the window's reported state and the tab the
302
+ * start was aimed at were gathered inside the hold, while that tab was still the selected one, and by the time this rejection reaches any other layer the
303
+ * selection is back where the user left it. A refusal that arrives without that state is one no selection was live for, so its fields are simply absent.
304
+ * The line reports and nothing more - the acquisition draws no conclusion about the browser from a single refusal.
305
+ */
306
+ if (formatError(error).includes(CAPTURE_SOURCE_UNAVAILABLE_MESSAGE)) {
307
+ const diagnostics = (error instanceof CaptureStartRefusedError) ? error.diagnostics : { activeTab: null, windowState: null };
308
+ LOG.warn("Chrome refused to start the tab capture.", { activeTab: diagnostics.activeTab, elapsedMs: acquisitionElapsed(), windowState: diagnostics.windowState });
309
+ }
310
+ // The failure is already an Error: acquireOnce normalizes every rejection at the one boundary where a page-side value enters, so it travels unchanged.
311
+ throw error;
312
+ }
313
+ }
314
+ //# sourceMappingURL=tabCapture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tabCapture.js","sourceRoot":"","sources":["../../src/browser/tabCapture.ts"],"names":[],"mappings":"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"}
@@ -46,4 +46,3 @@ export interface TabNetworkObserver extends Disposable {
46
46
  * @returns The observer handle, or null if installation failed.
47
47
  */
48
48
  export declare function observeTabResponses(page: Page, options: TabNetworkObserverOptions): Promise<Nullable<TabNetworkObserver>>;
49
- //# sourceMappingURL=tabNetworkObserver.d.ts.map
@@ -0,0 +1,117 @@
1
+ import type { Browser, Page } from "puppeteer-core";
2
+ import type { Clock } from "homebridge-plugin-utils";
3
+ import type { Nullable } from "../types/index.ts";
4
+ import { getExtensionPage } from "puppeteer-stream";
5
+ export declare const TAB_NOT_FOUND_MESSAGE = "The capture extension could not find the page's tab.";
6
+ export declare const TAB_NOT_SELECTED_MESSAGE = "The capture extension did not select the page's tab.";
7
+ /**
8
+ * The library value this module talks to, injected so a test can drive a whole hold without a browser.
9
+ */
10
+ export interface TabSelectionDeps {
11
+ readonly getExtensionPage: typeof getExtensionPage;
12
+ }
13
+ /**
14
+ * The collaborators an open runs through: the window topology, and the library lookup this module already talks to.
15
+ *
16
+ * A sibling of TabSelectionDeps rather than an extension of it, because TabSelectionDeps has to stay satisfiable by its own default for the three consumers that
17
+ * take it that way. The two topology functions answer questions about CDP's window table, which this module structurally cannot ask - it speaks to the capture
18
+ * extension and to nothing else - so they carry no default at all and arrive from a call site that can see both modules.
19
+ */
20
+ export interface SharedWindowTabDeps {
21
+ readonly confirmPlacement: (page: Page) => Promise<boolean>;
22
+ readonly getExtensionPage?: typeof getExtensionPage;
23
+ readonly resolveCarrier: (browser: Browser) => Promise<Nullable<Page>>;
24
+ }
25
+ /**
26
+ * Per-call context for an open: how long the whole turn may take, the clock that ceiling runs on, and the collaborators it runs through.
27
+ */
28
+ export interface OpenSharedWindowTabContext {
29
+ readonly ceilingMs?: number;
30
+ readonly clock?: Clock;
31
+ readonly deps: SharedWindowTabDeps;
32
+ }
33
+ /**
34
+ * The selected tab handed to a hold's body: what it is, and the way to be sure of it again at a moment of the body's own choosing.
35
+ */
36
+ export interface SelectedTab {
37
+ readonly id: number;
38
+ readonly reassert: () => Promise<void>;
39
+ readonly url: Nullable<string>;
40
+ readonly windowId: number;
41
+ }
42
+ /**
43
+ * Per-call context for a hold: how long the selection may be held, the clock that bound runs on, and the collaborators it talks through.
44
+ */
45
+ export interface WithTabSelectedContext {
46
+ readonly ceilingMs?: number;
47
+ readonly clock?: Clock;
48
+ readonly deps?: TabSelectionDeps;
49
+ }
50
+ export declare const defaultTabSelectionDeps: TabSelectionDeps;
51
+ /**
52
+ * Subscribes to the activation report: every tab this module activates through the extension, announced by id as soon as the update resolves.
53
+ *
54
+ * A captured page cannot hear its own activation, so the module performing the activation is the one place the fact exists to be announced at all. The report
55
+ * carries the id and stops there, which is what keeps this module's vocabulary to tabs and windows no matter what a subscriber goes on to do with one.
56
+ * @param listener - Called with the id of each tab this module activates.
57
+ * @returns The closure that ends the subscription. A subscriber that has gone away without calling it stays in the set for the life of the process.
58
+ */
59
+ export declare function onTabActivation(listener: (tabId: number) => void): () => void;
60
+ /**
61
+ * The tab id a page was identified as, when it has one.
62
+ *
63
+ * The report names a tab and a subscriber holds pages, so this is the bridge between them. The answer is only ever an id a completed identification cached, which
64
+ * means a page this module has never selected reads undefined - the right answer for it, because no activation of ours can have named it.
65
+ * @param page - The page to look up.
66
+ * @returns The cached tab id, or undefined when this page has not been identified.
67
+ */
68
+ export declare function getCachedTabId(page: Page): number | undefined;
69
+ /**
70
+ * Runs a body with a page's tab selected in its window, and hands back the tab that was selected before it afterwards.
71
+ *
72
+ * Holds are serialized: this queues onto the chain, and the hold that follows begins when this one has given the selection back - not when this caller has
73
+ * finished reading its result, which is what lets a body that outlives its ceiling keep running without holding the selection or the queue.
74
+ * @param page - The page whose tab the body needs selected.
75
+ * @param body - The work to run while the tab is selected. It receives the selected tab.
76
+ * @param context - The ceiling, clock, and collaborators. Defaults to the capture start's own deadline on the system clock with the production collaborators.
77
+ * @returns Whatever the body resolves with, even when the hold's ceiling lapsed first.
78
+ * @throws The body's own rejection, or a selection failure of this module's own.
79
+ */
80
+ export declare function withTabSelected<T>(page: Page, body: (tab: SelectedTab) => Promise<T>, context?: WithTabSelectedContext): Promise<T>;
81
+ /**
82
+ * Opens a page as a tab of the shared browser window, and hands the selection straight back to the tab that had it.
83
+ *
84
+ * The open belongs here because the open IS a selection change. Chrome picks the window for a plain background page and skips a minimized one, so a capture tab
85
+ * created while the shared window rests minimized beside a discovery window takes root in the discovery window instead and keeps that window alive long past the
86
+ * walk it was opened for. The one anchor Chrome honors in every window state is the opener relationship: a window.open evaluated on a page of the shared window
87
+ * opens its tab in that window, minimized or not, and restores the window on the way in (measured 2026-08-31, both window states).
88
+ *
89
+ * Running it as a turn on this module's executor closes two races rather than one. chrome.tabCapture records whichever tab is selected and page creation runs
90
+ * outside the capture lock, so a bare open could land between a concurrent stream's re-assert and its recording start and put a blank tab on that stream's
91
+ * recording; and two overlapping opens on one page silently lose all but the first, because a page carries a single transient activation. Serialized turns make
92
+ * both unrepresentable rather than unlikely.
93
+ *
94
+ * Two id spaces meet at this call and are never compared. The window identity a placement is confirmed against belongs to CDP's table, and this module never sees
95
+ * it - it arrives as an injected answer of true or false. Every id this module reads or writes itself, the tab that was selected and the tab that gets it back,
96
+ * is the capture extension's.
97
+ *
98
+ * Three side effects belong to somebody else. The tab arrives selected, which is why the selection goes back inside this same turn. The open restores a minimized
99
+ * window, which the window-visibility policy settles afterwards. And the give-back's activation report re-affirms whichever tab regains the selection, so when
100
+ * that is another stream's capture page its composition wobbles for about a second until the re-affirm ladder lands - the same self-healing wobble a capture
101
+ * start already causes once, now possible a second time at page creation.
102
+ * @param browser - The browser to open the tab in.
103
+ * @param context - The turn's ceiling, the clock it runs on, and the collaborators it runs through.
104
+ * @returns The opened page, or a page created the plain way when the anchor could not be had.
105
+ */
106
+ export declare function openSharedWindowTab(browser: Browser, context: OpenSharedWindowTabContext): Promise<Page>;
107
+ /**
108
+ * Installs the listener that closes the tabs abandoned opens leave behind, for the life of the browser it is given.
109
+ *
110
+ * A turn's evaluate keeps running inside Chrome after the turn's own wait has ended, so a carrier that was merely slow can land its tab long after the turn
111
+ * scanned for one and created its page the plain way. Nothing registered that tab, so nothing judges it and nothing closes it. The browser's own target events
112
+ * are what make it findable: a page target whose URL carries the open marker, and whose nonce no pass is waiting for, is one nobody asked for. Both target
113
+ * events are read because a window.open target is created at about:blank and takes its URL on the change that follows, which leaves the judgment a function of
114
+ * the target's URL and this module's own state and nothing else.
115
+ * @param browser - The browser whose targets to watch.
116
+ */
117
+ export declare function installStrayOpenTabReaper(browser: Browser): void;