@bnhf/prismcast 1.3.4-2026.2.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +7 -0
- package/README.md +347 -0
- package/bin/prismcast +6 -0
- package/dist/app.d.ts +6 -0
- package/dist/app.js +315 -0
- package/dist/app.js.map +1 -0
- package/dist/browser/cdp.d.ts +38 -0
- package/dist/browser/cdp.js +155 -0
- package/dist/browser/cdp.js.map +1 -0
- package/dist/browser/channelSelection.d.ts +65 -0
- package/dist/browser/channelSelection.js +202 -0
- package/dist/browser/channelSelection.js.map +1 -0
- package/dist/browser/display.d.ts +34 -0
- package/dist/browser/display.js +54 -0
- package/dist/browser/display.js.map +1 -0
- package/dist/browser/index.d.ts +205 -0
- package/dist/browser/index.js +1205 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/browser/tuning/fox.d.ts +2 -0
- package/dist/browser/tuning/fox.js +83 -0
- package/dist/browser/tuning/fox.js.map +1 -0
- package/dist/browser/tuning/hbo.d.ts +2 -0
- package/dist/browser/tuning/hbo.js +237 -0
- package/dist/browser/tuning/hbo.js.map +1 -0
- package/dist/browser/tuning/hulu.d.ts +2 -0
- package/dist/browser/tuning/hulu.js +550 -0
- package/dist/browser/tuning/hulu.js.map +1 -0
- package/dist/browser/tuning/sling.d.ts +2 -0
- package/dist/browser/tuning/sling.js +518 -0
- package/dist/browser/tuning/sling.js.map +1 -0
- package/dist/browser/tuning/thumbnailRow.d.ts +2 -0
- package/dist/browser/tuning/thumbnailRow.js +108 -0
- package/dist/browser/tuning/thumbnailRow.js.map +1 -0
- package/dist/browser/tuning/tileClick.d.ts +2 -0
- package/dist/browser/tuning/tileClick.js +103 -0
- package/dist/browser/tuning/tileClick.js.map +1 -0
- package/dist/browser/tuning/youtubeTv.d.ts +2 -0
- package/dist/browser/tuning/youtubeTv.js +182 -0
- package/dist/browser/tuning/youtubeTv.js.map +1 -0
- package/dist/browser/video.d.ts +289 -0
- package/dist/browser/video.js +996 -0
- package/dist/browser/video.js.map +1 -0
- package/dist/channels/index.d.ts +3 -0
- package/dist/channels/index.js +392 -0
- package/dist/channels/index.js.map +1 -0
- package/dist/config/index.d.ts +53 -0
- package/dist/config/index.js +233 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/presets.d.ts +98 -0
- package/dist/config/presets.js +241 -0
- package/dist/config/presets.js.map +1 -0
- package/dist/config/profiles.d.ts +79 -0
- package/dist/config/profiles.js +245 -0
- package/dist/config/profiles.js.map +1 -0
- package/dist/config/providers.d.ts +120 -0
- package/dist/config/providers.js +450 -0
- package/dist/config/providers.js.map +1 -0
- package/dist/config/sites.d.ts +22 -0
- package/dist/config/sites.js +377 -0
- package/dist/config/sites.js.map +1 -0
- package/dist/config/userChannels.d.ts +178 -0
- package/dist/config/userChannels.js +543 -0
- package/dist/config/userChannels.js.map +1 -0
- package/dist/config/userConfig.d.ts +235 -0
- package/dist/config/userConfig.js +913 -0
- package/dist/config/userConfig.js.map +1 -0
- package/dist/hdhr/channelMap.d.ts +21 -0
- package/dist/hdhr/channelMap.js +82 -0
- package/dist/hdhr/channelMap.js.map +1 -0
- package/dist/hdhr/deviceId.d.ts +11 -0
- package/dist/hdhr/deviceId.js +84 -0
- package/dist/hdhr/deviceId.js.map +1 -0
- package/dist/hdhr/discover.d.ts +6 -0
- package/dist/hdhr/discover.js +155 -0
- package/dist/hdhr/discover.js.map +1 -0
- package/dist/hdhr/index.d.ts +9 -0
- package/dist/hdhr/index.js +87 -0
- package/dist/hdhr/index.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +144 -0
- package/dist/index.js.map +1 -0
- package/dist/routes/assets.d.ts +6 -0
- package/dist/routes/assets.js +79 -0
- package/dist/routes/assets.js.map +1 -0
- package/dist/routes/auth.d.ts +6 -0
- package/dist/routes/auth.js +77 -0
- package/dist/routes/auth.js.map +1 -0
- package/dist/routes/channels.d.ts +6 -0
- package/dist/routes/channels.js +40 -0
- package/dist/routes/channels.js.map +1 -0
- package/dist/routes/components.d.ts +138 -0
- package/dist/routes/components.js +210 -0
- package/dist/routes/components.js.map +1 -0
- package/dist/routes/config.d.ts +72 -0
- package/dist/routes/config.js +1977 -0
- package/dist/routes/config.js.map +1 -0
- package/dist/routes/debug.d.ts +6 -0
- package/dist/routes/debug.js +274 -0
- package/dist/routes/debug.js.map +1 -0
- package/dist/routes/health.d.ts +6 -0
- package/dist/routes/health.js +85 -0
- package/dist/routes/health.js.map +1 -0
- package/dist/routes/hls.d.ts +6 -0
- package/dist/routes/hls.js +25 -0
- package/dist/routes/hls.js.map +1 -0
- package/dist/routes/index.d.ts +19 -0
- package/dist/routes/index.js +49 -0
- package/dist/routes/index.js.map +1 -0
- package/dist/routes/logs.d.ts +6 -0
- package/dist/routes/logs.js +164 -0
- package/dist/routes/logs.js.map +1 -0
- package/dist/routes/mpegts.d.ts +6 -0
- package/dist/routes/mpegts.js +19 -0
- package/dist/routes/mpegts.js.map +1 -0
- package/dist/routes/play.d.ts +6 -0
- package/dist/routes/play.js +18 -0
- package/dist/routes/play.js.map +1 -0
- package/dist/routes/playlist.d.ts +36 -0
- package/dist/routes/playlist.js +134 -0
- package/dist/routes/playlist.js.map +1 -0
- package/dist/routes/root.d.ts +6 -0
- package/dist/routes/root.js +2920 -0
- package/dist/routes/root.js.map +1 -0
- package/dist/routes/streams.d.ts +6 -0
- package/dist/routes/streams.js +88 -0
- package/dist/routes/streams.js.map +1 -0
- package/dist/routes/theme.d.ts +15 -0
- package/dist/routes/theme.js +275 -0
- package/dist/routes/theme.js.map +1 -0
- package/dist/routes/ui.d.ts +56 -0
- package/dist/routes/ui.js +354 -0
- package/dist/routes/ui.js.map +1 -0
- package/dist/service/commands.d.ts +41 -0
- package/dist/service/commands.js +391 -0
- package/dist/service/commands.js.map +1 -0
- package/dist/service/generators.d.ts +33 -0
- package/dist/service/generators.js +432 -0
- package/dist/service/generators.js.map +1 -0
- package/dist/service/index.d.ts +2 -0
- package/dist/service/index.js +7 -0
- package/dist/service/index.js.map +1 -0
- package/dist/streaming/clients.d.ts +48 -0
- package/dist/streaming/clients.js +114 -0
- package/dist/streaming/clients.js.map +1 -0
- package/dist/streaming/fmp4Segmenter.d.ts +61 -0
- package/dist/streaming/fmp4Segmenter.js +461 -0
- package/dist/streaming/fmp4Segmenter.js.map +1 -0
- package/dist/streaming/hls.d.ts +120 -0
- package/dist/streaming/hls.js +722 -0
- package/dist/streaming/hls.js.map +1 -0
- package/dist/streaming/hlsSegments.d.ts +54 -0
- package/dist/streaming/hlsSegments.js +162 -0
- package/dist/streaming/hlsSegments.js.map +1 -0
- package/dist/streaming/lifecycle.d.ts +33 -0
- package/dist/streaming/lifecycle.js +185 -0
- package/dist/streaming/lifecycle.js.map +1 -0
- package/dist/streaming/monitor.d.ts +74 -0
- package/dist/streaming/monitor.js +1310 -0
- package/dist/streaming/monitor.js.map +1 -0
- package/dist/streaming/mp4Parser.d.ts +74 -0
- package/dist/streaming/mp4Parser.js +566 -0
- package/dist/streaming/mp4Parser.js.map +1 -0
- package/dist/streaming/mpegts.d.ts +14 -0
- package/dist/streaming/mpegts.js +248 -0
- package/dist/streaming/mpegts.js.map +1 -0
- package/dist/streaming/registry.d.ts +119 -0
- package/dist/streaming/registry.js +127 -0
- package/dist/streaming/registry.js.map +1 -0
- package/dist/streaming/setup.d.ts +135 -0
- package/dist/streaming/setup.js +670 -0
- package/dist/streaming/setup.js.map +1 -0
- package/dist/streaming/showInfo.d.ts +30 -0
- package/dist/streaming/showInfo.js +362 -0
- package/dist/streaming/showInfo.js.map +1 -0
- package/dist/streaming/statusEmitter.d.ts +125 -0
- package/dist/streaming/statusEmitter.js +139 -0
- package/dist/streaming/statusEmitter.js.map +1 -0
- package/dist/types/index.d.ts +403 -0
- package/dist/types/index.js +6 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/debugFilter.d.ts +38 -0
- package/dist/utils/debugFilter.js +157 -0
- package/dist/utils/debugFilter.js.map +1 -0
- package/dist/utils/delay.d.ts +6 -0
- package/dist/utils/delay.js +15 -0
- package/dist/utils/delay.js.map +1 -0
- package/dist/utils/errors.d.ts +15 -0
- package/dist/utils/errors.js +40 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/evaluate.d.ts +51 -0
- package/dist/utils/evaluate.js +124 -0
- package/dist/utils/evaluate.js.map +1 -0
- package/dist/utils/ffmpeg.d.ts +65 -0
- package/dist/utils/ffmpeg.js +317 -0
- package/dist/utils/ffmpeg.js.map +1 -0
- package/dist/utils/fileLogger.d.ts +25 -0
- package/dist/utils/fileLogger.js +248 -0
- package/dist/utils/fileLogger.js.map +1 -0
- package/dist/utils/format.d.ts +16 -0
- package/dist/utils/format.js +46 -0
- package/dist/utils/format.js.map +1 -0
- package/dist/utils/html.d.ts +6 -0
- package/dist/utils/html.js +24 -0
- package/dist/utils/html.js.map +1 -0
- package/dist/utils/index.d.ts +15 -0
- package/dist/utils/index.js +20 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/logEmitter.d.ts +17 -0
- package/dist/utils/logEmitter.js +30 -0
- package/dist/utils/logEmitter.js.map +1 -0
- package/dist/utils/logger.d.ts +82 -0
- package/dist/utils/logger.js +219 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/m3u.d.ts +32 -0
- package/dist/utils/m3u.js +148 -0
- package/dist/utils/m3u.js.map +1 -0
- package/dist/utils/morganStream.d.ts +7 -0
- package/dist/utils/morganStream.js +33 -0
- package/dist/utils/morganStream.js.map +1 -0
- package/dist/utils/platform.d.ts +64 -0
- package/dist/utils/platform.js +157 -0
- package/dist/utils/platform.js.map +1 -0
- package/dist/utils/retry.d.ts +15 -0
- package/dist/utils/retry.js +82 -0
- package/dist/utils/retry.js.map +1 -0
- package/dist/utils/streamContext.d.ts +28 -0
- package/dist/utils/streamContext.js +33 -0
- package/dist/utils/streamContext.js.map +1 -0
- package/dist/utils/version.d.ts +37 -0
- package/dist/utils/version.js +228 -0
- package/dist/utils/version.js.map +1 -0
- package/package.json +92 -0
- package/prismcast.png +0 -0
- package/prismcast.svg +74 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { EventEmitter } from "events";
|
|
2
|
+
/* A singleton EventEmitter that broadcasts status updates to all subscribed SSE clients. The emitter maintains current state for all streams, allowing new clients
|
|
3
|
+
* to receive a snapshot of current status immediately upon connecting.
|
|
4
|
+
*/
|
|
5
|
+
const statusEmitter = new EventEmitter();
|
|
6
|
+
// Increase the default listener limit to support many concurrent SSE connections.
|
|
7
|
+
statusEmitter.setMaxListeners(100);
|
|
8
|
+
/**
|
|
9
|
+
* Creates the initial StreamStatus object for a new stream. This provides a consistent starting state with all health metrics at their default values.
|
|
10
|
+
* @param options - The stream initialization options.
|
|
11
|
+
* @returns The initial stream status.
|
|
12
|
+
*/
|
|
13
|
+
export function createInitialStreamStatus(options) {
|
|
14
|
+
return {
|
|
15
|
+
bufferingDuration: null,
|
|
16
|
+
channel: options.channelName,
|
|
17
|
+
clientCount: 0,
|
|
18
|
+
clients: [],
|
|
19
|
+
currentTime: 0,
|
|
20
|
+
duration: 0,
|
|
21
|
+
escalationLevel: 0,
|
|
22
|
+
health: "healthy",
|
|
23
|
+
id: options.numericStreamId,
|
|
24
|
+
lastIssueTime: null,
|
|
25
|
+
lastIssueType: null,
|
|
26
|
+
lastRecoveryTime: null,
|
|
27
|
+
logoUrl: "",
|
|
28
|
+
memoryBytes: 0,
|
|
29
|
+
networkState: 0,
|
|
30
|
+
pageReloadsInWindow: 0,
|
|
31
|
+
providerName: options.providerName,
|
|
32
|
+
readyState: 0,
|
|
33
|
+
recoveryAttempts: 0,
|
|
34
|
+
showName: "",
|
|
35
|
+
startTime: options.startTime.toISOString(),
|
|
36
|
+
url: options.url
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
// Current status for all active streams, keyed by stream ID.
|
|
40
|
+
const streamStatuses = new Map();
|
|
41
|
+
// Cached system status, updated periodically and on significant events.
|
|
42
|
+
let cachedSystemStatus = null;
|
|
43
|
+
/**
|
|
44
|
+
* Emits a stream added event when a new stream starts.
|
|
45
|
+
* @param status - The initial status of the new stream.
|
|
46
|
+
*/
|
|
47
|
+
export function emitStreamAdded(status) {
|
|
48
|
+
streamStatuses.set(status.id, status);
|
|
49
|
+
statusEmitter.emit("streamAdded", status);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Emits a stream removed event when a stream ends.
|
|
53
|
+
* @param streamId - The ID of the stream that ended.
|
|
54
|
+
*/
|
|
55
|
+
export function emitStreamRemoved(streamId) {
|
|
56
|
+
streamStatuses.delete(streamId);
|
|
57
|
+
statusEmitter.emit("streamRemoved", { id: streamId });
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Emits a stream health changed event with the current stream status. This function always stores and emits the status to ensure SSE clients and snapshots have
|
|
61
|
+
* current data. During healthy playback the monitor calls this every ~2 seconds anyway, so removing the previous selective filter has negligible bandwidth impact
|
|
62
|
+
* while eliminating staleness during recovery/buffering periods.
|
|
63
|
+
* @param status - The updated stream status.
|
|
64
|
+
*/
|
|
65
|
+
export function emitStreamHealthChanged(status) {
|
|
66
|
+
streamStatuses.set(status.id, status);
|
|
67
|
+
statusEmitter.emit("streamHealthChanged", status);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Emits a system status changed event when browser or system state changes.
|
|
71
|
+
* @param status - The updated system status.
|
|
72
|
+
*/
|
|
73
|
+
export function emitSystemStatusChanged(status) {
|
|
74
|
+
// Only emit if something meaningful changed.
|
|
75
|
+
if ((cachedSystemStatus?.browser.connected !== status.browser.connected) ||
|
|
76
|
+
(cachedSystemStatus.streams.active !== status.streams.active)) {
|
|
77
|
+
cachedSystemStatus = status;
|
|
78
|
+
statusEmitter.emit("systemStatusChanged", status);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Updates the cached system status without emitting an event. Used for periodic updates that should be included in snapshots but don't need to notify clients.
|
|
83
|
+
* @param status - The updated system status.
|
|
84
|
+
*/
|
|
85
|
+
export function updateSystemStatus(status) {
|
|
86
|
+
cachedSystemStatus = status;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Gets the current status snapshot for all streams and the system.
|
|
90
|
+
* @returns The current status snapshot.
|
|
91
|
+
*/
|
|
92
|
+
export function getStatusSnapshot() {
|
|
93
|
+
return {
|
|
94
|
+
streams: Array.from(streamStatuses.values()),
|
|
95
|
+
system: cachedSystemStatus ?? {
|
|
96
|
+
browser: { connected: false, pageCount: 0 },
|
|
97
|
+
memory: { heapUsed: 0, rss: 0 },
|
|
98
|
+
streams: { active: 0, limit: 10 },
|
|
99
|
+
uptime: 0
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Gets the current status for a specific stream.
|
|
105
|
+
* @param streamId - The ID of the stream.
|
|
106
|
+
* @returns The stream status, or undefined if not found.
|
|
107
|
+
*/
|
|
108
|
+
export function getStreamStatus(streamId) {
|
|
109
|
+
return streamStatuses.get(streamId);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Removes a stream from the status tracking without emitting an event. Used during cleanup when the stream has already been removed.
|
|
113
|
+
* @param streamId - The ID of the stream to remove.
|
|
114
|
+
*/
|
|
115
|
+
export function removeStreamStatus(streamId) {
|
|
116
|
+
streamStatuses.delete(streamId);
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Subscribes a callback to receive all status events. Returns an unsubscribe function.
|
|
120
|
+
* @param callback - Function to call when a status event is emitted.
|
|
121
|
+
* @returns A function to unsubscribe the callback.
|
|
122
|
+
*/
|
|
123
|
+
export function subscribeToStatus(callback) {
|
|
124
|
+
const streamAddedHandler = (data) => { callback("streamAdded", data); };
|
|
125
|
+
const streamRemovedHandler = (data) => { callback("streamRemoved", data); };
|
|
126
|
+
const streamHealthChangedHandler = (data) => { callback("streamHealthChanged", data); };
|
|
127
|
+
const systemStatusChangedHandler = (data) => { callback("systemStatusChanged", data); };
|
|
128
|
+
statusEmitter.on("streamAdded", streamAddedHandler);
|
|
129
|
+
statusEmitter.on("streamRemoved", streamRemovedHandler);
|
|
130
|
+
statusEmitter.on("streamHealthChanged", streamHealthChangedHandler);
|
|
131
|
+
statusEmitter.on("systemStatusChanged", systemStatusChangedHandler);
|
|
132
|
+
return () => {
|
|
133
|
+
statusEmitter.off("streamAdded", streamAddedHandler);
|
|
134
|
+
statusEmitter.off("streamRemoved", streamRemovedHandler);
|
|
135
|
+
statusEmitter.off("streamHealthChanged", streamHealthChangedHandler);
|
|
136
|
+
statusEmitter.off("systemStatusChanged", systemStatusChangedHandler);
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=statusEmitter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"statusEmitter.js","sourceRoot":"","sources":["../../src/streaming/statusEmitter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
import type { Frame, Page } from "puppeteer-core";
|
|
2
|
+
import type { RecoveryMetrics } from "../streaming/monitor.js";
|
|
3
|
+
/**
|
|
4
|
+
* A utility type that represents a value that can be null.
|
|
5
|
+
* @typeParam T - The type that can be nullable.
|
|
6
|
+
*/
|
|
7
|
+
export type Nullable<T> = T | null;
|
|
8
|
+
/**
|
|
9
|
+
* Browser-related configuration controlling Chrome launch behavior. Viewport dimensions are derived from the quality preset via getViewport() and are not stored in
|
|
10
|
+
* this configuration object.
|
|
11
|
+
*/
|
|
12
|
+
export interface BrowserConfig {
|
|
13
|
+
executablePath: Nullable<string>;
|
|
14
|
+
initTimeout: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Filesystem paths for Chrome profile data and extension files.
|
|
18
|
+
*/
|
|
19
|
+
export interface PathsConfig {
|
|
20
|
+
chromeProfileName: string;
|
|
21
|
+
extensionDirName: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Playback monitoring and recovery timing configuration. These values control how quickly the system detects playback problems and how aggressively it attempts
|
|
25
|
+
* recovery. The defaults balance responsiveness against false positives from temporary buffering.
|
|
26
|
+
*/
|
|
27
|
+
export interface PlaybackConfig {
|
|
28
|
+
bufferingGracePeriod: number;
|
|
29
|
+
channelSelectorDelay: number;
|
|
30
|
+
channelSwitchDelay: number;
|
|
31
|
+
clickToPlayDelay: number;
|
|
32
|
+
iframeInitDelay: number;
|
|
33
|
+
maxPageReloads: number;
|
|
34
|
+
monitorInterval: number;
|
|
35
|
+
pageReloadWindow: number;
|
|
36
|
+
sourceReloadDelay: number;
|
|
37
|
+
stallCountThreshold: number;
|
|
38
|
+
stallThreshold: number;
|
|
39
|
+
sustainedPlaybackRequired: number;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Recovery behavior configuration controlling retry logic, backoff timing, and circuit breaker thresholds. These settings determine how the system handles
|
|
43
|
+
* failures and prevents runaway resource consumption from broken streams.
|
|
44
|
+
*/
|
|
45
|
+
export interface RecoveryConfig {
|
|
46
|
+
backoffJitter: number;
|
|
47
|
+
circuitBreakerThreshold: number;
|
|
48
|
+
circuitBreakerWindow: number;
|
|
49
|
+
maxBackoffDelay: number;
|
|
50
|
+
stalePageCleanupInterval: number;
|
|
51
|
+
stalePageGracePeriod: number;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* HLS streaming configuration controlling segment generation and lifecycle.
|
|
55
|
+
*/
|
|
56
|
+
export interface HLSConfig {
|
|
57
|
+
idleTimeout: number;
|
|
58
|
+
maxSegments: number;
|
|
59
|
+
segmentDuration: number;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Channels configuration controlling which predefined channels are enabled.
|
|
63
|
+
*/
|
|
64
|
+
export interface ChannelsConfig {
|
|
65
|
+
disabledPredefined: string[];
|
|
66
|
+
enabledProviders: string[];
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* HDHomeRun emulation configuration. When enabled, PrismCast runs a separate HTTP server that emulates the HDHomeRun API, allowing Plex to discover and use
|
|
70
|
+
* PrismCast as a virtual tuner for live TV and DVR recording. The emulated device appears in Plex's tuner setup and serves PrismCast's HLS streams directly.
|
|
71
|
+
*/
|
|
72
|
+
export interface HdhrConfig {
|
|
73
|
+
deviceId: string;
|
|
74
|
+
enabled: boolean;
|
|
75
|
+
friendlyName: string;
|
|
76
|
+
port: number;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Logging configuration controlling file-based logging behavior.
|
|
80
|
+
*/
|
|
81
|
+
export interface LoggingConfig {
|
|
82
|
+
httpLogLevel: "all" | "errors" | "filtered" | "none";
|
|
83
|
+
maxSize: number;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* HTTP server configuration controlling network binding.
|
|
87
|
+
*/
|
|
88
|
+
export interface ServerConfig {
|
|
89
|
+
host: string;
|
|
90
|
+
port: number;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Capture mode for media recording. Determines how video/audio is captured from the browser and processed for HLS output.
|
|
94
|
+
* - "ffmpeg": Captures WebM (H264+Opus) and uses FFmpeg to transcode audio to AAC. More stable for long recordings.
|
|
95
|
+
* - "native": Captures fMP4 (H264+AAC) directly from Chrome. No dependencies but may be unstable with long recordings.
|
|
96
|
+
*/
|
|
97
|
+
export type CaptureMode = "ffmpeg" | "native";
|
|
98
|
+
/**
|
|
99
|
+
* Media streaming configuration controlling video capture quality, timeouts, and concurrency limits.
|
|
100
|
+
*/
|
|
101
|
+
export interface StreamingConfig {
|
|
102
|
+
audioBitsPerSecond: number;
|
|
103
|
+
captureMode: CaptureMode;
|
|
104
|
+
frameRate: number;
|
|
105
|
+
maxConcurrentStreams: number;
|
|
106
|
+
maxNavigationRetries: number;
|
|
107
|
+
navigationTimeout: number;
|
|
108
|
+
qualityPreset: string;
|
|
109
|
+
videoBitsPerSecond: number;
|
|
110
|
+
videoTimeout: number;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Root configuration object containing all application settings organized by functional area.
|
|
114
|
+
*/
|
|
115
|
+
export interface Config {
|
|
116
|
+
browser: BrowserConfig;
|
|
117
|
+
channels: ChannelsConfig;
|
|
118
|
+
hdhr: HdhrConfig;
|
|
119
|
+
hls: HLSConfig;
|
|
120
|
+
logging: LoggingConfig;
|
|
121
|
+
paths: PathsConfig;
|
|
122
|
+
playback: PlaybackConfig;
|
|
123
|
+
recovery: RecoveryConfig;
|
|
124
|
+
server: ServerConfig;
|
|
125
|
+
streaming: StreamingConfig;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* UI category for profile grouping in dropdowns and reference documentation. Profiles are grouped by their fullscreen mechanism and special characteristics.
|
|
129
|
+
* - "api": Profiles using the JavaScript fullscreen API (including embedded iframe and click-to-play variants).
|
|
130
|
+
* - "keyboard": Profiles using keyboard shortcuts (typically the 'f' key) for fullscreen.
|
|
131
|
+
* - "multiChannel": Multi-channel profiles requiring a channel selector for tile or thumbnail-based channel selection.
|
|
132
|
+
* - "special": Special-purpose profiles like static page capture.
|
|
133
|
+
*/
|
|
134
|
+
export type ProfileCategory = "api" | "keyboard" | "multiChannel" | "special";
|
|
135
|
+
/**
|
|
136
|
+
* Site profile definition with optional flags. All flags are optional because profiles can inherit from other profiles, and only the flags that differ from the
|
|
137
|
+
* parent need to be specified. The DEFAULT_SITE_PROFILE provides baseline values for any flags not set through inheritance.
|
|
138
|
+
*/
|
|
139
|
+
export interface SiteProfile {
|
|
140
|
+
category?: ProfileCategory;
|
|
141
|
+
channelSelection?: ChannelSelectionConfig;
|
|
142
|
+
channelSelector?: Nullable<string>;
|
|
143
|
+
clickSelector?: Nullable<string>;
|
|
144
|
+
clickToPlay?: boolean;
|
|
145
|
+
description?: string;
|
|
146
|
+
extends?: string;
|
|
147
|
+
summary?: string;
|
|
148
|
+
fullscreenKey?: Nullable<string>;
|
|
149
|
+
fullscreenSelector?: Nullable<string>;
|
|
150
|
+
lockVolumeProperties?: boolean;
|
|
151
|
+
needsIframeHandling?: boolean;
|
|
152
|
+
noVideo?: boolean;
|
|
153
|
+
selectReadyVideo?: boolean;
|
|
154
|
+
useRequestFullscreen?: boolean;
|
|
155
|
+
waitForNetworkIdle?: boolean;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Fully-resolved site profile with all flags having concrete values. After resolving inheritance chains and applying defaults, every flag has a definite boolean
|
|
159
|
+
* or string value. This interface is used by stream handling code that needs to check profile flags without worrying about undefined values.
|
|
160
|
+
*/
|
|
161
|
+
export interface ResolvedSiteProfile {
|
|
162
|
+
channelSelection: ChannelSelectionConfig;
|
|
163
|
+
channelSelector: Nullable<string>;
|
|
164
|
+
clickSelector: Nullable<string>;
|
|
165
|
+
clickToPlay: boolean;
|
|
166
|
+
fullscreenKey: Nullable<string>;
|
|
167
|
+
fullscreenSelector: Nullable<string>;
|
|
168
|
+
lockVolumeProperties: boolean;
|
|
169
|
+
maxContinuousPlayback: Nullable<number>;
|
|
170
|
+
needsIframeHandling: boolean;
|
|
171
|
+
noVideo: boolean;
|
|
172
|
+
selectReadyVideo: boolean;
|
|
173
|
+
useRequestFullscreen: boolean;
|
|
174
|
+
waitForNetworkIdle: boolean;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Result of resolving a site profile. Includes both the resolved profile configuration and the name of the profile that was matched. The name indicates whether the
|
|
178
|
+
* profile came from a channel hint, domain-based autodetection, or the default fallback.
|
|
179
|
+
*/
|
|
180
|
+
export interface ProfileResolutionResult {
|
|
181
|
+
profile: ResolvedSiteProfile;
|
|
182
|
+
profileName: string;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Channel definition mapping a short name to a streaming URL with optional configuration overrides.
|
|
186
|
+
*/
|
|
187
|
+
export interface Channel {
|
|
188
|
+
channelNumber?: number;
|
|
189
|
+
channelSelector?: string;
|
|
190
|
+
name?: string;
|
|
191
|
+
profile?: string;
|
|
192
|
+
provider?: string;
|
|
193
|
+
stationId?: string;
|
|
194
|
+
url: string;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Enriched channel entry returned by getChannelListing(). Wraps a Channel definition with source classification and enabled status metadata, providing the
|
|
198
|
+
* single source of truth for merged channel data across the codebase.
|
|
199
|
+
*/
|
|
200
|
+
export interface ChannelListingEntry {
|
|
201
|
+
availableByProvider: boolean;
|
|
202
|
+
channel: Channel;
|
|
203
|
+
enabled: boolean;
|
|
204
|
+
key: string;
|
|
205
|
+
source: "override" | "predefined" | "user";
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Map of channel short names to channel definitions. Channel names must be URL-safe strings (lowercase letters, numbers, hyphens) since they appear in stream
|
|
209
|
+
* request URLs.
|
|
210
|
+
*/
|
|
211
|
+
export type ChannelMap = Record<string, Channel>;
|
|
212
|
+
/**
|
|
213
|
+
* Represents a group of provider variants for the same content. Used by the UI to display provider selection dropdowns for multi-provider channels.
|
|
214
|
+
*/
|
|
215
|
+
export interface ProviderGroup {
|
|
216
|
+
canonicalKey: string;
|
|
217
|
+
variants: {
|
|
218
|
+
key: string;
|
|
219
|
+
label: string;
|
|
220
|
+
}[];
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Information about an active streaming session. Created when a stream request is received and deleted when the stream ends.
|
|
224
|
+
*/
|
|
225
|
+
export interface StreamInfo {
|
|
226
|
+
channelName: Nullable<string>;
|
|
227
|
+
id: number;
|
|
228
|
+
page: Page;
|
|
229
|
+
startTime: Date;
|
|
230
|
+
stopMonitor: Nullable<() => RecoveryMetrics>;
|
|
231
|
+
url: string;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Snapshot of a video element's playback state. Collected by the playback health monitor to detect stalls, errors, and other problems.
|
|
235
|
+
*/
|
|
236
|
+
export interface VideoState {
|
|
237
|
+
currentTime: number;
|
|
238
|
+
ended: boolean;
|
|
239
|
+
error: boolean;
|
|
240
|
+
muted: boolean;
|
|
241
|
+
networkState: number;
|
|
242
|
+
paused: boolean;
|
|
243
|
+
readyState: number;
|
|
244
|
+
time: number;
|
|
245
|
+
volume: number;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Strategy for selecting a video element when multiple are present. "selectFirstVideo" takes the first video in DOM order; "selectReadyVideo" finds the video
|
|
249
|
+
* with readyState >= 3, which typically identifies the actively playing main content rather than preloaded ads.
|
|
250
|
+
*/
|
|
251
|
+
export type VideoSelectorType = "selectFirstVideo" | "selectReadyVideo";
|
|
252
|
+
/**
|
|
253
|
+
* Result of URL validation indicating whether the URL is safe to navigate to.
|
|
254
|
+
*/
|
|
255
|
+
export interface UrlValidationResult {
|
|
256
|
+
reason?: string;
|
|
257
|
+
valid: boolean;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Alias for UrlValidationResult maintained for backward compatibility with existing code.
|
|
261
|
+
*/
|
|
262
|
+
export type UrlValidation = UrlValidationResult;
|
|
263
|
+
/**
|
|
264
|
+
* Health check response structure returned by the /health endpoint.
|
|
265
|
+
*/
|
|
266
|
+
export interface HealthStatus {
|
|
267
|
+
browser: {
|
|
268
|
+
connected: boolean;
|
|
269
|
+
pageCount: number;
|
|
270
|
+
};
|
|
271
|
+
captureMode: string;
|
|
272
|
+
chrome: Nullable<string>;
|
|
273
|
+
clients: {
|
|
274
|
+
byType: {
|
|
275
|
+
count: number;
|
|
276
|
+
type: string;
|
|
277
|
+
}[];
|
|
278
|
+
total: number;
|
|
279
|
+
};
|
|
280
|
+
ffmpegAvailable: boolean;
|
|
281
|
+
memory: {
|
|
282
|
+
heapTotal: number;
|
|
283
|
+
heapUsed: number;
|
|
284
|
+
rss: number;
|
|
285
|
+
segmentBuffers: number;
|
|
286
|
+
};
|
|
287
|
+
message?: string;
|
|
288
|
+
status: "degraded" | "healthy" | "unhealthy";
|
|
289
|
+
streams: {
|
|
290
|
+
active: number;
|
|
291
|
+
limit: number;
|
|
292
|
+
};
|
|
293
|
+
timestamp: string;
|
|
294
|
+
uptime: number;
|
|
295
|
+
version: string;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Information about a single active stream as returned by the /streams endpoint.
|
|
299
|
+
*/
|
|
300
|
+
export interface StreamListItem {
|
|
301
|
+
channel: Nullable<string>;
|
|
302
|
+
duration: number;
|
|
303
|
+
id: number;
|
|
304
|
+
startTime: string;
|
|
305
|
+
url: string;
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Response structure for the /streams endpoint.
|
|
309
|
+
*/
|
|
310
|
+
export interface StreamListResponse {
|
|
311
|
+
count: number;
|
|
312
|
+
limit: number;
|
|
313
|
+
streams: StreamListItem[];
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Available channel selection strategies. Each strategy implements a different approach to finding and selecting channels in a multi-channel player UI.
|
|
317
|
+
*
|
|
318
|
+
* - "foxGrid": Find channel by station code in a non-virtualized guide grid, click the channel logo button via DOM .click(). Used by Fox.com.
|
|
319
|
+
* - "guideGrid": Find channel by exact-matching image alt text, click nearest clickable ancestor. Optionally clicks a tab to reveal the list first. Used by Hulu
|
|
320
|
+
* Live TV.
|
|
321
|
+
* - "hboGrid": Discover the HBO tab page URL from the homepage menu bar, scrape the live channel tile rail for a matching channel name, and navigate to the watch
|
|
322
|
+
* URL. Caches the tab URL across tunes with stale-cache fallback. Used by HBO Max.
|
|
323
|
+
* - "none": No channel selection needed (single-channel sites). This is the default.
|
|
324
|
+
* - "slingGrid": Find channel by data-testid in a virtualized A-Z guide grid, scroll via binary search on .guide-cell scrollTop, click the on-now program
|
|
325
|
+
* cell. Used by Sling TV.
|
|
326
|
+
* - "thumbnailRow": Find channel by matching image URL slug, click adjacent element on the same row. Used by USA Network.
|
|
327
|
+
* - "tileClick": Find channel tile by matching image URL slug, click tile, then click play button on modal. Used by Disney+ live channels.
|
|
328
|
+
* - "youtubeGrid": Find channel by aria-label in a non-virtualized EPG grid, extract the watch URL, and navigate directly. Used by YouTube TV.
|
|
329
|
+
*/
|
|
330
|
+
export type ChannelSelectionStrategy = "foxGrid" | "guideGrid" | "hboGrid" | "none" | "slingGrid" | "thumbnailRow" | "tileClick" | "youtubeGrid";
|
|
331
|
+
/**
|
|
332
|
+
* Configuration for channel selection behavior within a site profile.
|
|
333
|
+
*/
|
|
334
|
+
export interface ChannelSelectionConfig {
|
|
335
|
+
listSelector?: string;
|
|
336
|
+
playSelector?: string;
|
|
337
|
+
strategy: ChannelSelectionStrategy;
|
|
338
|
+
}
|
|
339
|
+
export interface ChannelSelectionProfile extends ResolvedSiteProfile {
|
|
340
|
+
channelSelector: string;
|
|
341
|
+
}
|
|
342
|
+
export declare function isChannelSelectionProfile(profile: ResolvedSiteProfile): profile is ChannelSelectionProfile;
|
|
343
|
+
/**
|
|
344
|
+
* Result of attempting to select a channel from a multi-channel player UI.
|
|
345
|
+
*/
|
|
346
|
+
export interface ChannelSelectorResult {
|
|
347
|
+
reason?: string;
|
|
348
|
+
success: boolean;
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* The strategy function signature. All strategies take the Puppeteer page and a narrowed profile with guaranteed non-null channelSelector.
|
|
352
|
+
*/
|
|
353
|
+
export type ChannelStrategyHandler = (page: Page, profile: ChannelSelectionProfile) => Promise<ChannelSelectorResult>;
|
|
354
|
+
/**
|
|
355
|
+
* The complete contract for a channel selection strategy. Each provider file exports a single object implementing this interface. The coordinator accesses all
|
|
356
|
+
* provider behavior through these hooks — no strategy-specific imports or hardcoded strategy name checks outside the registry.
|
|
357
|
+
*/
|
|
358
|
+
export interface ChannelStrategyEntry {
|
|
359
|
+
/**
|
|
360
|
+
* Resets all module-level caches (row positions, discovered URLs, watch URLs). Called on browser restart when cached state may be stale.
|
|
361
|
+
*/
|
|
362
|
+
clearCache?: () => void;
|
|
363
|
+
/**
|
|
364
|
+
* Selects the target channel in the provider's guide UI. Receives a Puppeteer page and a profile with a guaranteed non-null channelSelector. Must handle its
|
|
365
|
+
* own retry logic (e.g., overlay dismiss) and return a result indicating success or failure with a diagnostic reason.
|
|
366
|
+
*/
|
|
367
|
+
execute: ChannelStrategyHandler;
|
|
368
|
+
/**
|
|
369
|
+
* Removes a cached watch URL after it failed to produce a working stream. Called by the coordinator when a cached direct navigation fails.
|
|
370
|
+
*/
|
|
371
|
+
invalidateDirectUrl?: (channelSelector: string) => void;
|
|
372
|
+
/**
|
|
373
|
+
* Returns a watch URL for direct navigation, bypassing guide page loading. Implementations may perform async work such as fetching current asset IDs from
|
|
374
|
+
* provider APIs. The page parameter allows setting up response interception or accessing browser context when needed (e.g., cold cache setup).
|
|
375
|
+
*/
|
|
376
|
+
resolveDirectUrl?: (channelSelector: string, page: Page) => Promise<Nullable<string>>;
|
|
377
|
+
/**
|
|
378
|
+
* Set to true when the channelSelector is an image URL slug that must be polled for load completion before strategy dispatch. The coordinator waits for an img
|
|
379
|
+
* element whose src contains the slug to reach loaded state.
|
|
380
|
+
*/
|
|
381
|
+
usesImageSlug?: boolean;
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* Coordinates for a click target, used when clicking channel selector elements.
|
|
385
|
+
*/
|
|
386
|
+
export interface ClickTarget {
|
|
387
|
+
x: number;
|
|
388
|
+
y: number;
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Result of tuning to a channel, containing the video context needed for monitoring.
|
|
392
|
+
*/
|
|
393
|
+
export interface TuneResult {
|
|
394
|
+
context: Frame | Page;
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Browser chrome dimensions (toolbars, borders) calculated by comparing window.outerHeight/Width to window.innerHeight/Width. Used to set window size such that
|
|
398
|
+
* the viewport (content area) matches our target dimensions.
|
|
399
|
+
*/
|
|
400
|
+
export interface UiSize {
|
|
401
|
+
height: number;
|
|
402
|
+
width: number;
|
|
403
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// Type guard that proves channelSelector is a non-empty string. Matches the original !channelSelector truthiness check, which rejects both null and empty string.
|
|
2
|
+
// Used by the coordinator before dispatching to strategy functions.
|
|
3
|
+
export function isChannelSelectionProfile(profile) {
|
|
4
|
+
return (profile.channelSelector !== null) && (profile.channelSelector.length > 0);
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAwzBA,kKAAkK;AAClK,oEAAoE;AACpE,MAAM,UAAU,yBAAyB,CAAC,OAA4B;IAEpE,OAAO,CAAC,OAAO,CAAC,eAAe,KAAK,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACpF,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parses a comma-separated pattern string and configures the debug filter. Calling this function replaces any previous filter configuration.
|
|
3
|
+
* @param pattern - Comma-separated list of category patterns (e.g., "tuning:hulu,recovery,-streaming:ffmpeg").
|
|
4
|
+
*/
|
|
5
|
+
export declare function initDebugFilter(pattern: string): void;
|
|
6
|
+
/**
|
|
7
|
+
* Checks whether a specific debug category is enabled under the current filter configuration.
|
|
8
|
+
* @param category - The category to check (e.g., "tuning:hulu", "recovery:tab").
|
|
9
|
+
* @returns True if debug output should be produced for this category.
|
|
10
|
+
*/
|
|
11
|
+
export declare function isCategoryEnabled(category: string): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Fast-path check for whether any debug categories are configured. When this returns false, callers can skip category string construction entirely.
|
|
14
|
+
* @returns True if at least one debug category is enabled.
|
|
15
|
+
*/
|
|
16
|
+
export declare function isAnyDebugEnabled(): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Reconstructs the current filter pattern string from internal state. Returns an empty string when no debug output is configured.
|
|
19
|
+
* @returns The current pattern string (e.g., "*,-streaming:ffmpeg" or "tuning:hulu,recovery").
|
|
20
|
+
*/
|
|
21
|
+
export declare function getCurrentPattern(): string;
|
|
22
|
+
/**
|
|
23
|
+
* Metadata for a known debug category. Used by the /debug UI to display available categories with descriptions.
|
|
24
|
+
*/
|
|
25
|
+
export interface DebugCategory {
|
|
26
|
+
readonly category: string;
|
|
27
|
+
readonly description: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Static registry of all known debug categories with descriptions. Sorted alphabetically by category. The /debug endpoint uses this to render hierarchical checkboxes.
|
|
31
|
+
* Parent groups (e.g., "streaming", "timing", "tuning") are derived by the UI from the colon-separated namespaces — only leaf categories are declared here.
|
|
32
|
+
*/
|
|
33
|
+
export declare const DEBUG_CATEGORIES: readonly DebugCategory[];
|
|
34
|
+
/**
|
|
35
|
+
* Creates a lightweight elapsed-time closure using performance.now(). Call the returned function to get the elapsed milliseconds since creation.
|
|
36
|
+
* @returns A closure that returns elapsed milliseconds as a number.
|
|
37
|
+
*/
|
|
38
|
+
export declare function startTimer(): () => number;
|