prismcast 1.13.0 → 1.14.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 (218) hide show
  1. package/dist/app.d.ts +88 -6
  2. package/dist/app.js +287 -154
  3. package/dist/app.js.map +1 -1
  4. package/dist/browser/cdp.d.ts +6 -17
  5. package/dist/browser/cdp.js +6 -57
  6. package/dist/browser/cdp.js.map +1 -1
  7. package/dist/browser/index.d.ts +106 -23
  8. package/dist/browser/index.js +292 -225
  9. package/dist/browser/index.js.map +1 -1
  10. package/dist/browser/precaching.d.ts +25 -11
  11. package/dist/browser/precaching.js +245 -97
  12. package/dist/browser/precaching.js.map +1 -1
  13. package/dist/browser/tabCapture.js +3 -10
  14. package/dist/browser/tabCapture.js.map +1 -1
  15. package/dist/browser/tuning/comcastPolymer.js +13 -14
  16. package/dist/browser/tuning/comcastPolymer.js.map +1 -1
  17. package/dist/browser/tuning/hbo.js +34 -17
  18. package/dist/browser/tuning/hbo.js.map +1 -1
  19. package/dist/browser/video.d.ts +1 -1
  20. package/dist/browser/video.js +3 -3
  21. package/dist/channels/index.js +5 -5
  22. package/dist/channels/index.js.map +1 -1
  23. package/dist/cliHelp.d.ts +11 -0
  24. package/dist/cliHelp.js +148 -0
  25. package/dist/cliHelp.js.map +1 -0
  26. package/dist/config/channelForm.js +5 -4
  27. package/dist/config/channelForm.js.map +1 -1
  28. package/dist/config/consistencyProbe.d.ts +2 -4
  29. package/dist/config/consistencyProbe.js +8 -51
  30. package/dist/config/consistencyProbe.js.map +1 -1
  31. package/dist/config/index.d.ts +107 -55
  32. package/dist/config/index.js +499 -267
  33. package/dist/config/index.js.map +1 -1
  34. package/dist/config/paths.d.ts +13 -8
  35. package/dist/config/paths.js +21 -25
  36. package/dist/config/paths.js.map +1 -1
  37. package/dist/config/persistence.d.ts +57 -11
  38. package/dist/config/persistence.js +127 -44
  39. package/dist/config/persistence.js.map +1 -1
  40. package/dist/config/reactivity.d.ts +60 -36
  41. package/dist/config/reactivity.js +89 -116
  42. package/dist/config/reactivity.js.map +1 -1
  43. package/dist/config/services.d.ts +61 -26
  44. package/dist/config/services.js +137 -68
  45. package/dist/config/services.js.map +1 -1
  46. package/dist/config/streamSettings.d.ts +24 -0
  47. package/dist/config/streamSettings.js +17 -0
  48. package/dist/config/streamSettings.js.map +1 -0
  49. package/dist/config/userChannels.d.ts +60 -52
  50. package/dist/config/userChannels.js +138 -188
  51. package/dist/config/userChannels.js.map +1 -1
  52. package/dist/config/userConfig.d.ts +224 -61
  53. package/dist/config/userConfig.js +351 -134
  54. package/dist/config/userConfig.js.map +1 -1
  55. package/dist/hdhr/discover.d.ts +7 -1
  56. package/dist/hdhr/discover.js +12 -6
  57. package/dist/hdhr/discover.js.map +1 -1
  58. package/dist/hdhr/index.d.ts +51 -10
  59. package/dist/hdhr/index.js +108 -112
  60. package/dist/hdhr/index.js.map +1 -1
  61. package/dist/hdhr/udp.d.ts +11 -4
  62. package/dist/hdhr/udp.js +25 -20
  63. package/dist/hdhr/udp.js.map +1 -1
  64. package/dist/index.js +16 -143
  65. package/dist/index.js.map +1 -1
  66. package/dist/native/index.d.ts +1 -1
  67. package/dist/native/index.js +4 -3
  68. package/dist/native/index.js.map +1 -1
  69. package/dist/native/proxy.d.ts +1 -1
  70. package/dist/native/proxy.js +36 -28
  71. package/dist/native/proxy.js.map +1 -1
  72. package/dist/routes/cdp.d.ts +7 -6
  73. package/dist/routes/cdp.js +9 -8
  74. package/dist/routes/cdp.js.map +1 -1
  75. package/dist/routes/components.d.ts +23 -5
  76. package/dist/routes/components.js +21 -4
  77. package/dist/routes/components.js.map +1 -1
  78. package/dist/routes/config/channels/endpoints/browse.js +39 -29
  79. package/dist/routes/config/channels/endpoints/browse.js.map +1 -1
  80. package/dist/routes/config/channels/endpoints/bulk.js +2 -6
  81. package/dist/routes/config/channels/endpoints/bulk.js.map +1 -1
  82. package/dist/routes/config/channels/endpoints/predefined.js +5 -15
  83. package/dist/routes/config/channels/endpoints/predefined.js.map +1 -1
  84. package/dist/routes/config/channels/endpoints/prefs.js +7 -6
  85. package/dist/routes/config/channels/endpoints/prefs.js.map +1 -1
  86. package/dist/routes/config/channels/endpoints/service.js +6 -5
  87. package/dist/routes/config/channels/endpoints/service.js.map +1 -1
  88. package/dist/routes/config/channels/endpoints/tags.js +4 -16
  89. package/dist/routes/config/channels/endpoints/tags.js.map +1 -1
  90. package/dist/routes/config/channels/table.d.ts +2 -1
  91. package/dist/routes/config/channels/table.js +11 -13
  92. package/dist/routes/config/channels/table.js.map +1 -1
  93. package/dist/routes/config/http/envelope.d.ts +6 -3
  94. package/dist/routes/config/http/envelope.js +18 -5
  95. package/dist/routes/config/http/envelope.js.map +1 -1
  96. package/dist/routes/config/index.d.ts +21 -13
  97. package/dist/routes/config/index.js +47 -34
  98. package/dist/routes/config/index.js.map +1 -1
  99. package/dist/routes/config/settings.d.ts +43 -6
  100. package/dist/routes/config/settings.js +225 -125
  101. package/dist/routes/config/settings.js.map +1 -1
  102. package/dist/routes/config/vocabulary.d.ts +24 -0
  103. package/dist/routes/config/vocabulary.js +33 -0
  104. package/dist/routes/config/vocabulary.js.map +1 -0
  105. package/dist/routes/debug.js +28 -13
  106. package/dist/routes/debug.js.map +1 -1
  107. package/dist/routes/root/content.js +33 -26
  108. package/dist/routes/root/content.js.map +1 -1
  109. package/dist/routes/root/scripts/channels.js +23 -11
  110. package/dist/routes/root/scripts/channels.js.map +1 -1
  111. package/dist/routes/root/scripts/config.d.ts +1 -1
  112. package/dist/routes/root/scripts/config.js +127 -79
  113. package/dist/routes/root/scripts/config.js.map +1 -1
  114. package/dist/routes/root/scripts/shared.js +34 -23
  115. package/dist/routes/root/scripts/shared.js.map +1 -1
  116. package/dist/routes/root/scripts/status.handlers.d.ts +8 -13
  117. package/dist/routes/root/scripts/status.handlers.js +35 -21
  118. package/dist/routes/root/scripts/status.handlers.js.map +1 -1
  119. package/dist/routes/root/styles.js +13 -16
  120. package/dist/routes/root/styles.js.map +1 -1
  121. package/dist/routes/services.js +12 -16
  122. package/dist/routes/services.js.map +1 -1
  123. package/dist/routes/theme.js +12 -12
  124. package/dist/routes/theme.js.map +1 -1
  125. package/dist/routes/ui.d.ts +4 -3
  126. package/dist/routes/ui.js +17 -13
  127. package/dist/routes/ui.js.map +1 -1
  128. package/dist/service/generators.js +12 -9
  129. package/dist/service/generators.js.map +1 -1
  130. package/dist/streaming/captureSession.d.ts +4 -4
  131. package/dist/streaming/captureSession.js +6 -7
  132. package/dist/streaming/captureSession.js.map +1 -1
  133. package/dist/streaming/codec.d.ts +12 -2
  134. package/dist/streaming/codec.js +40 -28
  135. package/dist/streaming/codec.js.map +1 -1
  136. package/dist/streaming/fmp4Segmenter.d.ts +14 -4
  137. package/dist/streaming/fmp4Segmenter.js +99 -79
  138. package/dist/streaming/fmp4Segmenter.js.map +1 -1
  139. package/dist/streaming/hls.d.ts +21 -14
  140. package/dist/streaming/hls.js +148 -122
  141. package/dist/streaming/hls.js.map +1 -1
  142. package/dist/streaming/hlsResume.d.ts +36 -13
  143. package/dist/streaming/hlsResume.js +68 -37
  144. package/dist/streaming/hlsResume.js.map +1 -1
  145. package/dist/streaming/monitor.d.ts +5 -3
  146. package/dist/streaming/monitor.js +47 -37
  147. package/dist/streaming/monitor.js.map +1 -1
  148. package/dist/streaming/mp4Parser.d.ts +29 -4
  149. package/dist/streaming/mp4Parser.js +49 -7
  150. package/dist/streaming/mp4Parser.js.map +1 -1
  151. package/dist/streaming/playlistBuilder.d.ts +1 -2
  152. package/dist/streaming/playlistBuilder.js +2 -3
  153. package/dist/streaming/playlistBuilder.js.map +1 -1
  154. package/dist/streaming/preroll.d.ts +43 -16
  155. package/dist/streaming/preroll.js +112 -62
  156. package/dist/streaming/preroll.js.map +1 -1
  157. package/dist/streaming/pretune.d.ts +2 -2
  158. package/dist/streaming/pretune.js +11 -7
  159. package/dist/streaming/pretune.js.map +1 -1
  160. package/dist/streaming/recovery.d.ts +29 -2
  161. package/dist/streaming/recovery.js +43 -4
  162. package/dist/streaming/recovery.js.map +1 -1
  163. package/dist/streaming/registry.d.ts +13 -10
  164. package/dist/streaming/registry.js +6 -5
  165. package/dist/streaming/registry.js.map +1 -1
  166. package/dist/streaming/setup.d.ts +29 -20
  167. package/dist/streaming/setup.js +181 -170
  168. package/dist/streaming/setup.js.map +1 -1
  169. package/dist/streaming/showInfo.d.ts +24 -12
  170. package/dist/streaming/showInfo.js +120 -113
  171. package/dist/streaming/showInfo.js.map +1 -1
  172. package/dist/streaming/statusEmitter.d.ts +15 -10
  173. package/dist/streaming/statusEmitter.js +24 -20
  174. package/dist/streaming/statusEmitter.js.map +1 -1
  175. package/dist/types/config.d.ts +24 -13
  176. package/dist/types/config.js +5 -1
  177. package/dist/types/config.js.map +1 -1
  178. package/dist/types/index.d.ts +3 -2
  179. package/dist/types/index.js +2 -1
  180. package/dist/types/index.js.map +1 -1
  181. package/dist/types/profiles.d.ts +2 -2
  182. package/dist/types/selection.d.ts +12 -10
  183. package/dist/types/streaming.d.ts +12 -5
  184. package/dist/types/streaming.js +12 -5
  185. package/dist/types/streaming.js.map +1 -1
  186. package/dist/utils/debugFilter.d.ts +3 -2
  187. package/dist/utils/debugFilter.js +7 -5
  188. package/dist/utils/debugFilter.js.map +1 -1
  189. package/dist/{hdhr → utils}/deviceId.d.ts +1 -1
  190. package/dist/{hdhr → utils}/deviceId.js +11 -29
  191. package/dist/utils/deviceId.js.map +1 -0
  192. package/dist/utils/errors.d.ts +7 -0
  193. package/dist/utils/errors.js +12 -3
  194. package/dist/utils/errors.js.map +1 -1
  195. package/dist/utils/fileLogger.d.ts +23 -12
  196. package/dist/utils/fileLogger.js +73 -41
  197. package/dist/utils/fileLogger.js.map +1 -1
  198. package/dist/utils/httpErrors.d.ts +13 -0
  199. package/dist/utils/httpErrors.js +22 -0
  200. package/dist/utils/httpErrors.js.map +1 -0
  201. package/dist/utils/index.d.ts +3 -0
  202. package/dist/utils/index.js +3 -0
  203. package/dist/utils/index.js.map +1 -1
  204. package/dist/utils/logger.d.ts +9 -8
  205. package/dist/utils/logger.js +64 -20
  206. package/dist/utils/logger.js.map +1 -1
  207. package/dist/utils/markup.js +8 -3
  208. package/dist/utils/markup.js.map +1 -1
  209. package/dist/utils/plainObject.d.ts +6 -0
  210. package/dist/utils/plainObject.js +18 -0
  211. package/dist/utils/plainObject.js.map +1 -0
  212. package/dist/utils/runtimeIdentity.context.js +1 -29
  213. package/dist/utils/runtimeIdentity.context.js.map +1 -1
  214. package/dist/utils/runtimeIdentity.d.ts +17 -6
  215. package/dist/utils/runtimeIdentity.js +50 -17
  216. package/dist/utils/runtimeIdentity.js.map +1 -1
  217. package/package.json +5 -5
  218. package/dist/hdhr/deviceId.js.map +0 -1
@@ -1,16 +1,15 @@
1
1
  import { LOG } from "../utils/index.js";
2
2
  // Factory.
3
3
  /**
4
- * Creates a CaptureSession over an already-acquired capture stream and optional FFmpeg child. The pipeline output - the stream the segmenter will consume - is
5
- * derived here: FFmpeg's stdout when transcoding, otherwise the raw capture stream itself.
6
- * @param options - The capture stream and optional FFmpeg child to own.
4
+ * Creates a CaptureSession over an already-acquired capture stream and the FFmpeg child remuxing it. The pipeline output - the stream the segmenter will consume -
5
+ * is FFmpeg's stdout.
6
+ * @param options - The capture stream and the FFmpeg child to own.
7
7
  * @returns A CaptureSession handle.
8
8
  */
9
9
  export function createCaptureSession(options) {
10
10
  const { ffmpegProcess, rawCaptureStream } = options;
11
- // The pipeline output the segmenter consumes. In FFmpeg mode this is FFmpeg's fMP4 stdout; in native-fMP4 mode the raw capture stream is already fMP4 and is its
12
- // own output. Computed once because both handles are stable for the session's lifetime.
13
- const outputStream = ffmpegProcess?.stdout ?? rawCaptureStream;
11
+ // The pipeline output the segmenter consumes is FFmpeg's fMP4 stdout, read once because the handle is stable for the session's lifetime.
12
+ const outputStream = ffmpegProcess.stdout;
14
13
  let disposed = false;
15
14
  let segmenter = null;
16
15
  const attachSegmenter = (incoming) => {
@@ -31,7 +30,7 @@ export function createCaptureSession(options) {
31
30
  }
32
31
  disposed = true;
33
32
  // Step 1: kill FFmpeg first so its shuttingDown flag is set before the capture stream's EOF can reach its stdin. See the module header for why the order matters.
34
- ffmpegProcess?.kill();
33
+ ffmpegProcess.kill();
35
34
  // Step 2: destroy the raw capture stream to fire STOP_RECORDING while the browser is still connected and to carry EOF down the pipeline.
36
35
  if (!rawCaptureStream.destroyed) {
37
36
  rawCaptureStream.destroy();
@@ -1 +1 @@
1
- {"version":3,"file":"captureSession.js","sourceRoot":"","sources":["../../src/streaming/captureSession.ts"],"names":[],"mappings":"AA6CA,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AA8CxC,WAAW;AAEX;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAoC;IAEvE,MAAM,EAAE,aAAa,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAC;IAEpD,iKAAiK;IACjK,wFAAwF;IACxF,MAAM,YAAY,GAAa,aAAa,EAAE,MAAM,IAAI,gBAAgB,CAAC;IAEzE,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,IAAI,SAAS,GAAkC,IAAI,CAAC;IAEpD,MAAM,eAAe,GAAG,CAAC,QAA6B,EAAQ,EAAE;QAE9D,gKAAgK;QAChK,iJAAiJ;QACjJ,IAAG,QAAQ,EAAE,CAAC;YAEZ,GAAG,CAAC,KAAK,CAAC,iBAAiB,EAAE,iFAAiF,CAAC,CAAC;YAChH,QAAQ,CAAC,IAAI,EAAE,CAAC;YAEhB,OAAO;QACT,CAAC;QAED,SAAS,GAAG,QAAQ,CAAC;QAErB,6HAA6H;QAC7H,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC9B,CAAC,CAAC;IAEF,MAAM,OAAO,GAAG,GAAS,EAAE;QAEzB,IAAG,QAAQ,EAAE,CAAC;YAEZ,OAAO;QACT,CAAC;QAED,QAAQ,GAAG,IAAI,CAAC;QAEhB,kKAAkK;QAClK,aAAa,EAAE,IAAI,EAAE,CAAC;QAEtB,yIAAyI;QACzI,IAAG,CAAC,gBAAgB,CAAC,SAAS,EAAE,CAAC;YAE/B,gBAAgB,CAAC,OAAO,EAAE,CAAC;QAC7B,CAAC;QAED,kEAAkE;QAClE,SAAS,EAAE,IAAI,EAAE,CAAC;IACpB,CAAC,CAAC;IAEF,OAAO;QAEL,eAAe;QACf,OAAO;QACP,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,OAAO;QAEzB,IAAI,QAAQ;YAEV,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,IAAI,SAAS;YAEX,OAAO,SAAS,CAAC;QACnB,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"captureSession.js","sourceRoot":"","sources":["../../src/streaming/captureSession.ts"],"names":[],"mappings":"AAuCA,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AA8CxC,WAAW;AAEX;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAoC;IAEvE,MAAM,EAAE,aAAa,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAC;IAEpD,yIAAyI;IACzI,MAAM,YAAY,GAAa,aAAa,CAAC,MAAM,CAAC;IAEpD,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,IAAI,SAAS,GAAkC,IAAI,CAAC;IAEpD,MAAM,eAAe,GAAG,CAAC,QAA6B,EAAQ,EAAE;QAE9D,gKAAgK;QAChK,iJAAiJ;QACjJ,IAAG,QAAQ,EAAE,CAAC;YAEZ,GAAG,CAAC,KAAK,CAAC,iBAAiB,EAAE,iFAAiF,CAAC,CAAC;YAChH,QAAQ,CAAC,IAAI,EAAE,CAAC;YAEhB,OAAO;QACT,CAAC;QAED,SAAS,GAAG,QAAQ,CAAC;QAErB,6HAA6H;QAC7H,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC9B,CAAC,CAAC;IAEF,MAAM,OAAO,GAAG,GAAS,EAAE;QAEzB,IAAG,QAAQ,EAAE,CAAC;YAEZ,OAAO;QACT,CAAC;QAED,QAAQ,GAAG,IAAI,CAAC;QAEhB,kKAAkK;QAClK,aAAa,CAAC,IAAI,EAAE,CAAC;QAErB,yIAAyI;QACzI,IAAG,CAAC,gBAAgB,CAAC,SAAS,EAAE,CAAC;YAE/B,gBAAgB,CAAC,OAAO,EAAE,CAAC;QAC7B,CAAC;QAED,kEAAkE;QAClE,SAAS,EAAE,IAAI,EAAE,CAAC;IACpB,CAAC,CAAC;IAEF,OAAO;QAEL,eAAe;QACf,OAAO;QACP,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,OAAO;QAEzB,IAAI,QAAQ;YAEV,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,IAAI,SAAS;YAEX,OAAO,SAAS,CAAC;QACnB,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -2,12 +2,22 @@ import type { CaptureCodec } from "../types/index.ts";
2
2
  export type { CaptureCodec } from "../types/index.ts";
3
3
  /**
4
4
  * Returns the effective capture codec based on the user's allowlist and GPU hardware capabilities. Walks codecs in priority order (highest quality first), returning
5
- * the first that's both allowed by the user AND supported by the GPU. Falls back to H.264 as the universal baseline.
5
+ * the first that the user allows and this GPU can capture, as isCaptureCodecSupported() answers it. Falls back to CAPTURE_BASELINE_CODEC.
6
6
  *
7
- * This is the single source of truth for all capture codec decisions in the codebase. Do not check GPU codec capabilities directly - call this function instead.
7
+ * This is the single source of truth for the capture's codec decision, and isCaptureCodecSupported() is the one answer to whether this GPU can capture a codec. A
8
+ * caller that needs the decision or the per-codec answer asks this module rather than reading the GPU capabilities itself.
8
9
  * @returns The codec to use for capture.
9
10
  */
10
11
  export declare function getEffectiveCaptureCodec(): CaptureCodec;
12
+ /**
13
+ * Answers whether this GPU can capture a codec. The baseline needs no GPU encoding, so it is always supported; any other codec is supported when CODEC_PRIORITY
14
+ * holds it and the GPU reports the hardware encoding flag CAPTURE_CODEC_CAPABILITIES keys to it, and a codec the list does not hold is not. Capabilities not yet
15
+ * detected read as unsupported, because a GPU whose encoders are unknown must never be offered a codec it may not encode. The effective-codec walk and the settings
16
+ * form's codec items read this answer, and the acceleration answer reads the effective codec's flag in CAPTURE_CODEC_CAPABILITIES.
17
+ * @param codec - The codec to test.
18
+ * @returns True when this GPU can capture the codec.
19
+ */
20
+ export declare function isCaptureCodecSupported(codec: CaptureCodec): boolean;
11
21
  /**
12
22
  * Returns the Matroska MIME type string for the effective capture codec. Used by the capture pipeline to configure Chrome's MediaRecorder.
13
23
  * @returns The MIME type string for the current capture codec.
@@ -2,12 +2,15 @@
2
2
  *
3
3
  * codec.ts: Capture codec selection for PrismCast.
4
4
  */
5
+ import { CAPTURE_BASELINE_CODEC } from "../types/index.js";
5
6
  import { CONFIG } from "../config/index.js";
6
7
  import { getGpuCapabilities } from "../browser/display.js";
7
- /* This module is the single source of truth for capture codec behavior. Every component that needs to know which video codec to use for capture - MIME type
8
- * selection, preroll generation, status display - calls getEffectiveCaptureCodec() rather than checking GPU capabilities directly. The decision encapsulates three
9
- * inputs: the user's codec allowlist (CONFIG.streaming.captureCodecs), the GPU's hardware encoding capabilities, and the priority order (prefer higher-quality
10
- * codecs when available). Codec identity (RECOGNIZED_CODECS and CaptureCodec) lives in types/streaming.ts; this module provides the runtime logic.
8
+ /* This module is the single source of truth for capture codec behavior. The capture's codec decision, getEffectiveCaptureCodec(), combines the user's codec
9
+ * allowlist (CONFIG.streaming.captureCodecs), the GPU's hardware encoding capabilities, and the priority order (prefer higher-quality codecs when available).
10
+ * Whether this GPU can capture a given codec is isCaptureCodecSupported()'s answer. The effective-codec walk and the settings form's codec items read this answer,
11
+ * and the acceleration answer reads the effective codec's flag in CAPTURE_CODEC_CAPABILITIES. Every component that needs the decision or the per-codec answer -
12
+ * MIME type selection, preroll generation, status display, the settings form - asks this module rather than reading the GPU capabilities itself. Codec identity
13
+ * (RECOGNIZED_CODECS, CaptureCodec and CAPTURE_BASELINE_CODEC) lives in types/streaming.ts; this module provides the runtime logic.
11
14
  */
12
15
  // Matroska MIME types keyed by capture codec. Matroska is used over WebM because it supports a broader range of codecs (including HEVC and AV1), allowing codec
13
16
  // upgrades without changing the container format. FFmpeg's demuxer handles both Matroska and WebM identically. All variants use Opus audio which FFmpeg transcodes
@@ -16,27 +19,46 @@ const CAPTURE_MIME_TYPES = {
16
19
  h264: "video/x-matroska;codecs=h264,opus",
17
20
  hevc: "video/x-matroska;codecs=hvc1.1.6.L93.B0,opus"
18
21
  };
19
- // Codec priority order. Higher-quality codecs are tried first. Each entry pairs a codec with its GPU capability check. H.264 is the implicit fallback and is not
20
- // listed here since it always works (Chrome's MediaRecorder baseline).
21
- const CODEC_PRIORITY = [
22
- { capability: "hevcHardwareEncoding", codec: "hevc" }
23
- ];
22
+ // Each recognized codec's GPU hardware encoding flag. The table is keyed by the codec union, so the compiler holds every recognized codec, the baseline among them,
23
+ // to the flag that answers whether this GPU encodes it in hardware.
24
+ const CAPTURE_CODEC_CAPABILITIES = {
25
+ h264: "h264HardwareEncoding",
26
+ hevc: "hevcHardwareEncoding"
27
+ };
28
+ // Codec priority order. Higher-quality codecs are tried first. The baseline needs no GPU capability (Chrome's MediaRecorder encodes it everywhere), so the list's
29
+ // type excludes it and it is the walk's fallback rather than an entry.
30
+ const CODEC_PRIORITY = ["hevc"];
24
31
  /**
25
32
  * Returns the effective capture codec based on the user's allowlist and GPU hardware capabilities. Walks codecs in priority order (highest quality first), returning
26
- * the first that's both allowed by the user AND supported by the GPU. Falls back to H.264 as the universal baseline.
33
+ * the first that the user allows and this GPU can capture, as isCaptureCodecSupported() answers it. Falls back to CAPTURE_BASELINE_CODEC.
27
34
  *
28
- * This is the single source of truth for all capture codec decisions in the codebase. Do not check GPU codec capabilities directly - call this function instead.
35
+ * This is the single source of truth for the capture's codec decision, and isCaptureCodecSupported() is the one answer to whether this GPU can capture a codec. A
36
+ * caller that needs the decision or the per-codec answer asks this module rather than reading the GPU capabilities itself.
29
37
  * @returns The codec to use for capture.
30
38
  */
31
39
  export function getEffectiveCaptureCodec() {
32
40
  const allowedCodecs = CONFIG.streaming.captureCodecs;
33
- const gpuCaps = getGpuCapabilities();
34
- for (const { capability, codec } of CODEC_PRIORITY) {
35
- if (allowedCodecs.includes(codec) && gpuCaps?.[capability]) {
41
+ for (const codec of CODEC_PRIORITY) {
42
+ if (allowedCodecs.includes(codec) && isCaptureCodecSupported(codec)) {
36
43
  return codec;
37
44
  }
38
45
  }
39
- return "h264";
46
+ return CAPTURE_BASELINE_CODEC;
47
+ }
48
+ /**
49
+ * Answers whether this GPU can capture a codec. The baseline needs no GPU encoding, so it is always supported; any other codec is supported when CODEC_PRIORITY
50
+ * holds it and the GPU reports the hardware encoding flag CAPTURE_CODEC_CAPABILITIES keys to it, and a codec the list does not hold is not. Capabilities not yet
51
+ * detected read as unsupported, because a GPU whose encoders are unknown must never be offered a codec it may not encode. The effective-codec walk and the settings
52
+ * form's codec items read this answer, and the acceleration answer reads the effective codec's flag in CAPTURE_CODEC_CAPABILITIES.
53
+ * @param codec - The codec to test.
54
+ * @returns True when this GPU can capture the codec.
55
+ */
56
+ export function isCaptureCodecSupported(codec) {
57
+ if (codec === CAPTURE_BASELINE_CODEC) {
58
+ return true;
59
+ }
60
+ // A codec the priority list does not hold is never chosen by the walk, so no GPU flag can make it supported.
61
+ return CODEC_PRIORITY.includes(codec) && (getGpuCapabilities()?.[CAPTURE_CODEC_CAPABILITIES[codec]] === true);
40
62
  }
41
63
  /**
42
64
  * Returns the Matroska MIME type string for the effective capture codec. Used by the capture pipeline to configure Chrome's MediaRecorder.
@@ -50,18 +72,8 @@ export function getCaptureMimeType() {
50
72
  * @returns True if the effective codec has hardware encoding support.
51
73
  */
52
74
  export function isCaptureHardwareAccelerated() {
53
- const codec = getEffectiveCaptureCodec();
54
- const gpuCaps = getGpuCapabilities();
55
- if (codec === "h264") {
56
- return gpuCaps?.h264HardwareEncoding === true;
57
- }
58
- // All non-H.264 codecs in CODEC_PRIORITY are only selected when their hardware capability is true, so this is guaranteed. The explicit check keeps the function
59
- // self-contained rather than relying on getEffectiveCaptureCodec's selection logic.
60
- for (const { capability, codec: priorityCodec } of CODEC_PRIORITY) {
61
- if (priorityCodec === codec) {
62
- return gpuCaps?.[capability] === true;
63
- }
64
- }
65
- return false;
75
+ // A codec other than the baseline is chosen only when its flag is set, and the baseline is chosen whether or not its own flag is set, so one read of the effective
76
+ // codec's flag answers every codec.
77
+ return getGpuCapabilities()?.[CAPTURE_CODEC_CAPABILITIES[getEffectiveCaptureCodec()]] === true;
66
78
  }
67
79
  //# sourceMappingURL=codec.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"codec.js","sourceRoot":"","sources":["../../src/streaming/codec.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAK3D;;;;GAIG;AAEH,gKAAgK;AAChK,mKAAmK;AACnK,UAAU;AACV,MAAM,kBAAkB,GAAiC;IAEvD,IAAI,EAAE,mCAAmC;IACzC,IAAI,EAAE,8CAA8C;CACrD,CAAC;AAEF,iKAAiK;AACjK,uEAAuE;AACvE,MAAM,cAAc,GAA0F;IAE5G,EAAE,UAAU,EAAE,sBAAsB,EAAE,KAAK,EAAE,MAAM,EAAE;CACtD,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,wBAAwB;IAEtC,MAAM,aAAa,GAAG,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC;IACrD,MAAM,OAAO,GAAG,kBAAkB,EAAE,CAAC;IAErC,KAAI,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,IAAI,cAAc,EAAE,CAAC;QAElD,IAAG,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,OAAO,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC;YAE1D,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB;IAEhC,OAAO,kBAAkB,CAAC,wBAAwB,EAAE,CAAC,CAAC;AACxD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,4BAA4B;IAE1C,MAAM,KAAK,GAAG,wBAAwB,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,kBAAkB,EAAE,CAAC;IAErC,IAAG,KAAK,KAAK,MAAM,EAAE,CAAC;QAEpB,OAAO,OAAO,EAAE,oBAAoB,KAAK,IAAI,CAAC;IAChD,CAAC;IAED,gKAAgK;IAChK,oFAAoF;IACpF,KAAI,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,cAAc,EAAE,CAAC;QAEjE,IAAG,aAAa,KAAK,KAAK,EAAE,CAAC;YAE3B,OAAO,OAAO,EAAE,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;QACxC,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
1
+ {"version":3,"file":"codec.js","sourceRoot":"","sources":["../../src/streaming/codec.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAG5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAK3D;;;;;;GAMG;AAEH,gKAAgK;AAChK,mKAAmK;AACnK,UAAU;AACV,MAAM,kBAAkB,GAAiC;IAEvD,IAAI,EAAE,mCAAmC;IACzC,IAAI,EAAE,8CAA8C;CACrD,CAAC;AAEF,oKAAoK;AACpK,oEAAoE;AACpE,MAAM,0BAA0B,GAA+E;IAE7G,IAAI,EAAE,sBAAsB;IAC5B,IAAI,EAAE,sBAAsB;CAC7B,CAAC;AAEF,kKAAkK;AAClK,uEAAuE;AACvE,MAAM,cAAc,GAAoE,CAAC,MAAM,CAAC,CAAC;AAEjG;;;;;;;GAOG;AACH,MAAM,UAAU,wBAAwB;IAEtC,MAAM,aAAa,GAAG,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC;IAErD,KAAI,MAAM,KAAK,IAAI,cAAc,EAAE,CAAC;QAElC,IAAG,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,uBAAuB,CAAC,KAAK,CAAC,EAAE,CAAC;YAEnE,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,OAAO,sBAAsB,CAAC;AAChC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,uBAAuB,CAAC,KAAmB;IAEzD,IAAG,KAAK,KAAK,sBAAsB,EAAE,CAAC;QAEpC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,6GAA6G;IAC7G,OAAO,cAAc,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,kBAAkB,EAAE,EAAE,CAAC,0BAA0B,CAAC,KAAK,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;AAChH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB;IAEhC,OAAO,kBAAkB,CAAC,wBAAwB,EAAE,CAAC,CAAC;AACxD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,4BAA4B;IAE1C,mKAAmK;IACnK,oCAAoC;IACpC,OAAO,kBAAkB,EAAE,EAAE,CAAC,0BAA0B,CAAC,wBAAwB,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC;AACjG,CAAC"}
@@ -2,9 +2,17 @@ import type { CaptureCodec } from "./codec.ts";
2
2
  import type { Clock } from "homebridge-plugin-utils";
3
3
  import type { Nullable } from "../types/index.ts";
4
4
  import type { Readable } from "node:stream";
5
+ import type { StreamSettings } from "../config/streamSettings.ts";
6
+ export interface SegmentHistory {
7
+ readonly discontinuityIndices: ReadonlySet<number>;
8
+ readonly prunedDiscontinuityCount: number;
9
+ readonly segmentDurations: ReadonlyMap<number, number>;
10
+ readonly segmentTimestamps: ReadonlyMap<number, number>;
11
+ }
5
12
  export interface SegmenterContinuity {
6
13
  initialTrackTimestamps?: Map<number, bigint>;
7
14
  previousInitSegment?: Nullable<Buffer>;
15
+ priorSegmentHistory?: SegmentHistory;
8
16
  priorSessionStats?: SessionStats;
9
17
  startingInitVersion?: number;
10
18
  startingSegmentIndex?: number;
@@ -19,8 +27,9 @@ export interface FMP4SegmenterOptions {
19
27
  onStop: () => void;
20
28
  pendingDiscontinuity?: boolean;
21
29
  prerollBaseUrl?: Nullable<string>;
22
- prerollCodec?: CaptureCodec;
30
+ prerollCodec?: Nullable<CaptureCodec>;
23
31
  prerollSegmentCount?: number;
32
+ segmentDuration: StreamSettings["segmentDuration"];
24
33
  streamId: number;
25
34
  }
26
35
  /**
@@ -53,6 +62,7 @@ export interface SessionStats {
53
62
  */
54
63
  export interface FMP4SegmenterResult {
55
64
  getContinuitySnapshot: () => SegmenterContinuity;
65
+ getDiscontinuityCount: () => number;
56
66
  getInitSegment: () => Nullable<Buffer>;
57
67
  getInitVersion: () => number;
58
68
  getKeyframeStats: () => KeyframeStats;
@@ -66,8 +76,8 @@ export interface FMP4SegmenterResult {
66
76
  stop: () => void;
67
77
  }
68
78
  /**
69
- * Formats keyframe statistics into a human-readable summary for the termination log. Returns an empty string if no moof boxes were processed. The format mirrors the
70
- * recovery metrics summary style used in monitor.ts.
79
+ * Formats keyframe statistics into a human-readable summary for the termination log. Returns an empty string if no moof boxes were processed. The format mirrors
80
+ * formatRecoveryMetricsSummary() in recovery.ts, which the termination log in lifecycle.ts composes alongside it.
71
81
  *
72
82
  * Example output:
73
83
  * - "Keyframes: 2490 of 2490 moofs (100.0%), interval 1.9-2.1s avg 2.0s."
@@ -119,7 +129,7 @@ export declare function computeDiscontinuitySequence(options: {
119
129
  }): number | undefined;
120
130
  /**
121
131
  * Creates an fMP4 segmenter that transforms MP4 input into HLS segments. The segmenter parses MP4 boxes, extracts the init segment, optionally detects keyframes
122
- * in each moof fragment when KEYFRAME_DEBUG is enabled, and accumulates media fragments into segments based on the configured duration.
132
+ * in each moof fragment when KEYFRAME_DEBUG is enabled, and accumulates media fragments into segments based on the segment duration it is given.
123
133
  * @param options - Segmenter options including stream ID and callbacks.
124
134
  * @returns The segmenter interface with pipe, stop, and keyframe stats methods.
125
135
  */