prismcast 1.2.0 → 1.3.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.
- package/README.md +26 -1
- package/dist/app.js +29 -2
- package/dist/app.js.map +1 -1
- package/dist/browser/cdp.js +1 -1
- package/dist/browser/cdp.js.map +1 -1
- package/dist/browser/channelSelection.d.ts +14 -4
- package/dist/browser/channelSelection.js +48 -704
- package/dist/browser/channelSelection.js.map +1 -1
- package/dist/browser/index.d.ts +18 -4
- package/dist/browser/index.js +205 -39
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/tuning/fox.d.ts +19 -0
- package/dist/browser/tuning/fox.js +61 -0
- package/dist/browser/tuning/fox.js.map +1 -0
- package/dist/browser/tuning/hbo.d.ts +22 -0
- package/dist/browser/tuning/hbo.js +182 -0
- package/dist/browser/tuning/hbo.js.map +1 -0
- package/dist/browser/tuning/hulu.d.ts +30 -0
- package/dist/browser/tuning/hulu.js +514 -0
- package/dist/browser/tuning/hulu.js.map +1 -0
- package/dist/browser/tuning/sling.d.ts +22 -0
- package/dist/browser/tuning/sling.js +287 -0
- package/dist/browser/tuning/sling.js.map +1 -0
- package/dist/browser/tuning/thumbnailRow.d.ts +18 -0
- package/dist/browser/tuning/thumbnailRow.js +107 -0
- package/dist/browser/tuning/thumbnailRow.js.map +1 -0
- package/dist/browser/tuning/tileClick.d.ts +18 -0
- package/dist/browser/tuning/tileClick.js +102 -0
- package/dist/browser/tuning/tileClick.js.map +1 -0
- package/dist/browser/tuning/youtubeTv.d.ts +17 -0
- package/dist/browser/tuning/youtubeTv.js +99 -0
- package/dist/browser/tuning/youtubeTv.js.map +1 -0
- package/dist/browser/video.d.ts +2 -2
- package/dist/browser/video.js +18 -8
- package/dist/browser/video.js.map +1 -1
- package/dist/channels/index.js +131 -12
- package/dist/channels/index.js.map +1 -1
- package/dist/config/profiles.d.ts +5 -5
- package/dist/config/profiles.js +35 -11
- package/dist/config/profiles.js.map +1 -1
- package/dist/config/providers.d.ts +48 -4
- package/dist/config/providers.js +182 -22
- package/dist/config/providers.js.map +1 -1
- package/dist/config/sites.d.ts +10 -0
- package/dist/config/sites.js +96 -17
- package/dist/config/sites.js.map +1 -1
- package/dist/config/userChannels.js +21 -3
- package/dist/config/userChannels.js.map +1 -1
- package/dist/config/userConfig.d.ts +2 -1
- package/dist/config/userConfig.js +12 -4
- package/dist/config/userConfig.js.map +1 -1
- package/dist/index.js +10 -4
- package/dist/index.js.map +1 -1
- package/dist/routes/auth.js +6 -0
- package/dist/routes/auth.js.map +1 -1
- package/dist/routes/config.d.ts +5 -0
- package/dist/routes/config.js +273 -35
- package/dist/routes/config.js.map +1 -1
- 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/index.d.ts +1 -0
- package/dist/routes/index.js +3 -0
- package/dist/routes/index.js.map +1 -1
- package/dist/routes/logs.js +17 -5
- package/dist/routes/logs.js.map +1 -1
- package/dist/routes/root.js +507 -128
- package/dist/routes/root.js.map +1 -1
- package/dist/routes/theme.js +7 -0
- package/dist/routes/theme.js.map +1 -1
- package/dist/service/commands.js +8 -8
- package/dist/service/commands.js.map +1 -1
- package/dist/service/generators.js +22 -16
- package/dist/service/generators.js.map +1 -1
- package/dist/streaming/fmp4Segmenter.d.ts +7 -0
- package/dist/streaming/fmp4Segmenter.js +124 -15
- package/dist/streaming/fmp4Segmenter.js.map +1 -1
- package/dist/streaming/hls.d.ts +74 -6
- package/dist/streaming/hls.js +212 -130
- package/dist/streaming/hls.js.map +1 -1
- package/dist/streaming/hlsSegments.js +11 -4
- package/dist/streaming/hlsSegments.js.map +1 -1
- package/dist/streaming/lifecycle.js +1 -1
- package/dist/streaming/lifecycle.js.map +1 -1
- package/dist/streaming/monitor.d.ts +1 -1
- package/dist/streaming/monitor.js +202 -53
- package/dist/streaming/monitor.js.map +1 -1
- package/dist/streaming/mp4Parser.d.ts +29 -1
- package/dist/streaming/mp4Parser.js +243 -18
- package/dist/streaming/mp4Parser.js.map +1 -1
- package/dist/streaming/mpegts.d.ts +5 -2
- package/dist/streaming/mpegts.js +122 -29
- package/dist/streaming/mpegts.js.map +1 -1
- package/dist/streaming/registry.d.ts +1 -1
- package/dist/streaming/registry.js.map +1 -1
- package/dist/streaming/setup.d.ts +13 -1
- package/dist/streaming/setup.js +136 -36
- package/dist/streaming/setup.js.map +1 -1
- package/dist/streaming/showInfo.js +9 -9
- package/dist/streaming/showInfo.js.map +1 -1
- package/dist/streaming/statusEmitter.js +5 -6
- package/dist/streaming/statusEmitter.js.map +1 -1
- package/dist/types/index.d.ts +16 -3
- package/dist/types/index.js +5 -1
- package/dist/types/index.js.map +1 -1
- 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/evaluate.js.map +1 -1
- package/dist/utils/ffmpeg.d.ts +5 -0
- package/dist/utils/ffmpeg.js +13 -2
- package/dist/utils/ffmpeg.js.map +1 -1
- package/dist/utils/fileLogger.d.ts +2 -1
- package/dist/utils/fileLogger.js +4 -2
- package/dist/utils/fileLogger.js.map +1 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/logEmitter.d.ts +1 -0
- package/dist/utils/logEmitter.js.map +1 -1
- package/dist/utils/logger.d.ts +9 -8
- package/dist/utils/logger.js +52 -28
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/retry.d.ts +1 -1
- package/dist/utils/retry.js +3 -3
- package/dist/utils/retry.js.map +1 -1
- package/dist/utils/version.js +4 -9
- package/dist/utils/version.js.map +1 -1
- package/package.json +6 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channelSelection.js","sourceRoot":"","sources":["../../src/browser/channelSelection.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"channelSelection.js","sourceRoot":"","sources":["../../src/browser/channelSelection.ts"],"names":[],"mappings":"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"}
|
package/dist/browser/index.d.ts
CHANGED
|
@@ -51,9 +51,13 @@ export declare function getDataDir(): string;
|
|
|
51
51
|
*/
|
|
52
52
|
export declare function ensureDataDirectory(): Promise<void>;
|
|
53
53
|
/**
|
|
54
|
-
* Terminates any Chrome processes that are still using our profile directory from previous runs
|
|
55
|
-
* previous instance crashed without releasing the lock, we cannot launch a new browser with the same profile. This function
|
|
56
|
-
* Chrome processes whose command line contains our profile directory path
|
|
54
|
+
* Terminates any Chrome processes that are still using our profile directory from previous runs and waits for them to fully exit. Chrome locks its profile
|
|
55
|
+
* directory while running, and if a previous instance crashed without releasing the lock, we cannot launch a new browser with the same profile. This function
|
|
56
|
+
* uses pkill to find and terminate any Chrome processes whose command line contains our profile directory path, then polls pgrep to verify the processes have
|
|
57
|
+
* actually exited before returning.
|
|
58
|
+
*
|
|
59
|
+
* Waiting for exit is critical during service restarts. Without it, the new Chrome can launch while the old one is still releasing its profile lock and
|
|
60
|
+
* tabCapture extension state, causing stale capture errors that cascade into startup failures.
|
|
57
61
|
*
|
|
58
62
|
* This is called at startup before launching the browser to ensure a clean slate. It's safe to call even when no stale processes exist - pkill returns a non-zero
|
|
59
63
|
* exit code when no processes match, which we ignore.
|
|
@@ -82,8 +86,8 @@ export declare function buildLaunchOptions(): LaunchOptions;
|
|
|
82
86
|
*
|
|
83
87
|
* - Returning the existing browser if it's still connected
|
|
84
88
|
* - Launching a new browser if none exists or the previous one disconnected
|
|
89
|
+
* - Serializing concurrent callers so only one launch occurs at a time
|
|
85
90
|
* - Waiting for the puppeteer-stream extension to initialize
|
|
86
|
-
* - Minimizing the browser window to reduce GPU usage
|
|
87
91
|
* - Setting up disconnect handlers for crash recovery
|
|
88
92
|
* @returns The browser instance.
|
|
89
93
|
* @throws If the browser cannot be launched.
|
|
@@ -177,6 +181,16 @@ export declare function startStalePageCleanup(): void;
|
|
|
177
181
|
* the browser and streams.
|
|
178
182
|
*/
|
|
179
183
|
export declare function stopStalePageCleanup(): void;
|
|
184
|
+
/**
|
|
185
|
+
* Starts the periodic browser restart eligibility check. This should be called once during server startup, after the browser is initialized. The interval runs
|
|
186
|
+
* indefinitely until stopBrowserRestartChecking() is called (typically during graceful shutdown).
|
|
187
|
+
*/
|
|
188
|
+
export declare function startBrowserRestartChecking(): void;
|
|
189
|
+
/**
|
|
190
|
+
* Stops the browser restart checking interval and cancels any pending quiet timer. This should be called during graceful shutdown to prevent a restart from
|
|
191
|
+
* racing with server shutdown.
|
|
192
|
+
*/
|
|
193
|
+
export declare function stopBrowserRestartChecking(): void;
|
|
180
194
|
/**
|
|
181
195
|
* Extracts the Puppeteer Stream extension files when running as a packaged executable. This copies the extension files from within the packaged binary to the
|
|
182
196
|
* filesystem where Chrome can load them.
|
package/dist/browser/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { LOG, evaluateWithAbort, formatError } from "../utils/index.js";
|
|
1
|
+
import { LOG, evaluateWithAbort, formatError, startTimer } from "../utils/index.js";
|
|
2
2
|
import { getAllStreams, getStreamCount } from "../streaming/registry.js";
|
|
3
3
|
import { getEffectivePreset, getPresetViewport } from "../config/presets.js";
|
|
4
4
|
import { getExtensionPage, getStream, launch } from "puppeteer-stream";
|
|
5
5
|
import { resizeAndMinimizeWindow, unminimizeWindow } from "./cdp.js";
|
|
6
6
|
import { setBrowserChrome, setMaxSupportedViewport } from "./display.js";
|
|
7
7
|
import { CONFIG } from "../config/index.js";
|
|
8
|
-
import {
|
|
8
|
+
import { clearChannelSelectionCaches } from "./channelSelection.js";
|
|
9
9
|
import { emitSystemStatusChanged } from "../streaming/statusEmitter.js";
|
|
10
10
|
import { execSync } from "node:child_process";
|
|
11
11
|
import fs from "node:fs";
|
|
@@ -31,12 +31,33 @@ let currentBrowser = null;
|
|
|
31
31
|
// The Chrome version string (e.g., "Chrome/144.0.7559.110") captured when the browser launches. Cleared when the browser disconnects. Used by the
|
|
32
32
|
// health endpoint to report the active Chrome version.
|
|
33
33
|
let currentChromeVersion = null;
|
|
34
|
+
// Timestamp (Date.now()) when the current browser instance was launched. Used by the opportunistic restart check to determine browser age. Cleared when the
|
|
35
|
+
// browser disconnects.
|
|
36
|
+
let browserLaunchTime = null;
|
|
37
|
+
// Launch mutex. When a browser launch is in progress, this holds the pending promise so that concurrent callers piggyback on the same launch instead of
|
|
38
|
+
// starting a second Chrome process. Cleared in a finally block once the launch settles.
|
|
39
|
+
let browserLaunchPromise = null;
|
|
34
40
|
// The data directory stores Chrome's profile data and the streaming extension files. This is always ~/.prismcast, which provides a consistent location for
|
|
35
41
|
// user-specific data regardless of how PrismCast is run.
|
|
36
42
|
const dataDir = path.join(os.homedir(), ".prismcast");
|
|
37
43
|
// The stale page cleanup interval handle, stored so we can clear it during graceful shutdown. The interval periodically checks for browser pages that are not
|
|
38
44
|
// associated with active streams and closes them to prevent resource exhaustion.
|
|
39
45
|
let stalePageCleanupInterval = null;
|
|
46
|
+
/* Opportunistic browser restart state. Chrome accumulates memory pressure, GPU process issues, and general flakiness over multi-hour sessions with continuous
|
|
47
|
+
* media playback. We proactively restart Chrome after it has been running for BROWSER_MAX_AGE, waiting for a quiet period with zero active streams before
|
|
48
|
+
* executing the restart. After the restart, a fresh browser is launched immediately so it is ready for the next stream request.
|
|
49
|
+
*/
|
|
50
|
+
// Maximum browser uptime before considering a restart (6 hours).
|
|
51
|
+
const BROWSER_MAX_AGE = 6 * 60 * 60 * 1000;
|
|
52
|
+
// Duration of the quiet period (zero streams) required before executing the restart (5 minutes).
|
|
53
|
+
const BROWSER_RESTART_QUIET_PERIOD = 5 * 60 * 1000;
|
|
54
|
+
// How often to check whether the browser qualifies for a restart (30 seconds).
|
|
55
|
+
const BROWSER_RESTART_CHECK_INTERVAL = 30_000;
|
|
56
|
+
// Timer handle for the quiet period countdown. When set, the browser has exceeded BROWSER_MAX_AGE and we are waiting for BROWSER_RESTART_QUIET_PERIOD to
|
|
57
|
+
// elapse with zero active streams. Cancelled if a stream starts during the quiet period.
|
|
58
|
+
let restartQuietTimer = null;
|
|
59
|
+
// Interval handle for the periodic restart eligibility check.
|
|
60
|
+
let restartCheckInterval = null;
|
|
40
61
|
// Flag indicating that the browser is being closed intentionally via closeBrowser(). When true, the disconnect handler skips error logging and stream termination
|
|
41
62
|
// since these are handled by the shutdown code path. This prevents false "unexpected disconnect" errors during graceful shutdown.
|
|
42
63
|
let gracefulShutdownInProgress = false;
|
|
@@ -96,7 +117,7 @@ const LOGIN_TIMEOUT_MS = 15 * 60 * 1000;
|
|
|
96
117
|
export async function emitCurrentSystemStatus() {
|
|
97
118
|
let pageCount = 0;
|
|
98
119
|
try {
|
|
99
|
-
if (currentBrowser
|
|
120
|
+
if (currentBrowser?.connected) {
|
|
100
121
|
const pages = await currentBrowser.pages();
|
|
101
122
|
pageCount = pages.length;
|
|
102
123
|
}
|
|
@@ -107,7 +128,7 @@ export async function emitCurrentSystemStatus() {
|
|
|
107
128
|
const memUsage = process.memoryUsage();
|
|
108
129
|
const status = {
|
|
109
130
|
browser: {
|
|
110
|
-
connected: !!currentBrowser && currentBrowser.
|
|
131
|
+
connected: !!currentBrowser && currentBrowser.connected,
|
|
111
132
|
pageCount
|
|
112
133
|
},
|
|
113
134
|
memory: {
|
|
@@ -178,7 +199,7 @@ export function getDataDir() {
|
|
|
178
199
|
export async function ensureDataDirectory() {
|
|
179
200
|
try {
|
|
180
201
|
await fsPromises.mkdir(dataDir, { recursive: true });
|
|
181
|
-
LOG.
|
|
202
|
+
LOG.debug("browser", "Data directory ready: %s.", dataDir);
|
|
182
203
|
}
|
|
183
204
|
catch (error) {
|
|
184
205
|
LOG.error("Failed to create data directory %s: %s.", dataDir, formatError(error));
|
|
@@ -200,9 +221,13 @@ export async function ensureDataDirectory() {
|
|
|
200
221
|
* attempting to capture streams.
|
|
201
222
|
*/
|
|
202
223
|
/**
|
|
203
|
-
* Terminates any Chrome processes that are still using our profile directory from previous runs
|
|
204
|
-
* previous instance crashed without releasing the lock, we cannot launch a new browser with the same profile. This function
|
|
205
|
-
* Chrome processes whose command line contains our profile directory path
|
|
224
|
+
* Terminates any Chrome processes that are still using our profile directory from previous runs and waits for them to fully exit. Chrome locks its profile
|
|
225
|
+
* directory while running, and if a previous instance crashed without releasing the lock, we cannot launch a new browser with the same profile. This function
|
|
226
|
+
* uses pkill to find and terminate any Chrome processes whose command line contains our profile directory path, then polls pgrep to verify the processes have
|
|
227
|
+
* actually exited before returning.
|
|
228
|
+
*
|
|
229
|
+
* Waiting for exit is critical during service restarts. Without it, the new Chrome can launch while the old one is still releasing its profile lock and
|
|
230
|
+
* tabCapture extension state, causing stale capture errors that cascade into startup failures.
|
|
206
231
|
*
|
|
207
232
|
* This is called at startup before launching the browser to ensure a clean slate. It's safe to call even when no stale processes exist - pkill returns a non-zero
|
|
208
233
|
* exit code when no processes match, which we ignore.
|
|
@@ -214,12 +239,30 @@ export function killStaleChrome() {
|
|
|
214
239
|
// Use pkill with -f to match against the full command line, not just the process name. This finds Chrome processes that were launched with our profile
|
|
215
240
|
// directory. The command is wrapped in quotes to handle paths with spaces.
|
|
216
241
|
execSync(["pkill -f \"", profileDir, "\""].join(""));
|
|
217
|
-
LOG.
|
|
242
|
+
LOG.debug("browser", "Killed stale Chrome instances using %s.", profileDir);
|
|
218
243
|
}
|
|
219
244
|
catch (_error) {
|
|
220
245
|
// When pkill finds no matching processes, it returns a non-zero exit code. This is expected when there are no stale processes from a clean shutdown. We
|
|
221
|
-
// silently ignore this expected case.
|
|
246
|
+
// silently ignore this expected case and skip the wait-for-exit polling below.
|
|
247
|
+
return;
|
|
222
248
|
}
|
|
249
|
+
// Poll until the killed processes have fully exited. pgrep returns exit code 0 when matching processes exist and non-zero when none remain. We poll every
|
|
250
|
+
// 200ms for up to 5 seconds. This ensures Chrome has released its profile directory lock and tabCapture extension state before we launch a new instance.
|
|
251
|
+
const maxWaitMs = 5000;
|
|
252
|
+
const pollIntervalMs = 200;
|
|
253
|
+
const deadline = Date.now() + maxWaitMs;
|
|
254
|
+
while (Date.now() < deadline) {
|
|
255
|
+
try {
|
|
256
|
+
execSync(["pgrep -f \"", profileDir, "\""].join(""), { stdio: "ignore" });
|
|
257
|
+
// Processes still exist. Wait and check again.
|
|
258
|
+
execSync(["sleep ", String(pollIntervalMs / 1000)].join(""));
|
|
259
|
+
}
|
|
260
|
+
catch (_error) {
|
|
261
|
+
// pgrep returned non-zero — no matching processes remain. Chrome has fully exited.
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
LOG.warn("Stale Chrome processes did not exit within %sms. Proceeding anyway.", maxWaitMs);
|
|
223
266
|
}
|
|
224
267
|
/**
|
|
225
268
|
* Locates the Google Chrome executable on the system. The CHROME_BIN environment variable takes precedence, allowing operators to specify a non-standard
|
|
@@ -415,7 +458,7 @@ async function detectDisplayDimensions(browser) {
|
|
|
415
458
|
// Cache the results for use by the preset system and window sizing.
|
|
416
459
|
setBrowserChrome(dimensions.chromeWidth, dimensions.chromeHeight);
|
|
417
460
|
setMaxSupportedViewport(maxWidth, maxHeight);
|
|
418
|
-
LOG.debug("Display detection complete: screen %s\u00d7%s, chrome %s\u00d7%s, max viewport %s\u00d7%s.", dimensions.availWidth, dimensions.availHeight, dimensions.chromeWidth, dimensions.chromeHeight, maxWidth, maxHeight);
|
|
461
|
+
LOG.debug("browser", "Display detection complete: screen %s\u00d7%s, chrome %s\u00d7%s, max viewport %s\u00d7%s.", dimensions.availWidth, dimensions.availHeight, dimensions.chromeWidth, dimensions.chromeHeight, maxWidth, maxHeight);
|
|
419
462
|
// Check if the configured preset needs to be degraded and warn the user.
|
|
420
463
|
const presetResult = getEffectivePreset(CONFIG);
|
|
421
464
|
if (presetResult.degraded && presetResult.maxViewport) {
|
|
@@ -450,11 +493,17 @@ async function detectDisplayDimensions(browser) {
|
|
|
450
493
|
* This ensures streams fail gracefully rather than hanging indefinitely trying to use closed pages.
|
|
451
494
|
*/
|
|
452
495
|
function handleBrowserDisconnect() {
|
|
453
|
-
// Clear the browser reference and cached version so getCurrentBrowser() will launch a new instance on the next call.
|
|
496
|
+
// Clear the browser reference, launch timestamp, and cached version so getCurrentBrowser() will launch a new instance on the next call.
|
|
454
497
|
currentBrowser = null;
|
|
498
|
+
browserLaunchTime = null;
|
|
455
499
|
currentChromeVersion = null;
|
|
456
|
-
//
|
|
457
|
-
|
|
500
|
+
// Cancel any pending restart quiet timer since the browser is already gone.
|
|
501
|
+
if (restartQuietTimer) {
|
|
502
|
+
clearTimeout(restartQuietTimer);
|
|
503
|
+
restartQuietTimer = null;
|
|
504
|
+
}
|
|
505
|
+
// Clear all channel selection caches. Cached state (guide row positions, discovered page URLs) may be stale in a new browser session.
|
|
506
|
+
clearChannelSelectionCaches();
|
|
458
507
|
// Clear login state if login mode was active. We clear directly rather than calling endLoginMode() because the browser is already gone and we don't want to
|
|
459
508
|
// attempt any browser operations.
|
|
460
509
|
if (loginModeActive) {
|
|
@@ -490,19 +539,41 @@ function handleBrowserDisconnect() {
|
|
|
490
539
|
*
|
|
491
540
|
* - Returning the existing browser if it's still connected
|
|
492
541
|
* - Launching a new browser if none exists or the previous one disconnected
|
|
542
|
+
* - Serializing concurrent callers so only one launch occurs at a time
|
|
493
543
|
* - Waiting for the puppeteer-stream extension to initialize
|
|
494
|
-
* - Minimizing the browser window to reduce GPU usage
|
|
495
544
|
* - Setting up disconnect handlers for crash recovery
|
|
496
545
|
* @returns The browser instance.
|
|
497
546
|
* @throws If the browser cannot be launched.
|
|
498
547
|
*/
|
|
499
548
|
export async function getCurrentBrowser() {
|
|
500
|
-
// Fast path: if we have a browser and it's still connected, return it immediately. The
|
|
549
|
+
// Fast path: if we have a browser and it's still connected, return it immediately. The connected property verifies the DevTools Protocol connection is
|
|
501
550
|
// still alive.
|
|
502
|
-
if (currentBrowser
|
|
551
|
+
if (currentBrowser?.connected) {
|
|
503
552
|
return currentBrowser;
|
|
504
553
|
}
|
|
505
|
-
//
|
|
554
|
+
// If a launch is already in progress (e.g., from the restart path or a concurrent stream request), piggyback on that promise instead of starting a second
|
|
555
|
+
// Chrome process. Two concurrent launches with the same profile directory would contend on Chrome's profile lock.
|
|
556
|
+
if (browserLaunchPromise) {
|
|
557
|
+
return browserLaunchPromise;
|
|
558
|
+
}
|
|
559
|
+
// We need to launch a new browser. Store the promise so concurrent callers can piggyback on this launch.
|
|
560
|
+
browserLaunchPromise = launchBrowser();
|
|
561
|
+
try {
|
|
562
|
+
return await browserLaunchPromise;
|
|
563
|
+
}
|
|
564
|
+
finally {
|
|
565
|
+
browserLaunchPromise = null;
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
/**
|
|
569
|
+
* Launches a new browser instance and performs post-launch initialization (extension readiness, display detection, version capture). This is the inner launch
|
|
570
|
+
* function called by getCurrentBrowser() and serialized by the browserLaunchPromise mutex.
|
|
571
|
+
* @returns The browser instance.
|
|
572
|
+
* @throws If the browser cannot be launched.
|
|
573
|
+
*/
|
|
574
|
+
async function launchBrowser() {
|
|
575
|
+
const browserElapsed = startTimer();
|
|
576
|
+
// This happens on first stream request, after a browser crash, during server warmup, or during an opportunistic restart.
|
|
506
577
|
try {
|
|
507
578
|
const options = buildLaunchOptions();
|
|
508
579
|
// The launch function from puppeteer-stream wraps standard Puppeteer launch to inject the streaming extension. We pass our custom launch function that
|
|
@@ -510,6 +581,7 @@ export async function getCurrentBrowser() {
|
|
|
510
581
|
currentBrowser = await launch({ launch: launchWithCustomArgs }, options);
|
|
511
582
|
// Register a handler for browser disconnection. This ensures we clean up properly if the browser crashes or is closed unexpectedly.
|
|
512
583
|
currentBrowser.on("disconnected", handleBrowserDisconnect);
|
|
584
|
+
LOG.debug("timing:browser", "Chrome process spawned. (+%sms)", browserElapsed());
|
|
513
585
|
// Poll for the puppeteer-stream extension to finish initializing. The extension injects a START_RECORDING function into its options page context. We poll
|
|
514
586
|
// for this function's existence rather than using a fixed delay, so the browser is ready as soon as the extension loads — typically 200-500ms rather than the
|
|
515
587
|
// full configured timeout. Uses getExtensionPage() from puppeteer-stream to locate the extension's options page.
|
|
@@ -522,24 +594,26 @@ export async function getCurrentBrowser() {
|
|
|
522
594
|
// assertExtensionLoaded() in puppeteer-stream will retry before each capture attempt, so this isn't fatal.
|
|
523
595
|
LOG.warn("Extension did not initialize within %d ms. Streams may need additional time to start.", CONFIG.browser.initTimeout);
|
|
524
596
|
}
|
|
597
|
+
LOG.debug("timing:browser", "Extension initialized. (+%sms)", browserElapsed());
|
|
525
598
|
// Detect display dimensions to determine maximum supported viewport. This must happen before we start streaming so the preset system can degrade to a
|
|
526
599
|
// smaller preset if needed.
|
|
527
600
|
await detectDisplayDimensions(currentBrowser);
|
|
528
|
-
|
|
529
|
-
// it reduces resource consumption. CDP allows us to control window state without affecting capture.
|
|
530
|
-
await minimizeBrowserWindow();
|
|
601
|
+
LOG.debug("timing:browser", "Display detection complete. (+%sms)", browserElapsed());
|
|
531
602
|
// Log the Chrome version for diagnostic reference. This helps correlate browser behavior changes (tab unresponsiveness, memory pressure, capture issues)
|
|
532
603
|
// with specific Chrome releases.
|
|
533
604
|
const chromeVersion = await currentBrowser.version();
|
|
605
|
+
browserLaunchTime = Date.now();
|
|
534
606
|
currentChromeVersion = chromeVersion;
|
|
535
607
|
LOG.info("Chrome ready: %s.", chromeVersion);
|
|
608
|
+
LOG.debug("timing:browser", "Browser ready. Total: %sms.", browserElapsed());
|
|
536
609
|
// Emit system status update for SSE subscribers.
|
|
537
610
|
await emitCurrentSystemStatus();
|
|
538
611
|
}
|
|
539
612
|
catch (error) {
|
|
540
613
|
LOG.error("Failed to launch browser: %s.", formatError(error));
|
|
541
|
-
// Clear the browser reference and cached version on failure so the next call will attempt to launch again.
|
|
614
|
+
// Clear the browser reference, launch timestamp, and cached version on failure so the next call will attempt to launch again.
|
|
542
615
|
currentBrowser = null;
|
|
616
|
+
browserLaunchTime = null;
|
|
543
617
|
currentChromeVersion = null;
|
|
544
618
|
throw error;
|
|
545
619
|
}
|
|
@@ -557,7 +631,7 @@ export function getChromeVersion() {
|
|
|
557
631
|
* @returns True if the browser is connected and ready for use, false otherwise.
|
|
558
632
|
*/
|
|
559
633
|
export function isBrowserConnected() {
|
|
560
|
-
return !!currentBrowser && currentBrowser.
|
|
634
|
+
return !!currentBrowser && currentBrowser.connected;
|
|
561
635
|
}
|
|
562
636
|
/**
|
|
563
637
|
* Resizes the browser window to the effective viewport and minimizes it. This function combines viewport sizing with minimization to ensure the window is
|
|
@@ -569,7 +643,7 @@ export function isBrowserConnected() {
|
|
|
569
643
|
*/
|
|
570
644
|
export async function minimizeBrowserWindow() {
|
|
571
645
|
// Guard against calling this when no browser is running.
|
|
572
|
-
if (!currentBrowser
|
|
646
|
+
if (!currentBrowser?.connected) {
|
|
573
647
|
return;
|
|
574
648
|
}
|
|
575
649
|
let tempPage = null;
|
|
@@ -607,7 +681,7 @@ export async function minimizeBrowserWindow() {
|
|
|
607
681
|
}
|
|
608
682
|
}
|
|
609
683
|
// Resizing/minimizing is not critical - log a warning but don't fail the operation.
|
|
610
|
-
LOG.
|
|
684
|
+
LOG.debug("browser", "Could not resize and minimize browser window: %s.", formatError(error));
|
|
611
685
|
}
|
|
612
686
|
}
|
|
613
687
|
/**
|
|
@@ -616,7 +690,7 @@ export async function minimizeBrowserWindow() {
|
|
|
616
690
|
*/
|
|
617
691
|
export async function getBrowserPages() {
|
|
618
692
|
// Guard against calling this when no browser is running.
|
|
619
|
-
if (!currentBrowser
|
|
693
|
+
if (!currentBrowser?.connected) {
|
|
620
694
|
return [];
|
|
621
695
|
}
|
|
622
696
|
try {
|
|
@@ -641,19 +715,20 @@ export async function closeBrowser() {
|
|
|
641
715
|
// calls to closeBrowser().
|
|
642
716
|
setGracefulShutdown(true);
|
|
643
717
|
const browserRef = currentBrowser;
|
|
644
|
-
// Clear the reference and cached version early to prevent any new operations from using it.
|
|
718
|
+
// Clear the reference, launch timestamp, and cached version early to prevent any new operations from using it.
|
|
645
719
|
currentBrowser = null;
|
|
720
|
+
browserLaunchTime = null;
|
|
646
721
|
currentChromeVersion = null;
|
|
647
722
|
if (!browserRef) {
|
|
648
723
|
return;
|
|
649
724
|
}
|
|
650
725
|
// Stage 1: Try graceful close with a timeout. We use Promise.race to avoid hanging indefinitely if Chrome is unresponsive.
|
|
651
726
|
let closedGracefully = false;
|
|
652
|
-
if (browserRef.
|
|
727
|
+
if (browserRef.connected) {
|
|
653
728
|
try {
|
|
654
729
|
await Promise.race([
|
|
655
730
|
browserRef.close(),
|
|
656
|
-
new Promise((_, reject) => setTimeout(() => reject(new Error("Browser close timed out")), 5000))
|
|
731
|
+
new Promise((_, reject) => setTimeout(() => { reject(new Error("Browser close timed out")); }, 5000))
|
|
657
732
|
]);
|
|
658
733
|
closedGracefully = true;
|
|
659
734
|
}
|
|
@@ -663,7 +738,7 @@ export async function closeBrowser() {
|
|
|
663
738
|
LOG.warn("Browser did not close within 5 seconds. Forcing termination.");
|
|
664
739
|
}
|
|
665
740
|
else {
|
|
666
|
-
LOG.debug("Browser close error: %s.", message);
|
|
741
|
+
LOG.debug("browser", "Browser close error: %s.", message);
|
|
667
742
|
}
|
|
668
743
|
}
|
|
669
744
|
}
|
|
@@ -676,11 +751,11 @@ export async function closeBrowser() {
|
|
|
676
751
|
const browserProcess = browserRef.process();
|
|
677
752
|
if (browserProcess && !browserProcess.killed) {
|
|
678
753
|
browserProcess.kill("SIGKILL");
|
|
679
|
-
LOG.debug("Sent SIGKILL to browser process.");
|
|
754
|
+
LOG.debug("browser", "Sent SIGKILL to browser process.");
|
|
680
755
|
}
|
|
681
756
|
}
|
|
682
757
|
catch (error) {
|
|
683
|
-
LOG.debug("Browser process kill error: %s.", formatError(error));
|
|
758
|
+
LOG.debug("browser", "Browser process kill error: %s.", formatError(error));
|
|
684
759
|
}
|
|
685
760
|
}
|
|
686
761
|
// Stage 3: As a final fallback, use pkill to ensure no Chrome processes using our profile remain.
|
|
@@ -710,7 +785,7 @@ export async function startLoginMode(url) {
|
|
|
710
785
|
return { error: "Login is already in progress.", success: false };
|
|
711
786
|
}
|
|
712
787
|
// Ensure browser is available.
|
|
713
|
-
if (!currentBrowser
|
|
788
|
+
if (!currentBrowser?.connected) {
|
|
714
789
|
return { error: "Browser is not connected.", success: false };
|
|
715
790
|
}
|
|
716
791
|
try {
|
|
@@ -787,7 +862,7 @@ export async function endLoginMode() {
|
|
|
787
862
|
loginUrl = null;
|
|
788
863
|
loginStartTime = null;
|
|
789
864
|
// Re-minimize the browser window.
|
|
790
|
-
if (wasActive && currentBrowser
|
|
865
|
+
if (wasActive && currentBrowser?.connected) {
|
|
791
866
|
await minimizeBrowserWindow();
|
|
792
867
|
}
|
|
793
868
|
if (wasActive) {
|
|
@@ -840,7 +915,7 @@ export function getLoginStatus() {
|
|
|
840
915
|
*/
|
|
841
916
|
export async function cleanupStalePages() {
|
|
842
917
|
// Guard against calling this when no browser is running.
|
|
843
|
-
if (!currentBrowser
|
|
918
|
+
if (!currentBrowser?.connected) {
|
|
844
919
|
return;
|
|
845
920
|
}
|
|
846
921
|
try {
|
|
@@ -919,12 +994,12 @@ export async function cleanupStalePages() {
|
|
|
919
994
|
}
|
|
920
995
|
// Log only if we actually closed something, to avoid log spam from idle cleanup runs.
|
|
921
996
|
if (closedCount > 0) {
|
|
922
|
-
LOG.
|
|
997
|
+
LOG.debug("browser", "Cleaned up %s stale page(s).", closedCount);
|
|
923
998
|
}
|
|
924
999
|
}
|
|
925
1000
|
catch (error) {
|
|
926
1001
|
// Cleanup failure is not critical - log a warning and try again next interval.
|
|
927
|
-
LOG.
|
|
1002
|
+
LOG.debug("browser", "Stale page cleanup failed: %s.", formatError(error));
|
|
928
1003
|
}
|
|
929
1004
|
}
|
|
930
1005
|
/**
|
|
@@ -932,7 +1007,7 @@ export async function cleanupStalePages() {
|
|
|
932
1007
|
* indefinitely until stopStalePageCleanup() is called (typically during graceful shutdown).
|
|
933
1008
|
*/
|
|
934
1009
|
export function startStalePageCleanup() {
|
|
935
|
-
stalePageCleanupInterval = setInterval(cleanupStalePages, CONFIG.recovery.stalePageCleanupInterval);
|
|
1010
|
+
stalePageCleanupInterval = setInterval(() => { void cleanupStalePages(); }, CONFIG.recovery.stalePageCleanupInterval);
|
|
936
1011
|
}
|
|
937
1012
|
/**
|
|
938
1013
|
* Stops the stale page cleanup interval. This should be called during graceful shutdown to prevent the cleanup from running after we've started shutting down
|
|
@@ -944,6 +1019,97 @@ export function stopStalePageCleanup() {
|
|
|
944
1019
|
stalePageCleanupInterval = null;
|
|
945
1020
|
}
|
|
946
1021
|
}
|
|
1022
|
+
/* Opportunistic browser restart functions. The check runs on a 30-second interval and, when the browser exceeds BROWSER_MAX_AGE with zero active streams, starts
|
|
1023
|
+
* a quiet period timer. The quiet timer is cancelled if a stream starts, ensuring active viewers are never disrupted. When the timer expires, the browser is
|
|
1024
|
+
* closed and immediately re-launched.
|
|
1025
|
+
*/
|
|
1026
|
+
/**
|
|
1027
|
+
* Checks whether the browser qualifies for an opportunistic restart. Called periodically by the restart check interval. The check skips when any of these
|
|
1028
|
+
* conditions hold: graceful shutdown in progress, login mode active, browser not connected, browser age below threshold. If active streams exist, any pending
|
|
1029
|
+
* quiet timer is cancelled (streams started during the quiet period reset the countdown). Otherwise a quiet timer is started if one is not already running.
|
|
1030
|
+
*/
|
|
1031
|
+
function checkBrowserRestart() {
|
|
1032
|
+
// Skip if the server is shutting down, login mode is active, or the browser is not connected.
|
|
1033
|
+
if (gracefulShutdownInProgress || loginModeActive || !currentBrowser || !currentBrowser.connected || !browserLaunchTime) {
|
|
1034
|
+
return;
|
|
1035
|
+
}
|
|
1036
|
+
// Skip if the browser has not exceeded the maximum age.
|
|
1037
|
+
const age = Date.now() - browserLaunchTime;
|
|
1038
|
+
if (age < BROWSER_MAX_AGE) {
|
|
1039
|
+
return;
|
|
1040
|
+
}
|
|
1041
|
+
// If there are active streams, cancel any pending quiet timer and return. Streams that start during the quiet period reset the countdown.
|
|
1042
|
+
if (getStreamCount() > 0) {
|
|
1043
|
+
if (restartQuietTimer) {
|
|
1044
|
+
LOG.debug("browser", "Browser restart quiet period cancelled — streams are active.");
|
|
1045
|
+
clearTimeout(restartQuietTimer);
|
|
1046
|
+
restartQuietTimer = null;
|
|
1047
|
+
}
|
|
1048
|
+
return;
|
|
1049
|
+
}
|
|
1050
|
+
// No active streams and the browser is old enough. Start the quiet timer if one is not already running.
|
|
1051
|
+
if (!restartQuietTimer) {
|
|
1052
|
+
LOG.debug("browser", "Browser uptime exceeds threshold. Quiet period started — restart will proceed if no streams start within %s minutes.", Math.round(BROWSER_RESTART_QUIET_PERIOD / 60000));
|
|
1053
|
+
restartQuietTimer = setTimeout(() => {
|
|
1054
|
+
void executeBrowserRestart();
|
|
1055
|
+
}, BROWSER_RESTART_QUIET_PERIOD);
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
/**
|
|
1059
|
+
* Executes the opportunistic browser restart after the quiet period has elapsed. Performs a final guard check before proceeding, then closes the browser and
|
|
1060
|
+
* immediately re-launches a fresh instance.
|
|
1061
|
+
*/
|
|
1062
|
+
async function executeBrowserRestart() {
|
|
1063
|
+
// Clear the timer handle.
|
|
1064
|
+
restartQuietTimer = null;
|
|
1065
|
+
// Final guard: re-check all preconditions. Conditions may have changed during the quiet period (e.g., a stream started just before the timer fired, login
|
|
1066
|
+
// mode was activated, or the browser disconnected on its own).
|
|
1067
|
+
if (gracefulShutdownInProgress || loginModeActive || (getStreamCount() > 0) || !currentBrowser || !currentBrowser.connected || !browserLaunchTime) {
|
|
1068
|
+
LOG.debug("browser", "Browser restart aborted — preconditions no longer met.");
|
|
1069
|
+
return;
|
|
1070
|
+
}
|
|
1071
|
+
const age = Date.now() - browserLaunchTime;
|
|
1072
|
+
const hours = Math.floor(age / 3600000);
|
|
1073
|
+
const minutes = Math.floor((age % 3600000) / 60000);
|
|
1074
|
+
LOG.info("Restarting browser for scheduled maintenance (uptime: %sh %sm).", hours, minutes);
|
|
1075
|
+
try {
|
|
1076
|
+
// closeBrowser() sets gracefulShutdownInProgress = true internally and performs multi-stage graceful close.
|
|
1077
|
+
await closeBrowser();
|
|
1078
|
+
// Reset the flag since the server is NOT shutting down — only the browser is restarting.
|
|
1079
|
+
setGracefulShutdown(false);
|
|
1080
|
+
// Launch a fresh browser instance so it is ready for the next stream request.
|
|
1081
|
+
await getCurrentBrowser();
|
|
1082
|
+
// Minimize the new window to reduce GPU usage and desktop clutter.
|
|
1083
|
+
await minimizeBrowserWindow();
|
|
1084
|
+
LOG.info("Browser restart complete. Fresh instance is ready.");
|
|
1085
|
+
}
|
|
1086
|
+
catch (error) {
|
|
1087
|
+
LOG.error("Browser restart failed: %s.", formatError(error));
|
|
1088
|
+
// Ensure the graceful shutdown flag is cleared even on failure so new stream requests can still launch a browser.
|
|
1089
|
+
setGracefulShutdown(false);
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
/**
|
|
1093
|
+
* Starts the periodic browser restart eligibility check. This should be called once during server startup, after the browser is initialized. The interval runs
|
|
1094
|
+
* indefinitely until stopBrowserRestartChecking() is called (typically during graceful shutdown).
|
|
1095
|
+
*/
|
|
1096
|
+
export function startBrowserRestartChecking() {
|
|
1097
|
+
restartCheckInterval = setInterval(checkBrowserRestart, BROWSER_RESTART_CHECK_INTERVAL);
|
|
1098
|
+
}
|
|
1099
|
+
/**
|
|
1100
|
+
* Stops the browser restart checking interval and cancels any pending quiet timer. This should be called during graceful shutdown to prevent a restart from
|
|
1101
|
+
* racing with server shutdown.
|
|
1102
|
+
*/
|
|
1103
|
+
export function stopBrowserRestartChecking() {
|
|
1104
|
+
if (restartCheckInterval) {
|
|
1105
|
+
clearInterval(restartCheckInterval);
|
|
1106
|
+
restartCheckInterval = null;
|
|
1107
|
+
}
|
|
1108
|
+
if (restartQuietTimer) {
|
|
1109
|
+
clearTimeout(restartQuietTimer);
|
|
1110
|
+
restartQuietTimer = null;
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
947
1113
|
/* When running as a packaged executable (created by the `pkg` tool), the application is bundled into a single binary. Node modules like puppeteer-stream are
|
|
948
1114
|
* included in the bundle, but Chrome cannot load extensions from within the packaged binary - it needs actual files on the filesystem.
|
|
949
1115
|
*
|
|
@@ -992,7 +1158,7 @@ export async function prepareExtension() {
|
|
|
992
1158
|
throw error;
|
|
993
1159
|
}
|
|
994
1160
|
}
|
|
995
|
-
LOG.
|
|
1161
|
+
LOG.debug("browser", "Extension files prepared successfully.");
|
|
996
1162
|
}
|
|
997
1163
|
catch (error) {
|
|
998
1164
|
LOG.error("Extension preparation failed: %s.", formatError(error));
|