prismcast 1.5.2 → 1.7.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 (239) hide show
  1. package/README.md +44 -28
  2. package/dist/app.d.ts +5 -0
  3. package/dist/app.js +63 -5
  4. package/dist/app.js.map +1 -1
  5. package/dist/browser/cdp.js +1 -1
  6. package/dist/browser/cdp.js.map +1 -1
  7. package/dist/browser/channelSelection.d.ts +10 -34
  8. package/dist/browser/channelSelection.js +31 -96
  9. package/dist/browser/channelSelection.js.map +1 -1
  10. package/dist/browser/display.d.ts +19 -0
  11. package/dist/browser/display.js +16 -11
  12. package/dist/browser/display.js.map +1 -1
  13. package/dist/browser/index.d.ts +31 -54
  14. package/dist/browser/index.js +334 -272
  15. package/dist/browser/index.js.map +1 -1
  16. package/dist/browser/login.d.ts +65 -0
  17. package/dist/browser/login.js +193 -0
  18. package/dist/browser/login.js.map +1 -0
  19. package/dist/browser/precaching.js +15 -3
  20. package/dist/browser/precaching.js.map +1 -1
  21. package/dist/browser/tuning/comcastPolymer.d.ts +23 -0
  22. package/dist/browser/tuning/comcastPolymer.js +655 -0
  23. package/dist/browser/tuning/comcastPolymer.js.map +1 -0
  24. package/dist/browser/tuning/cox.d.ts +2 -0
  25. package/dist/browser/tuning/cox.js +14 -0
  26. package/dist/browser/tuning/cox.js.map +1 -0
  27. package/dist/browser/tuning/directv.js +14 -1
  28. package/dist/browser/tuning/directv.js.map +1 -1
  29. package/dist/browser/tuning/fox.js +14 -2
  30. package/dist/browser/tuning/fox.js.map +1 -1
  31. package/dist/browser/tuning/hbo.js +12 -1
  32. package/dist/browser/tuning/hbo.js.map +1 -1
  33. package/dist/browser/tuning/hulu.js +24 -1
  34. package/dist/browser/tuning/hulu.js.map +1 -1
  35. package/dist/browser/tuning/shared.d.ts +46 -0
  36. package/dist/browser/tuning/shared.js +100 -0
  37. package/dist/browser/tuning/shared.js.map +1 -0
  38. package/dist/browser/tuning/sling.js +35 -5
  39. package/dist/browser/tuning/sling.js.map +1 -1
  40. package/dist/browser/tuning/spectrum.js +13 -1
  41. package/dist/browser/tuning/spectrum.js.map +1 -1
  42. package/dist/browser/tuning/thumbnailRow.js +1 -1
  43. package/dist/browser/tuning/thumbnailRow.js.map +1 -1
  44. package/dist/browser/tuning/tileClick.js +1 -1
  45. package/dist/browser/tuning/tileClick.js.map +1 -1
  46. package/dist/browser/tuning/xfinity.d.ts +2 -0
  47. package/dist/browser/tuning/xfinity.js +14 -0
  48. package/dist/browser/tuning/xfinity.js.map +1 -0
  49. package/dist/browser/tuning/youtubeTv.js +15 -1
  50. package/dist/browser/tuning/youtubeTv.js.map +1 -1
  51. package/dist/browser/video.d.ts +20 -0
  52. package/dist/browser/video.js +168 -124
  53. package/dist/browser/video.js.map +1 -1
  54. package/dist/channels/index.d.ts +2 -2
  55. package/dist/channels/index.js +2075 -683
  56. package/dist/channels/index.js.map +1 -1
  57. package/dist/config/health.d.ts +28 -28
  58. package/dist/config/health.js +72 -54
  59. package/dist/config/health.js.map +1 -1
  60. package/dist/config/index.js +29 -64
  61. package/dist/config/index.js.map +1 -1
  62. package/dist/config/paths.d.ts +12 -0
  63. package/dist/config/paths.js +16 -0
  64. package/dist/config/paths.js.map +1 -1
  65. package/dist/config/profiles.d.ts +3 -2
  66. package/dist/config/profiles.js +45 -34
  67. package/dist/config/profiles.js.map +1 -1
  68. package/dist/config/providerPacks.js +4 -1
  69. package/dist/config/providerPacks.js.map +1 -1
  70. package/dist/config/providers.d.ts +19 -5
  71. package/dist/config/providers.js +123 -93
  72. package/dist/config/providers.js.map +1 -1
  73. package/dist/config/sites.d.ts +28 -0
  74. package/dist/config/sites.js +104 -127
  75. package/dist/config/sites.js.map +1 -1
  76. package/dist/config/userChannels.d.ts +53 -2
  77. package/dist/config/userChannels.js +222 -13
  78. package/dist/config/userChannels.js.map +1 -1
  79. package/dist/config/userConfig.d.ts +2 -1
  80. package/dist/config/userConfig.js +6 -15
  81. package/dist/config/userConfig.js.map +1 -1
  82. package/dist/config/userProfiles.d.ts +0 -1
  83. package/dist/config/userProfiles.js +18 -10
  84. package/dist/config/userProfiles.js.map +1 -1
  85. package/dist/hdhr/channelMap.d.ts +1 -1
  86. package/dist/hdhr/channelMap.js +4 -4
  87. package/dist/hdhr/channelMap.js.map +1 -1
  88. package/dist/index.js +25 -22
  89. package/dist/index.js.map +1 -1
  90. package/dist/native/decrypt.d.ts +32 -0
  91. package/dist/native/decrypt.js +85 -0
  92. package/dist/native/decrypt.js.map +1 -0
  93. package/dist/native/index.d.ts +61 -0
  94. package/dist/native/index.js +342 -0
  95. package/dist/native/index.js.map +1 -0
  96. package/dist/native/intercept.d.ts +35 -0
  97. package/dist/native/intercept.js +184 -0
  98. package/dist/native/intercept.js.map +1 -0
  99. package/dist/native/probe.d.ts +49 -0
  100. package/dist/native/probe.js +294 -0
  101. package/dist/native/probe.js.map +1 -0
  102. package/dist/native/proxy.d.ts +54 -0
  103. package/dist/native/proxy.js +947 -0
  104. package/dist/native/proxy.js.map +1 -0
  105. package/dist/routes/components.d.ts +43 -0
  106. package/dist/routes/components.js +122 -0
  107. package/dist/routes/components.js.map +1 -1
  108. package/dist/routes/config/channels/index.d.ts +2 -2
  109. package/dist/routes/config/channels/index.js +1 -1
  110. package/dist/routes/config/channels/index.js.map +1 -1
  111. package/dist/routes/config/channels/routes.js +443 -65
  112. package/dist/routes/config/channels/routes.js.map +1 -1
  113. package/dist/routes/config/channels/table.d.ts +76 -0
  114. package/dist/routes/config/channels/table.js +369 -89
  115. package/dist/routes/config/channels/table.js.map +1 -1
  116. package/dist/routes/config/index.d.ts +1 -1
  117. package/dist/routes/config/index.js +1 -1
  118. package/dist/routes/config/index.js.map +1 -1
  119. package/dist/routes/config/providers.d.ts +6 -6
  120. package/dist/routes/config/providers.js +73 -99
  121. package/dist/routes/config/providers.js.map +1 -1
  122. package/dist/routes/debug.js +5 -5
  123. package/dist/routes/debug.js.map +1 -1
  124. package/dist/routes/hls.js +12 -2
  125. package/dist/routes/hls.js.map +1 -1
  126. package/dist/routes/index.d.ts +0 -15
  127. package/dist/routes/index.js +2 -16
  128. package/dist/routes/index.js.map +1 -1
  129. package/dist/routes/providers.js +106 -3
  130. package/dist/routes/providers.js.map +1 -1
  131. package/dist/routes/root/content.js +124 -47
  132. package/dist/routes/root/content.js.map +1 -1
  133. package/dist/routes/root/index.js +2 -1
  134. package/dist/routes/root/index.js.map +1 -1
  135. package/dist/routes/root/scripts/channels.js +772 -312
  136. package/dist/routes/root/scripts/channels.js.map +1 -1
  137. package/dist/routes/root/scripts/config.js +596 -544
  138. package/dist/routes/root/scripts/config.js.map +1 -1
  139. package/dist/routes/root/scripts/index.d.ts +1 -0
  140. package/dist/routes/root/scripts/index.js +1 -0
  141. package/dist/routes/root/scripts/index.js.map +1 -1
  142. package/dist/routes/root/scripts/shared.d.ts +6 -0
  143. package/dist/routes/root/scripts/shared.js +391 -0
  144. package/dist/routes/root/scripts/shared.js.map +1 -0
  145. package/dist/routes/root/scripts/status.js +49 -33
  146. package/dist/routes/root/scripts/status.js.map +1 -1
  147. package/dist/routes/root/styles.js +117 -10
  148. package/dist/routes/root/styles.js.map +1 -1
  149. package/dist/service/commands.js +2 -1
  150. package/dist/service/commands.js.map +1 -1
  151. package/dist/streaming/fmp4Segmenter.d.ts +5 -0
  152. package/dist/streaming/fmp4Segmenter.js +146 -42
  153. package/dist/streaming/fmp4Segmenter.js.map +1 -1
  154. package/dist/streaming/hls.d.ts +24 -19
  155. package/dist/streaming/hls.js +603 -297
  156. package/dist/streaming/hls.js.map +1 -1
  157. package/dist/streaming/hlsResume.d.ts +16 -3
  158. package/dist/streaming/hlsResume.js +35 -8
  159. package/dist/streaming/hlsResume.js.map +1 -1
  160. package/dist/streaming/hlsSegments.d.ts +41 -2
  161. package/dist/streaming/hlsSegments.js +131 -28
  162. package/dist/streaming/hlsSegments.js.map +1 -1
  163. package/dist/streaming/lifecycle.js +27 -13
  164. package/dist/streaming/lifecycle.js.map +1 -1
  165. package/dist/streaming/monitor.d.ts +1 -0
  166. package/dist/streaming/monitor.js +862 -474
  167. package/dist/streaming/monitor.js.map +1 -1
  168. package/dist/streaming/mp4Parser.d.ts +52 -6
  169. package/dist/streaming/mp4Parser.js +156 -30
  170. package/dist/streaming/mp4Parser.js.map +1 -1
  171. package/dist/streaming/mpegts.d.ts +2 -2
  172. package/dist/streaming/mpegts.js +156 -109
  173. package/dist/streaming/mpegts.js.map +1 -1
  174. package/dist/streaming/playlistBuilder.d.ts +38 -0
  175. package/dist/streaming/playlistBuilder.js +66 -0
  176. package/dist/streaming/playlistBuilder.js.map +1 -0
  177. package/dist/streaming/preroll.d.ts +126 -0
  178. package/dist/streaming/preroll.js +434 -0
  179. package/dist/streaming/preroll.js.map +1 -0
  180. package/dist/streaming/pretune.d.ts +8 -0
  181. package/dist/streaming/pretune.js +226 -0
  182. package/dist/streaming/pretune.js.map +1 -0
  183. package/dist/streaming/recovery.d.ts +0 -6
  184. package/dist/streaming/recovery.js +0 -8
  185. package/dist/streaming/recovery.js.map +1 -1
  186. package/dist/streaming/registry.d.ts +57 -9
  187. package/dist/streaming/registry.js +26 -7
  188. package/dist/streaming/registry.js.map +1 -1
  189. package/dist/streaming/setup.d.ts +8 -1
  190. package/dist/streaming/setup.js +71 -27
  191. package/dist/streaming/setup.js.map +1 -1
  192. package/dist/streaming/showInfo.d.ts +29 -4
  193. package/dist/streaming/showInfo.js +210 -38
  194. package/dist/streaming/showInfo.js.map +1 -1
  195. package/dist/streaming/statusEmitter.d.ts +20 -6
  196. package/dist/streaming/statusEmitter.js +31 -7
  197. package/dist/streaming/statusEmitter.js.map +1 -1
  198. package/dist/types/channels.d.ts +32 -0
  199. package/dist/types/config.d.ts +2 -2
  200. package/dist/types/index.d.ts +2 -2
  201. package/dist/types/index.js.map +1 -1
  202. package/dist/types/profiles.d.ts +13 -1
  203. package/dist/types/selection.d.ts +5 -1
  204. package/dist/types/shared.d.ts +1 -1
  205. package/dist/types/streaming.d.ts +7 -0
  206. package/dist/utils/chromeFetch.d.ts +20 -0
  207. package/dist/utils/chromeFetch.js +43 -0
  208. package/dist/utils/chromeFetch.js.map +1 -0
  209. package/dist/utils/debugFilter.d.ts +0 -5
  210. package/dist/utils/debugFilter.js +20 -11
  211. package/dist/utils/debugFilter.js.map +1 -1
  212. package/dist/utils/delay.d.ts +28 -0
  213. package/dist/utils/delay.js +35 -1
  214. package/dist/utils/delay.js.map +1 -1
  215. package/dist/utils/evaluate.js +6 -11
  216. package/dist/utils/evaluate.js.map +1 -1
  217. package/dist/utils/ffmpeg.d.ts +14 -12
  218. package/dist/utils/ffmpeg.js +114 -134
  219. package/dist/utils/ffmpeg.js.map +1 -1
  220. package/dist/utils/format.d.ts +6 -0
  221. package/dist/utils/format.js +8 -0
  222. package/dist/utils/format.js.map +1 -1
  223. package/dist/utils/index.d.ts +3 -0
  224. package/dist/utils/index.js +3 -0
  225. package/dist/utils/index.js.map +1 -1
  226. package/dist/utils/logEmitter.js +1 -1
  227. package/dist/utils/logEmitter.js.map +1 -1
  228. package/dist/utils/pid.d.ts +40 -0
  229. package/dist/utils/pid.js +83 -0
  230. package/dist/utils/pid.js.map +1 -0
  231. package/dist/utils/retry.d.ts +15 -9
  232. package/dist/utils/retry.js +7 -23
  233. package/dist/utils/retry.js.map +1 -1
  234. package/dist/utils/timing.d.ts +5 -0
  235. package/dist/utils/timing.js +13 -0
  236. package/dist/utils/timing.js.map +1 -0
  237. package/dist/utils/version.js +2 -2
  238. package/dist/utils/version.js.map +1 -1
  239. package/package.json +7 -7
@@ -0,0 +1,294 @@
1
+ /* Copyright(C) 2024-2026, HJD (https://github.com/hjdhjd). All rights reserved.
2
+ *
3
+ * probe.ts: DRM probe for HLS manifest encryption classification.
4
+ */
5
+ import { LOG, chromeFetch, startTimer } from "../utils/index.js";
6
+ /* This module fetches an HLS master manifest, selects the highest-bandwidth variant, and inspects its #EXT-X-KEY tags to classify the encryption type. The result
7
+ * determines whether PrismCast can consume the stream natively (clear or AES-128) or must fall back to screen capture (Widevine, FairPlay, or other DRM).
8
+ *
9
+ * Classification logic:
10
+ * - No #EXT-X-KEY or METHOD=NONE → "clear" (no encryption, direct pass-through)
11
+ * - METHOD=AES-128 with accessible key URL → "aes128" (Node can decrypt with crypto.createDecipheriv)
12
+ * - METHOD=SAMPLE-AES, SAMPLE-AES-CTR, or any other method → "drm" (requires CDM, not viable)
13
+ */
14
+ // Timeout for individual manifest/key fetches.
15
+ const FETCH_TIMEOUT = 10000;
16
+ // Cache of encryption types keyed by channel name. Stores the classification (clear/aes128/drm) with a timestamp for TTL expiration. Variant URLs and key URLs
17
+ // contain session-bound auth tokens that expire between tunes, so they must never be cached — only the stable encryption type is safe to persist across sessions.
18
+ // The DRM skip optimization in setup.ts uses this cache to avoid installing the CDP interceptor for channels known to use DRM.
19
+ const probeCache = new Map();
20
+ // Cache entries older than this are considered stale and re-probed. 24 hours covers the case where a provider changes a channel's encryption profile (e.g., free →
21
+ // premium DRM). The DRM short-circuit in probeManifest() still applies within the TTL, so frequently-tuned DRM channels avoid repeated probe overhead.
22
+ const PROBE_CACHE_TTL = 24 * 60 * 60 * 1000;
23
+ /**
24
+ * Returns the cached encryption type for a channel, or null if the channel has not been probed or the cache entry has expired. Used by the stream setup path to skip
25
+ * CDP interceptor installation for channels already known to use DRM.
26
+ *
27
+ * @param channelName - The channel name to look up.
28
+ * @returns The cached encryption type, or null if not probed or expired.
29
+ */
30
+ export function getCachedEncryption(channelName) {
31
+ const entry = probeCache.get(channelName);
32
+ if (!entry) {
33
+ return null;
34
+ }
35
+ if ((Date.now() - entry.timestamp) > PROBE_CACHE_TTL) {
36
+ probeCache.delete(channelName);
37
+ return null;
38
+ }
39
+ return entry.encryption;
40
+ }
41
+ /**
42
+ * Clears the probe cache for a specific channel. Called when a native stream fails, forcing a fresh probe on the next attempt.
43
+ *
44
+ * @param channelName - The channel name to clear from the cache.
45
+ */
46
+ export function clearProbeCache(channelName) {
47
+ probeCache.delete(channelName);
48
+ }
49
+ /**
50
+ * Probes an HLS master manifest to determine encryption type and select the best variant. The probe cache is checked for DRM channels only — if a previous probe
51
+ * classified the channel as DRM, we return the cached result immediately since the caller will bail out regardless of URLs. For viable channels (clear or aes128),
52
+ * we always run the full probe because the variant URL and key URL contain auth tokens that expire between browser sessions.
53
+ *
54
+ * @param masterUrl - The master manifest URL (contains auth tokens from the browser's original request).
55
+ * @param channelName - The channel name for cache lookup.
56
+ * @returns The probe result, or null if probing fails.
57
+ */
58
+ export async function probeManifest(masterUrl, channelName) {
59
+ // Short-circuit for DRM channels only. The cached DRM classification is stable within the TTL window (providers rarely change DRM type), and the caller returns
60
+ // null immediately on DRM without using any URLs. For clear/aes128 channels, we must re-probe to get fresh variant and key URLs with current auth tokens.
61
+ const cached = getCachedEncryption(channelName);
62
+ if (cached === "drm") {
63
+ LOG.debug("native:probe", "Probe cache hit for %s: drm.", channelName);
64
+ return { audioVariantUrl: null, bandwidth: 0, bestVariantUrl: "", codec: null, encryption: "drm", keyUrl: null, resolution: null };
65
+ }
66
+ const elapsed = startTimer();
67
+ try {
68
+ // Fetch the master manifest.
69
+ const masterBody = await fetchManifestText(masterUrl);
70
+ if (!masterBody) {
71
+ LOG.debug("native:probe", "Failed to fetch master manifest for %s.", channelName);
72
+ return null;
73
+ }
74
+ // Parse variant streams and select the highest bandwidth.
75
+ const bestVariant = selectBestVariant(masterBody, masterUrl);
76
+ if (!bestVariant) {
77
+ LOG.debug("native:probe", "No variant streams found in master manifest for %s.", channelName);
78
+ return null;
79
+ }
80
+ LOG.debug("native:probe", "Best variant selected for %s: %s.", channelName, bestVariant.url.slice(0, 120));
81
+ // Check for a separate audio rendition in the master manifest.
82
+ const audioVariantUrl = parseAudioRendition(masterBody, masterUrl);
83
+ if (audioVariantUrl) {
84
+ LOG.debug("native:probe", "Separate audio rendition found for %s: %s.", channelName, audioVariantUrl.slice(0, 120));
85
+ }
86
+ // Fetch the variant manifest.
87
+ const variantBody = await fetchManifestText(bestVariant.url);
88
+ if (!variantBody) {
89
+ LOG.debug("native:probe", "Failed to fetch variant manifest for %s.", channelName);
90
+ return null;
91
+ }
92
+ // Classify encryption.
93
+ const result = await classifyEncryption(variantBody, bestVariant, audioVariantUrl, channelName);
94
+ probeCache.set(channelName, { encryption: result.encryption, timestamp: Date.now() });
95
+ LOG.debug("native:probe", "Probe completed for %s in %sms: %s.", channelName, elapsed(), result.encryption);
96
+ return result;
97
+ }
98
+ catch (error) {
99
+ LOG.debug("native:probe", "Probe failed for %s: %s.", channelName, String(error));
100
+ return null;
101
+ }
102
+ }
103
+ /**
104
+ * Fetches a manifest URL and returns the response text. Returns null on failure.
105
+ *
106
+ * @param url - The manifest URL to fetch.
107
+ * @returns The response text, or null on failure.
108
+ */
109
+ async function fetchManifestText(url) {
110
+ try {
111
+ const response = await chromeFetch(url, { signal: AbortSignal.timeout(FETCH_TIMEOUT) });
112
+ if (!response.ok) {
113
+ LOG.debug("native:probe", "Manifest fetch returned HTTP %s.", response.status);
114
+ return null;
115
+ }
116
+ return await response.text();
117
+ }
118
+ catch (error) {
119
+ LOG.debug("native:probe", "Manifest fetch error: %s.", String(error));
120
+ return null;
121
+ }
122
+ }
123
+ /**
124
+ * Parses #EXT-X-STREAM-INF lines from a master manifest and returns the highest-bandwidth variant with its metadata.
125
+ *
126
+ * @param masterBody - The master manifest content.
127
+ * @param masterUrl - The master manifest URL for resolving relative variant URLs.
128
+ * @returns The selected variant metadata, or null if no variants are found.
129
+ */
130
+ function selectBestVariant(masterBody, masterUrl) {
131
+ // Map video codec prefixes from CODECS attribute to human-readable labels. Defined outside the variant iteration loop to avoid per-line allocation.
132
+ const codecPrefixes = { "av01": "AV1", "avc1": "H264", "avc3": "H264", "hev1": "HEVC", "hvc1": "HEVC", "vp09": "VP9" };
133
+ const lines = masterBody.split("\n");
134
+ let bestBandwidth = 0;
135
+ let bestCodec = null;
136
+ let bestResolution = null;
137
+ let bestUrl = null;
138
+ const bandwidths = [];
139
+ for (let i = 0; i < lines.length; i++) {
140
+ const line = lines[i].trim();
141
+ if (!line.startsWith("#EXT-X-STREAM-INF:")) {
142
+ continue;
143
+ }
144
+ // Parse BANDWIDTH attribute.
145
+ const bandwidthMatch = /BANDWIDTH=(\d+)/.exec(line);
146
+ const bandwidth = bandwidthMatch ? Number(bandwidthMatch[1]) : 0;
147
+ // Parse RESOLUTION attribute (e.g., RESOLUTION=1920x1080).
148
+ const resolutionMatch = /RESOLUTION=(\d+x\d+)/.exec(line);
149
+ const resolution = resolutionMatch ? resolutionMatch[1] : null;
150
+ // Parse CODECS attribute and map the video codec prefix to a human-readable label. The CODECS value contains comma-separated codec strings (e.g.,
151
+ // "avc1.640028,mp4a.40.2"). The video codec is identified by its prefix: avc1/avc3 → H264, hvc1/hev1 → HEVC, av01 → AV1, vp09 → VP9.
152
+ const codecsMatch = /CODECS="([^"]+)"/.exec(line);
153
+ let codec = null;
154
+ if (codecsMatch) {
155
+ const codecStr = codecsMatch[1].split(",")[0].trim();
156
+ const prefix = codecStr.split(".")[0];
157
+ codec = codecPrefixes[prefix] ?? null;
158
+ }
159
+ // The variant URL is on the next line.
160
+ const variantLine = (i + 1 < lines.length) ? lines[i + 1].trim() : "";
161
+ if (!variantLine || variantLine.startsWith("#")) {
162
+ continue;
163
+ }
164
+ bandwidths.push(bandwidth);
165
+ if (bandwidth > bestBandwidth) {
166
+ bestBandwidth = bandwidth;
167
+ bestCodec = codec;
168
+ bestResolution = resolution;
169
+ bestUrl = variantLine;
170
+ }
171
+ }
172
+ LOG.debug("native:probe", "Found %s variant(s) with bandwidths: %s.", bandwidths.length, bandwidths.join(", "));
173
+ if (!bestUrl) {
174
+ return null;
175
+ }
176
+ // Resolve relative URLs against the master manifest URL.
177
+ return { bandwidth: bestBandwidth, codec: bestCodec, resolution: bestResolution, url: resolveUrl(bestUrl, masterUrl) };
178
+ }
179
+ /**
180
+ * Classifies the encryption type of a variant manifest by parsing its #EXT-X-KEY tags.
181
+ *
182
+ * @param variantBody - The variant manifest content.
183
+ * @param variant - The selected variant metadata (URL, bandwidth, resolution).
184
+ * @param audioVariantUrl - The audio rendition URL, or null when audio is muxed.
185
+ * @param channelName - The channel name for logging.
186
+ * @returns The probe result with the classified encryption type.
187
+ */
188
+ async function classifyEncryption(variantBody, variant, audioVariantUrl, channelName) {
189
+ const lines = variantBody.split("\n");
190
+ let encryption = "clear";
191
+ let keyUrl = null;
192
+ for (const line of lines) {
193
+ const trimmed = line.trim();
194
+ if (!trimmed.startsWith("#EXT-X-KEY:")) {
195
+ continue;
196
+ }
197
+ // Parse METHOD attribute.
198
+ const methodMatch = /METHOD=([A-Za-z0-9-]+)/.exec(trimmed);
199
+ const method = methodMatch ? methodMatch[1].toUpperCase() : "NONE";
200
+ if (method === "NONE") {
201
+ continue;
202
+ }
203
+ if (method === "AES-128") {
204
+ // Parse URI attribute for the key URL.
205
+ const uriMatch = /URI="([^"]+)"/.exec(trimmed);
206
+ if (!uriMatch) {
207
+ LOG.debug("native:probe", "AES-128 key tag has no URI for %s.", channelName);
208
+ encryption = "drm";
209
+ break;
210
+ }
211
+ const rawKeyUrl = resolveUrl(uriMatch[1], variant.url);
212
+ // Test that the key is accessible and is exactly 16 bytes.
213
+ // eslint-disable-next-line no-await-in-loop
214
+ const keyAccessible = await testKeyAccessibility(rawKeyUrl);
215
+ if (keyAccessible) {
216
+ encryption = "aes128";
217
+ keyUrl = rawKeyUrl;
218
+ }
219
+ else {
220
+ LOG.debug("native:probe", "AES-128 key inaccessible or wrong size for %s.", channelName);
221
+ encryption = "drm";
222
+ }
223
+ break;
224
+ }
225
+ // SAMPLE-AES, SAMPLE-AES-CTR, or any other method indicates DRM.
226
+ LOG.debug("native:probe", "Unsupported encryption method '%s' for %s.", method, channelName);
227
+ encryption = "drm";
228
+ break;
229
+ }
230
+ return { audioVariantUrl, bandwidth: variant.bandwidth, bestVariantUrl: variant.url, codec: variant.codec, encryption, keyUrl, resolution: variant.resolution };
231
+ }
232
+ /**
233
+ * Tests whether an AES-128 key URL is accessible and returns a 16-byte key.
234
+ *
235
+ * @param keyUrl - The key URL to test.
236
+ * @returns True if the key is accessible and exactly 16 bytes.
237
+ */
238
+ async function testKeyAccessibility(keyUrl) {
239
+ try {
240
+ const response = await chromeFetch(keyUrl, { signal: AbortSignal.timeout(FETCH_TIMEOUT) });
241
+ if (!response.ok) {
242
+ return false;
243
+ }
244
+ const buffer = await response.arrayBuffer();
245
+ LOG.debug("native:probe", "Key fetch returned %s bytes.", buffer.byteLength);
246
+ return buffer.byteLength === 16;
247
+ }
248
+ catch (error) {
249
+ LOG.debug("native:probe", "Key accessibility test failed: %s.", String(error));
250
+ return false;
251
+ }
252
+ }
253
+ /**
254
+ * Parses the first #EXT-X-MEDIA:TYPE=AUDIO rendition with a URI from a master manifest. Returns the absolute audio variant URL, or null if no separate audio
255
+ * rendition is declared (audio is muxed into the video variant).
256
+ *
257
+ * @param masterBody - The master manifest content.
258
+ * @param masterUrl - The master manifest URL for resolving relative URIs.
259
+ * @returns The absolute audio variant URL, or null.
260
+ */
261
+ function parseAudioRendition(masterBody, masterUrl) {
262
+ for (const line of masterBody.split("\n")) {
263
+ const trimmed = line.trim();
264
+ if (!trimmed.startsWith("#EXT-X-MEDIA:")) {
265
+ continue;
266
+ }
267
+ // Only match AUDIO renditions.
268
+ if (!trimmed.includes("TYPE=AUDIO")) {
269
+ continue;
270
+ }
271
+ // Extract the URI attribute. Not all #EXT-X-MEDIA:TYPE=AUDIO tags have a URI — some are descriptive-only when audio is muxed into the video variant.
272
+ const uriMatch = /URI="([^"]+)"/.exec(trimmed);
273
+ if (uriMatch) {
274
+ return resolveUrl(uriMatch[1], masterUrl);
275
+ }
276
+ }
277
+ return null;
278
+ }
279
+ /**
280
+ * Resolves a potentially relative URL against a base URL. Handles both absolute and relative URLs. Exported for reuse by the proxy module.
281
+ *
282
+ * @param url - The URL to resolve (may be relative or absolute).
283
+ * @param baseUrl - The base URL for resolving relative references.
284
+ * @returns The resolved absolute URL.
285
+ */
286
+ export function resolveUrl(url, baseUrl) {
287
+ // If the URL is already absolute, return it directly.
288
+ if (url.startsWith("http://") || url.startsWith("https://")) {
289
+ return url;
290
+ }
291
+ // Use the URL constructor to resolve relative URLs against the base.
292
+ return new URL(url, baseUrl).href;
293
+ }
294
+ //# sourceMappingURL=probe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"probe.js","sourceRoot":"","sources":["../../src/native/probe.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ import { type PrerollCodec } from "../streaming/preroll.js";
2
+ import type { CDPSession } from "puppeteer-core";
3
+ import type { Nullable } from "../types/index.js";
4
+ /**
5
+ * Options for creating a native HLS proxy.
6
+ */
7
+ export interface NativeProxyOptions {
8
+ audioVariantUrl: Nullable<string>;
9
+ cdpSession: CDPSession;
10
+ channelName: string;
11
+ encryption: "aes128" | "clear";
12
+ keyUrl: Nullable<string>;
13
+ onError: (error: string) => void;
14
+ prefetchedKey: Nullable<Buffer>;
15
+ prerollCodec?: PrerollCodec;
16
+ prerollSegmentCount?: number;
17
+ streamId: number;
18
+ streamIdStr: string;
19
+ variantUrl: string;
20
+ }
21
+ /**
22
+ * Public interface returned by createNativeProxy(). Provides start/stop control and health metrics.
23
+ */
24
+ export interface NativeProxy {
25
+ getConsecutiveErrors: () => number;
26
+ hasErrored: () => boolean;
27
+ getLastSegmentSize: () => Nullable<number>;
28
+ getLastSegmentTime: () => number;
29
+ getSegmentIndex: () => number;
30
+ getStats: () => NativeProxyStats;
31
+ getTargetDuration: () => number;
32
+ start: () => void;
33
+ isStopped: () => boolean;
34
+ setTokenRefreshTimer: (timer: ReturnType<typeof setTimeout>) => void;
35
+ stop: () => void;
36
+ updateAudioVariantUrl: (newUrl: string) => void;
37
+ updateCdpSession: (session: CDPSession) => void;
38
+ updateVariantUrl: (newUrl: string) => void;
39
+ }
40
+ /**
41
+ * Statistics tracked by the native proxy for the termination summary.
42
+ */
43
+ export interface NativeProxyStats {
44
+ fetchErrors: number;
45
+ segmentsFetched: number;
46
+ tokenRefreshes: number;
47
+ }
48
+ /**
49
+ * Creates a native HLS proxy that polls a variant manifest, fetches segments, and generates playlists.
50
+ *
51
+ * @param options - Proxy configuration.
52
+ * @returns The native proxy interface.
53
+ */
54
+ export declare function createNativeProxy(options: NativeProxyOptions): NativeProxy;