@hyperframes/producer 0.8.192 → 0.8.193
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/dist/distributed.d.ts +1 -0
- package/dist/distributed.js +258 -108
- package/dist/hyperframe.manifest.json +1 -1
- package/dist/hyperframe.runtime.iife.js +51 -51
- package/dist/index.js +490 -458
- package/dist/public-server.js +319 -299
- package/dist/services/distributed/plan.d.ts +2 -0
- package/dist/services/distributed/probeFacts.d.ts +4 -0
- package/dist/services/render/perfSummary.d.ts +6 -0
- package/dist/services/render/stages/audioStage.d.ts +3 -1
- package/dist/services/renderOrchestrator.d.ts +2 -0
- package/package.json +7 -7
package/dist/public-server.js
CHANGED
|
@@ -1384,18 +1384,9 @@ var RenderExecutionContext = class {
|
|
|
1384
1384
|
};
|
|
1385
1385
|
|
|
1386
1386
|
// src/services/render/artifactTransaction.ts
|
|
1387
|
-
import {
|
|
1388
|
-
closeSync as closeSync2,
|
|
1389
|
-
existsSync as existsSync5,
|
|
1390
|
-
fstatSync as fstatSync2,
|
|
1391
|
-
openSync as openSync2,
|
|
1392
|
-
readSync,
|
|
1393
|
-
readdirSync as readdirSync2,
|
|
1394
|
-
renameSync,
|
|
1395
|
-
rmSync as rmSync3
|
|
1396
|
-
} from "node:fs";
|
|
1387
|
+
import { closeSync as closeSync2, existsSync as existsSync5, fstatSync as fstatSync2, openSync as openSync2, readSync, readdirSync as readdirSync2, rmSync as rmSync3 } from "node:fs";
|
|
1397
1388
|
import { basename as basename3, dirname as dirname4, extname as extname2, join as join5, resolve as resolve4 } from "node:path";
|
|
1398
|
-
import { HLS_MASTER_PLAYLIST, HLS_VIDEO_PLAYLIST } from "@hyperframes/engine";
|
|
1389
|
+
import { HLS_MASTER_PLAYLIST, HLS_VIDEO_PLAYLIST, renameWithRetry } from "@hyperframes/engine";
|
|
1399
1390
|
|
|
1400
1391
|
// src/utils/ffprobe.ts
|
|
1401
1392
|
import {
|
|
@@ -1514,7 +1505,7 @@ function createRenderWorkDir(prefix, outputDir) {
|
|
|
1514
1505
|
// src/services/render/artifactTransaction.ts
|
|
1515
1506
|
var defaultFileSystem = {
|
|
1516
1507
|
existsSync: existsSync5,
|
|
1517
|
-
renameSync,
|
|
1508
|
+
renameSync: (source, destination) => renameWithRetry(source, destination),
|
|
1518
1509
|
rmSync: rmSync3
|
|
1519
1510
|
};
|
|
1520
1511
|
async function defaultArtifactDurationProbe(path) {
|
|
@@ -1913,58 +1904,10 @@ import {
|
|
|
1913
1904
|
|
|
1914
1905
|
// src/services/render/captureStageError.ts
|
|
1915
1906
|
import { CaptureFailure, classifyCaptureFailure } from "@hyperframes/engine";
|
|
1916
|
-
var CaptureStageError = class extends CaptureFailure {
|
|
1917
|
-
browserConsole;
|
|
1918
|
-
constructor(input) {
|
|
1919
|
-
const classified = classifyCaptureFailure(input.cause);
|
|
1920
|
-
super({
|
|
1921
|
-
kind: classified.kind,
|
|
1922
|
-
message: normalizeErrorMessage(input.cause),
|
|
1923
|
-
cause: input.cause,
|
|
1924
|
-
workerDiagnostics: classified.workerDiagnostics
|
|
1925
|
-
});
|
|
1926
|
-
this.name = "CaptureStageError";
|
|
1927
|
-
this.browserConsole = input.browserConsole.slice();
|
|
1928
|
-
if (input.cause instanceof Error && input.cause.stack) {
|
|
1929
|
-
this.stack = input.cause.stack;
|
|
1930
|
-
}
|
|
1931
|
-
}
|
|
1932
|
-
};
|
|
1933
|
-
function wrapCaptureStageError(error, browserConsole) {
|
|
1934
|
-
if (error instanceof CaptureStageError || error instanceof EncoderInterruptedError) return error;
|
|
1935
|
-
return new CaptureStageError({ cause: error, browserConsole });
|
|
1936
|
-
}
|
|
1937
|
-
function getCaptureStageBrowserConsole(error) {
|
|
1938
|
-
if (error instanceof CaptureStageError) return error.browserConsole;
|
|
1939
|
-
return [];
|
|
1940
|
-
}
|
|
1941
|
-
|
|
1942
|
-
// src/services/render/stages/captureHdrFrameShared.ts
|
|
1943
|
-
import {
|
|
1944
|
-
applyDomLayerMask as applyDomLayerMask2,
|
|
1945
|
-
blitRgba8OverRgb48le as blitRgba8OverRgb48le2,
|
|
1946
|
-
captureAlphaPng as captureAlphaPng2,
|
|
1947
|
-
decodePng as decodePng2,
|
|
1948
|
-
queryElementStacking as queryElementStacking2,
|
|
1949
|
-
removeDomLayerMask as removeDomLayerMask2
|
|
1950
|
-
} from "@hyperframes/engine";
|
|
1951
1907
|
|
|
1952
|
-
// src/services/
|
|
1953
|
-
import {
|
|
1954
|
-
import {
|
|
1955
|
-
import {
|
|
1956
|
-
captureAlphaPng,
|
|
1957
|
-
applyDomLayerMask,
|
|
1958
|
-
removeDomLayerMask,
|
|
1959
|
-
decodePng,
|
|
1960
|
-
blitRgba8OverRgb48le,
|
|
1961
|
-
blitRgb48leRegion,
|
|
1962
|
-
groupIntoLayers,
|
|
1963
|
-
blitRgb48leAffine,
|
|
1964
|
-
parseTransformMatrix,
|
|
1965
|
-
convertTransfer,
|
|
1966
|
-
isVideoHiddenBeforeStreamStart
|
|
1967
|
-
} from "@hyperframes/engine";
|
|
1908
|
+
// src/services/render/perfSummary.ts
|
|
1909
|
+
import { arch, cpus, platform, totalmem } from "node:os";
|
|
1910
|
+
import { fpsToNumber as fpsToNumber3 } from "@hyperframes/core";
|
|
1968
1911
|
|
|
1969
1912
|
// src/services/render/hdrPerf.ts
|
|
1970
1913
|
function createHdrPerfCollector() {
|
|
@@ -2070,7 +2013,280 @@ function finalizeHdrPerf(perf) {
|
|
|
2070
2013
|
};
|
|
2071
2014
|
}
|
|
2072
2015
|
|
|
2016
|
+
// src/services/render/perfSummary.ts
|
|
2017
|
+
function worstSubTimelineWaitOutcome(perfs) {
|
|
2018
|
+
const outcomes = perfs.map((p) => p.subTimelineWaitOutcome).filter((o) => !!o);
|
|
2019
|
+
if (outcomes.length === 0) return void 0;
|
|
2020
|
+
if (outcomes.includes("script_failure")) return "script_failure";
|
|
2021
|
+
if (outcomes.includes("timeout")) return "timeout";
|
|
2022
|
+
return "ready";
|
|
2023
|
+
}
|
|
2024
|
+
function pushWorkerDedupPerfs(results, sink) {
|
|
2025
|
+
for (const r of results) {
|
|
2026
|
+
if (r.perf) sink.push(r.perf);
|
|
2027
|
+
}
|
|
2028
|
+
}
|
|
2029
|
+
function pushWorkerPageErrors(results, sink) {
|
|
2030
|
+
for (const result of results) {
|
|
2031
|
+
for (const line of result.pageErrorLines ?? []) if (!sink.includes(line)) sink.push(line);
|
|
2032
|
+
}
|
|
2033
|
+
}
|
|
2034
|
+
function withWorkerPageErrors(consoleLines, workerLines) {
|
|
2035
|
+
return [...consoleLines, ...workerLines.filter((line) => !consoleLines.includes(line))];
|
|
2036
|
+
}
|
|
2037
|
+
function roundDb(value) {
|
|
2038
|
+
return value === void 0 ? void 0 : Math.round(Math.min(value, 999) * 10) / 10;
|
|
2039
|
+
}
|
|
2040
|
+
function aggregateDrawElement(perfs, de) {
|
|
2041
|
+
if (perfs.length === 0) return void 0;
|
|
2042
|
+
const modes = [...new Set(perfs.map((p) => p.captureMode).filter(Boolean))].sort();
|
|
2043
|
+
const gateReasons = [
|
|
2044
|
+
...new Set(
|
|
2045
|
+
[de.probeGateReason, ...perfs.map((p) => p.deGateReason)].filter((r) => !!r)
|
|
2046
|
+
)
|
|
2047
|
+
].sort();
|
|
2048
|
+
const gpuRenderers = [
|
|
2049
|
+
...new Set(perfs.map((p) => p.gpuRenderer).filter((r) => !!r))
|
|
2050
|
+
].sort();
|
|
2051
|
+
const drain = de.drainStats;
|
|
2052
|
+
return {
|
|
2053
|
+
mode: modes.join("|") || "unknown",
|
|
2054
|
+
compileGate: de.compileGate,
|
|
2055
|
+
clampReason: de.clampReason,
|
|
2056
|
+
workerInversion: de.workerInversion ?? "none",
|
|
2057
|
+
preInversionWorkers: de.preInversionWorkers,
|
|
2058
|
+
compositionElementCount: de.compositionElementCount,
|
|
2059
|
+
compositionElementCountSource: de.compositionElementCountSource,
|
|
2060
|
+
compositionElementTags: de.compositionElementTags,
|
|
2061
|
+
arollVideoCount: de.arollVideoCount,
|
|
2062
|
+
heygenVideoCount: de.heygenVideoCount,
|
|
2063
|
+
adaptersUsed: de.adaptersUsed,
|
|
2064
|
+
audioCount: de.audioCount,
|
|
2065
|
+
imageCount: de.imageCount,
|
|
2066
|
+
subCompositionCount: de.subCompositionCount,
|
|
2067
|
+
audioGroupCount: de.audioGroupCount,
|
|
2068
|
+
colorGradingCount: de.colorGradingCount,
|
|
2069
|
+
hasLut: de.hasLut,
|
|
2070
|
+
rootBodyMismatch: de.rootBodyMismatch,
|
|
2071
|
+
rootBodyDeltaPxBucket: de.rootBodyDeltaPxBucket,
|
|
2072
|
+
vfxHostCount: de.vfxHostCount,
|
|
2073
|
+
vfxCapture: de.vfxCapture,
|
|
2074
|
+
vfxTypes: de.vfxTypes,
|
|
2075
|
+
shortBand: de.shortBand,
|
|
2076
|
+
parallelRouter: de.parallelRouter ?? "none",
|
|
2077
|
+
preRouterWorkers: de.preRouterWorkers,
|
|
2078
|
+
gateReason: gateReasons.length > 0 ? gateReasons.join("|") : void 0,
|
|
2079
|
+
gpuRenderer: gpuRenderers.length > 0 ? gpuRenderers.join("|") : void 0,
|
|
2080
|
+
workerEncode: perfs.some((p) => p.deWorkerEncode),
|
|
2081
|
+
verifyArmed: perfs.reduce((sum, p) => sum + (p.deVerifyArmed ?? 0), 0),
|
|
2082
|
+
verifyChecked: drain?.verifyChecked ?? 0,
|
|
2083
|
+
verifyMinDb: roundDb(drain?.verifyMinDb),
|
|
2084
|
+
verifyInitMs: perfs.reduce((sum, p) => sum + (p.deVerifyInitMs ?? 0), 0),
|
|
2085
|
+
selfVerifyFallback: de.selfVerifyFallback,
|
|
2086
|
+
fallbackReason: de.fallbackReason,
|
|
2087
|
+
fallbackFailedDb: roundDb(de.fallbackFailedDb),
|
|
2088
|
+
fallbackFrameIndex: de.fallbackFrameIndex,
|
|
2089
|
+
fallbackThresholdDb: roundDb(de.fallbackThresholdDb),
|
|
2090
|
+
blankSuspects: drain?.blankSuspects ?? 0,
|
|
2091
|
+
blankDeterministicAccepts: drain?.blankDeterministicAccepts ?? 0,
|
|
2092
|
+
blankRecaptures: drain?.blankRecaptures ?? 0,
|
|
2093
|
+
boundaryFrames: perfs.reduce((sum, p) => sum + (p.deBoundaryFrames ?? 0), 0),
|
|
2094
|
+
ncprFallbacks: perfs.reduce((sum, p) => sum + (p.deNcprFallbacks ?? 0), 0),
|
|
2095
|
+
frameTimeouts: perfs.reduce((sum, p) => sum + (p.deFrameTimeouts ?? 0), 0)
|
|
2096
|
+
};
|
|
2097
|
+
}
|
|
2098
|
+
function maxDefined(values) {
|
|
2099
|
+
const present = values.filter((v) => typeof v === "number");
|
|
2100
|
+
return present.length > 0 ? Math.max(...present) : void 0;
|
|
2101
|
+
}
|
|
2102
|
+
function aggregateChromeMemory(perfs) {
|
|
2103
|
+
const sampled = perfs.filter((p) => (p.chromeMemorySamples ?? 0) > 0);
|
|
2104
|
+
if (sampled.length === 0) return void 0;
|
|
2105
|
+
return {
|
|
2106
|
+
browserRssPeakMb: maxDefined(sampled.map((p) => p.chromeBrowserRssPeakMb)),
|
|
2107
|
+
rendererRssPeakMb: maxDefined(sampled.map((p) => p.chromeRendererRssPeakMb)),
|
|
2108
|
+
// Last samples are per session; summing approximates the whole fleet's
|
|
2109
|
+
// footprint at the end of capture (workers run concurrently).
|
|
2110
|
+
rssLastMb: sampled.reduce((sum, p) => sum + (p.chromeRssLastMb ?? 0), 0),
|
|
2111
|
+
gpuProcessSeenLastSample: sampled.some((p) => p.chromeGpuProcessSeenLastSample === true),
|
|
2112
|
+
samples: sampled.reduce((sum, p) => sum + (p.chromeMemorySamples ?? 0), 0)
|
|
2113
|
+
};
|
|
2114
|
+
}
|
|
2115
|
+
function aggregateDedup(perfs) {
|
|
2116
|
+
if (perfs.length === 0) return void 0;
|
|
2117
|
+
const armed = perfs.some((p) => p.staticDedupArmed);
|
|
2118
|
+
const skipReasons = armed ? [] : [
|
|
2119
|
+
...new Set(perfs.map((p) => p.staticDedupSkipReason).filter((r) => !!r))
|
|
2120
|
+
].sort();
|
|
2121
|
+
const verificationPerfs = perfs.filter((perf) => perf.staticDedupVerificationOutcome);
|
|
2122
|
+
const verificationOutcomes = [
|
|
2123
|
+
...new Set(
|
|
2124
|
+
verificationPerfs.map((perf) => perf.staticDedupVerificationOutcome).filter((outcome) => outcome != null)
|
|
2125
|
+
)
|
|
2126
|
+
].sort();
|
|
2127
|
+
return {
|
|
2128
|
+
enabled: perfs.some((p) => p.staticDedupEnabled),
|
|
2129
|
+
armed,
|
|
2130
|
+
predictedFrames: perfs.reduce((sum, p) => sum + (p.staticDedupPredicted ?? 0), 0),
|
|
2131
|
+
reusedFrames: perfs.reduce((sum, p) => sum + (p.staticDedupReused ?? 0), 0),
|
|
2132
|
+
skipReason: skipReasons.length > 0 ? skipReasons.join("|") : void 0,
|
|
2133
|
+
...verificationPerfs.length === 0 ? {} : {
|
|
2134
|
+
verifiedFrames: verificationPerfs.reduce(
|
|
2135
|
+
(sum, perf) => sum + (perf.staticDedupVerified ?? 0),
|
|
2136
|
+
0
|
|
2137
|
+
),
|
|
2138
|
+
verificationOutcomes,
|
|
2139
|
+
plannedRuns: verificationPerfs.reduce(
|
|
2140
|
+
(sum, perf) => sum + (perf.staticDedupVerificationPlannedRuns ?? 0),
|
|
2141
|
+
0
|
|
2142
|
+
),
|
|
2143
|
+
completedRuns: verificationPerfs.reduce(
|
|
2144
|
+
(sum, perf) => sum + (perf.staticDedupVerificationCompletedRuns ?? 0),
|
|
2145
|
+
0
|
|
2146
|
+
),
|
|
2147
|
+
screenshots: verificationPerfs.reduce(
|
|
2148
|
+
(sum, perf) => sum + (perf.staticDedupVerificationScreenshots ?? 0),
|
|
2149
|
+
0
|
|
2150
|
+
),
|
|
2151
|
+
seeks: verificationPerfs.reduce(
|
|
2152
|
+
(sum, perf) => sum + (perf.staticDedupVerificationSeeks ?? 0),
|
|
2153
|
+
0
|
|
2154
|
+
),
|
|
2155
|
+
comparisons: verificationPerfs.reduce(
|
|
2156
|
+
(sum, perf) => sum + (perf.staticDedupVerificationComparisons ?? 0),
|
|
2157
|
+
0
|
|
2158
|
+
),
|
|
2159
|
+
verificationElapsedMs: verificationPerfs.reduce(
|
|
2160
|
+
(sum, perf) => sum + (perf.staticDedupVerificationElapsedMs ?? 0),
|
|
2161
|
+
0
|
|
2162
|
+
)
|
|
2163
|
+
}
|
|
2164
|
+
};
|
|
2165
|
+
}
|
|
2166
|
+
function aggregateBeginFrameReuse(perfs) {
|
|
2167
|
+
const noDamageFrames = perfs.reduce((sum, p) => sum + (p.beginFrameNoDamage ?? 0), 0);
|
|
2168
|
+
const hasDamageFrames = perfs.reduce((sum, p) => sum + (p.beginFrameHasDamage ?? 0), 0);
|
|
2169
|
+
if (noDamageFrames + hasDamageFrames === 0) return void 0;
|
|
2170
|
+
return { noDamageFrames, hasDamageFrames };
|
|
2171
|
+
}
|
|
2172
|
+
function buildRenderPerfSummary(input) {
|
|
2173
|
+
return {
|
|
2174
|
+
renderId: input.job.id,
|
|
2175
|
+
totalElapsedMs: input.totalElapsedMs,
|
|
2176
|
+
// RenderPerfSummary surfaces fps as a decimal because it lands in JSON
|
|
2177
|
+
// payloads (CLI telemetry, regression-harness reports) where a single
|
|
2178
|
+
// number is friendlier than `{num,den}`. Callers needing the rational
|
|
2179
|
+
// back can read `job.config.fps`.
|
|
2180
|
+
fps: fpsToNumber3(input.job.config.fps),
|
|
2181
|
+
quality: input.job.config.quality,
|
|
2182
|
+
workers: input.workerCount,
|
|
2183
|
+
workerSizing: input.workerSizing,
|
|
2184
|
+
chunkedEncode: input.enableChunkedEncode,
|
|
2185
|
+
chunkSizeFrames: input.enableChunkedEncode ? input.chunkedEncodeSize : null,
|
|
2186
|
+
compositionDurationSeconds: input.compositionDurationSeconds,
|
|
2187
|
+
totalFrames: input.totalFrames,
|
|
2188
|
+
resolution: { width: input.outputWidth, height: input.outputHeight },
|
|
2189
|
+
videoCount: input.videoCount,
|
|
2190
|
+
audioCount: input.audioCount,
|
|
2191
|
+
stages: input.perfStages,
|
|
2192
|
+
videoExtractBreakdown: input.videoExtractBreakdown,
|
|
2193
|
+
tmpPeakBytes: input.tmpPeakBytes,
|
|
2194
|
+
captureCalibration: input.captureCalibration ? {
|
|
2195
|
+
sampledFrames: input.captureCalibration.samples.map((sample) => sample.frameIndex),
|
|
2196
|
+
p95Ms: input.captureCalibration.estimate.p95Ms,
|
|
2197
|
+
multiplier: input.captureCalibration.estimate.multiplier,
|
|
2198
|
+
reasons: input.captureCalibration.estimate.reasons
|
|
2199
|
+
} : void 0,
|
|
2200
|
+
captureAttempts: input.captureAttempts.length > 0 ? input.captureAttempts : void 0,
|
|
2201
|
+
hdrDiagnostics: input.hdrDiagnostics.videoExtractionFailures > 0 || input.hdrDiagnostics.imageDecodeFailures > 0 ? { ...input.hdrDiagnostics } : void 0,
|
|
2202
|
+
hdrPerf: input.hdrPerf ? finalizeHdrPerf(input.hdrPerf) : void 0,
|
|
2203
|
+
observability: input.observability,
|
|
2204
|
+
captureAvgMs: input.totalFrames > 0 ? Math.round(
|
|
2205
|
+
(input.perfStages.captureFrameMs ?? input.perfStages.captureMs ?? 0) / input.totalFrames
|
|
2206
|
+
) : void 0,
|
|
2207
|
+
subTimelineWait: worstSubTimelineWaitOutcome(input.dedupPerfs),
|
|
2208
|
+
captureP50Ms: (() => {
|
|
2209
|
+
const withSamples = input.dedupPerfs.filter((p) => (p.p50TotalMs ?? 0) > 0);
|
|
2210
|
+
if (withSamples.length === 0) return void 0;
|
|
2211
|
+
return withSamples.reduce((a, b) => b.frames > a.frames ? b : a).p50TotalMs;
|
|
2212
|
+
})(),
|
|
2213
|
+
peakRssMb: Math.round(input.peakRssBytes / (1024 * 1024)),
|
|
2214
|
+
peakHeapUsedMb: Math.round(input.peakHeapUsedBytes / (1024 * 1024)),
|
|
2215
|
+
staticDedup: aggregateDedup(input.dedupPerfs),
|
|
2216
|
+
chromeMemory: aggregateChromeMemory(input.dedupPerfs),
|
|
2217
|
+
beginFrameReuse: aggregateBeginFrameReuse(input.dedupPerfs),
|
|
2218
|
+
drawElement: aggregateDrawElement(
|
|
2219
|
+
input.dedupPerfs,
|
|
2220
|
+
input.drawElement ?? { selfVerifyFallback: false }
|
|
2221
|
+
),
|
|
2222
|
+
host: {
|
|
2223
|
+
platform: platform(),
|
|
2224
|
+
arch: arch(),
|
|
2225
|
+
cpuCount: cpus().length,
|
|
2226
|
+
totalMemMb: Math.round(totalmem() / (1024 * 1024)),
|
|
2227
|
+
nodeVersion: process.version,
|
|
2228
|
+
gpuDisabled: input.gpuDisabled
|
|
2229
|
+
}
|
|
2230
|
+
};
|
|
2231
|
+
}
|
|
2232
|
+
|
|
2233
|
+
// src/services/render/captureStageError.ts
|
|
2234
|
+
var CaptureStageError = class extends CaptureFailure {
|
|
2235
|
+
browserConsole;
|
|
2236
|
+
constructor(input) {
|
|
2237
|
+
const classified = classifyCaptureFailure(input.cause);
|
|
2238
|
+
super({
|
|
2239
|
+
kind: classified.kind,
|
|
2240
|
+
message: normalizeErrorMessage(input.cause),
|
|
2241
|
+
cause: input.cause,
|
|
2242
|
+
workerDiagnostics: classified.workerDiagnostics,
|
|
2243
|
+
pageErrorLines: classified.pageErrorLines
|
|
2244
|
+
});
|
|
2245
|
+
this.name = "CaptureStageError";
|
|
2246
|
+
this.browserConsole = withWorkerPageErrors(input.browserConsole, [
|
|
2247
|
+
...classified.pageErrorLines
|
|
2248
|
+
]);
|
|
2249
|
+
if (input.cause instanceof Error && input.cause.stack) {
|
|
2250
|
+
this.stack = input.cause.stack;
|
|
2251
|
+
}
|
|
2252
|
+
}
|
|
2253
|
+
};
|
|
2254
|
+
function wrapCaptureStageError(error, browserConsole) {
|
|
2255
|
+
if (error instanceof CaptureStageError || error instanceof EncoderInterruptedError) return error;
|
|
2256
|
+
return new CaptureStageError({ cause: error, browserConsole });
|
|
2257
|
+
}
|
|
2258
|
+
function getCaptureStageBrowserConsole(error) {
|
|
2259
|
+
if (error instanceof CaptureStageError) return error.browserConsole;
|
|
2260
|
+
if (error instanceof CaptureFailure) return [...error.pageErrorLines];
|
|
2261
|
+
return [];
|
|
2262
|
+
}
|
|
2263
|
+
|
|
2264
|
+
// src/services/render/stages/captureHdrFrameShared.ts
|
|
2265
|
+
import {
|
|
2266
|
+
applyDomLayerMask as applyDomLayerMask2,
|
|
2267
|
+
blitRgba8OverRgb48le as blitRgba8OverRgb48le2,
|
|
2268
|
+
captureAlphaPng as captureAlphaPng2,
|
|
2269
|
+
decodePng as decodePng2,
|
|
2270
|
+
queryElementStacking as queryElementStacking2,
|
|
2271
|
+
removeDomLayerMask as removeDomLayerMask2
|
|
2272
|
+
} from "@hyperframes/engine";
|
|
2273
|
+
|
|
2073
2274
|
// src/services/hdrCompositor.ts
|
|
2275
|
+
import { readSync as readSync2, closeSync as closeSync3 } from "fs";
|
|
2276
|
+
import { join as join6 } from "path";
|
|
2277
|
+
import {
|
|
2278
|
+
captureAlphaPng,
|
|
2279
|
+
applyDomLayerMask,
|
|
2280
|
+
removeDomLayerMask,
|
|
2281
|
+
decodePng,
|
|
2282
|
+
blitRgba8OverRgb48le,
|
|
2283
|
+
blitRgb48leRegion,
|
|
2284
|
+
groupIntoLayers,
|
|
2285
|
+
blitRgb48leAffine,
|
|
2286
|
+
parseTransformMatrix,
|
|
2287
|
+
convertTransfer,
|
|
2288
|
+
isVideoHiddenBeforeStreamStart
|
|
2289
|
+
} from "@hyperframes/engine";
|
|
2074
2290
|
function countNonZeroAlpha(rgba) {
|
|
2075
2291
|
let n = 0;
|
|
2076
2292
|
for (let p = 3; p < rgba.length; p += 4) {
|
|
@@ -2537,7 +2753,7 @@ import {
|
|
|
2537
2753
|
resolveVideoExtractionWindow,
|
|
2538
2754
|
runFfmpeg
|
|
2539
2755
|
} from "@hyperframes/engine";
|
|
2540
|
-
import { fpsToFfmpegArg, fpsToNumber as
|
|
2756
|
+
import { fpsToFfmpegArg, fpsToNumber as fpsToNumber4 } from "@hyperframes/core";
|
|
2541
2757
|
var NO_FOLLOW_FLAG = constants2.O_NOFOLLOW ?? 0;
|
|
2542
2758
|
function tempDirSafePrefix(id) {
|
|
2543
2759
|
const safe = id.replace(/[^A-Za-z0-9_.-]/g, "_").slice(0, 80);
|
|
@@ -2773,7 +2989,7 @@ async function extractHdrVideoFrames(args) {
|
|
|
2773
2989
|
const { estimatedBytes, budgetBytes } = assertHdrExtractionDiskHeadroom(
|
|
2774
2990
|
framesDir,
|
|
2775
2991
|
plannedVideos,
|
|
2776
|
-
|
|
2992
|
+
fpsToNumber4(job.config.fps),
|
|
2777
2993
|
log
|
|
2778
2994
|
);
|
|
2779
2995
|
const releaseReservation = reserveHdrExtractionBytes(estimatedBytes, budgetBytes);
|
|
@@ -3226,222 +3442,12 @@ import {
|
|
|
3226
3442
|
prepareCaptureSessionForReuse,
|
|
3227
3443
|
spawnStreamingEncoder
|
|
3228
3444
|
} from "@hyperframes/engine";
|
|
3229
|
-
|
|
3230
|
-
// src/services/render/perfSummary.ts
|
|
3231
|
-
import { arch, cpus, platform, totalmem } from "node:os";
|
|
3232
|
-
import { fpsToNumber as fpsToNumber4 } from "@hyperframes/core";
|
|
3233
|
-
function worstSubTimelineWaitOutcome(perfs) {
|
|
3234
|
-
const outcomes = perfs.map((p) => p.subTimelineWaitOutcome).filter((o) => !!o);
|
|
3235
|
-
if (outcomes.length === 0) return void 0;
|
|
3236
|
-
if (outcomes.includes("script_failure")) return "script_failure";
|
|
3237
|
-
if (outcomes.includes("timeout")) return "timeout";
|
|
3238
|
-
return "ready";
|
|
3239
|
-
}
|
|
3240
|
-
function pushWorkerDedupPerfs(results, sink) {
|
|
3241
|
-
for (const r of results) {
|
|
3242
|
-
if (r.perf) sink.push(r.perf);
|
|
3243
|
-
}
|
|
3244
|
-
}
|
|
3245
|
-
function roundDb(value) {
|
|
3246
|
-
return value === void 0 ? void 0 : Math.round(Math.min(value, 999) * 10) / 10;
|
|
3247
|
-
}
|
|
3248
|
-
function aggregateDrawElement(perfs, de) {
|
|
3249
|
-
if (perfs.length === 0) return void 0;
|
|
3250
|
-
const modes = [...new Set(perfs.map((p) => p.captureMode).filter(Boolean))].sort();
|
|
3251
|
-
const gateReasons = [
|
|
3252
|
-
...new Set(
|
|
3253
|
-
[de.probeGateReason, ...perfs.map((p) => p.deGateReason)].filter((r) => !!r)
|
|
3254
|
-
)
|
|
3255
|
-
].sort();
|
|
3256
|
-
const gpuRenderers = [
|
|
3257
|
-
...new Set(perfs.map((p) => p.gpuRenderer).filter((r) => !!r))
|
|
3258
|
-
].sort();
|
|
3259
|
-
const drain = de.drainStats;
|
|
3260
|
-
return {
|
|
3261
|
-
mode: modes.join("|") || "unknown",
|
|
3262
|
-
compileGate: de.compileGate,
|
|
3263
|
-
clampReason: de.clampReason,
|
|
3264
|
-
workerInversion: de.workerInversion ?? "none",
|
|
3265
|
-
preInversionWorkers: de.preInversionWorkers,
|
|
3266
|
-
compositionElementCount: de.compositionElementCount,
|
|
3267
|
-
compositionElementCountSource: de.compositionElementCountSource,
|
|
3268
|
-
compositionElementTags: de.compositionElementTags,
|
|
3269
|
-
arollVideoCount: de.arollVideoCount,
|
|
3270
|
-
heygenVideoCount: de.heygenVideoCount,
|
|
3271
|
-
adaptersUsed: de.adaptersUsed,
|
|
3272
|
-
audioCount: de.audioCount,
|
|
3273
|
-
imageCount: de.imageCount,
|
|
3274
|
-
subCompositionCount: de.subCompositionCount,
|
|
3275
|
-
audioGroupCount: de.audioGroupCount,
|
|
3276
|
-
colorGradingCount: de.colorGradingCount,
|
|
3277
|
-
hasLut: de.hasLut,
|
|
3278
|
-
rootBodyMismatch: de.rootBodyMismatch,
|
|
3279
|
-
rootBodyDeltaPxBucket: de.rootBodyDeltaPxBucket,
|
|
3280
|
-
vfxHostCount: de.vfxHostCount,
|
|
3281
|
-
vfxCapture: de.vfxCapture,
|
|
3282
|
-
vfxTypes: de.vfxTypes,
|
|
3283
|
-
shortBand: de.shortBand,
|
|
3284
|
-
parallelRouter: de.parallelRouter ?? "none",
|
|
3285
|
-
preRouterWorkers: de.preRouterWorkers,
|
|
3286
|
-
gateReason: gateReasons.length > 0 ? gateReasons.join("|") : void 0,
|
|
3287
|
-
gpuRenderer: gpuRenderers.length > 0 ? gpuRenderers.join("|") : void 0,
|
|
3288
|
-
workerEncode: perfs.some((p) => p.deWorkerEncode),
|
|
3289
|
-
verifyArmed: perfs.reduce((sum, p) => sum + (p.deVerifyArmed ?? 0), 0),
|
|
3290
|
-
verifyChecked: drain?.verifyChecked ?? 0,
|
|
3291
|
-
verifyMinDb: roundDb(drain?.verifyMinDb),
|
|
3292
|
-
verifyInitMs: perfs.reduce((sum, p) => sum + (p.deVerifyInitMs ?? 0), 0),
|
|
3293
|
-
selfVerifyFallback: de.selfVerifyFallback,
|
|
3294
|
-
fallbackReason: de.fallbackReason,
|
|
3295
|
-
fallbackFailedDb: roundDb(de.fallbackFailedDb),
|
|
3296
|
-
fallbackFrameIndex: de.fallbackFrameIndex,
|
|
3297
|
-
fallbackThresholdDb: roundDb(de.fallbackThresholdDb),
|
|
3298
|
-
blankSuspects: drain?.blankSuspects ?? 0,
|
|
3299
|
-
blankDeterministicAccepts: drain?.blankDeterministicAccepts ?? 0,
|
|
3300
|
-
blankRecaptures: drain?.blankRecaptures ?? 0,
|
|
3301
|
-
boundaryFrames: perfs.reduce((sum, p) => sum + (p.deBoundaryFrames ?? 0), 0),
|
|
3302
|
-
ncprFallbacks: perfs.reduce((sum, p) => sum + (p.deNcprFallbacks ?? 0), 0),
|
|
3303
|
-
frameTimeouts: perfs.reduce((sum, p) => sum + (p.deFrameTimeouts ?? 0), 0)
|
|
3304
|
-
};
|
|
3305
|
-
}
|
|
3306
|
-
function maxDefined(values) {
|
|
3307
|
-
const present = values.filter((v) => typeof v === "number");
|
|
3308
|
-
return present.length > 0 ? Math.max(...present) : void 0;
|
|
3309
|
-
}
|
|
3310
|
-
function aggregateChromeMemory(perfs) {
|
|
3311
|
-
const sampled = perfs.filter((p) => (p.chromeMemorySamples ?? 0) > 0);
|
|
3312
|
-
if (sampled.length === 0) return void 0;
|
|
3313
|
-
return {
|
|
3314
|
-
browserRssPeakMb: maxDefined(sampled.map((p) => p.chromeBrowserRssPeakMb)),
|
|
3315
|
-
rendererRssPeakMb: maxDefined(sampled.map((p) => p.chromeRendererRssPeakMb)),
|
|
3316
|
-
// Last samples are per session; summing approximates the whole fleet's
|
|
3317
|
-
// footprint at the end of capture (workers run concurrently).
|
|
3318
|
-
rssLastMb: sampled.reduce((sum, p) => sum + (p.chromeRssLastMb ?? 0), 0),
|
|
3319
|
-
gpuProcessSeenLastSample: sampled.some((p) => p.chromeGpuProcessSeenLastSample === true),
|
|
3320
|
-
samples: sampled.reduce((sum, p) => sum + (p.chromeMemorySamples ?? 0), 0)
|
|
3321
|
-
};
|
|
3322
|
-
}
|
|
3323
|
-
function aggregateDedup(perfs) {
|
|
3324
|
-
if (perfs.length === 0) return void 0;
|
|
3325
|
-
const armed = perfs.some((p) => p.staticDedupArmed);
|
|
3326
|
-
const skipReasons = armed ? [] : [
|
|
3327
|
-
...new Set(perfs.map((p) => p.staticDedupSkipReason).filter((r) => !!r))
|
|
3328
|
-
].sort();
|
|
3329
|
-
const verificationPerfs = perfs.filter((perf) => perf.staticDedupVerificationOutcome);
|
|
3330
|
-
const verificationOutcomes = [
|
|
3331
|
-
...new Set(
|
|
3332
|
-
verificationPerfs.map((perf) => perf.staticDedupVerificationOutcome).filter((outcome) => outcome != null)
|
|
3333
|
-
)
|
|
3334
|
-
].sort();
|
|
3335
|
-
return {
|
|
3336
|
-
enabled: perfs.some((p) => p.staticDedupEnabled),
|
|
3337
|
-
armed,
|
|
3338
|
-
predictedFrames: perfs.reduce((sum, p) => sum + (p.staticDedupPredicted ?? 0), 0),
|
|
3339
|
-
reusedFrames: perfs.reduce((sum, p) => sum + (p.staticDedupReused ?? 0), 0),
|
|
3340
|
-
skipReason: skipReasons.length > 0 ? skipReasons.join("|") : void 0,
|
|
3341
|
-
...verificationPerfs.length === 0 ? {} : {
|
|
3342
|
-
verifiedFrames: verificationPerfs.reduce(
|
|
3343
|
-
(sum, perf) => sum + (perf.staticDedupVerified ?? 0),
|
|
3344
|
-
0
|
|
3345
|
-
),
|
|
3346
|
-
verificationOutcomes,
|
|
3347
|
-
plannedRuns: verificationPerfs.reduce(
|
|
3348
|
-
(sum, perf) => sum + (perf.staticDedupVerificationPlannedRuns ?? 0),
|
|
3349
|
-
0
|
|
3350
|
-
),
|
|
3351
|
-
completedRuns: verificationPerfs.reduce(
|
|
3352
|
-
(sum, perf) => sum + (perf.staticDedupVerificationCompletedRuns ?? 0),
|
|
3353
|
-
0
|
|
3354
|
-
),
|
|
3355
|
-
screenshots: verificationPerfs.reduce(
|
|
3356
|
-
(sum, perf) => sum + (perf.staticDedupVerificationScreenshots ?? 0),
|
|
3357
|
-
0
|
|
3358
|
-
),
|
|
3359
|
-
seeks: verificationPerfs.reduce(
|
|
3360
|
-
(sum, perf) => sum + (perf.staticDedupVerificationSeeks ?? 0),
|
|
3361
|
-
0
|
|
3362
|
-
),
|
|
3363
|
-
comparisons: verificationPerfs.reduce(
|
|
3364
|
-
(sum, perf) => sum + (perf.staticDedupVerificationComparisons ?? 0),
|
|
3365
|
-
0
|
|
3366
|
-
),
|
|
3367
|
-
verificationElapsedMs: verificationPerfs.reduce(
|
|
3368
|
-
(sum, perf) => sum + (perf.staticDedupVerificationElapsedMs ?? 0),
|
|
3369
|
-
0
|
|
3370
|
-
)
|
|
3371
|
-
}
|
|
3372
|
-
};
|
|
3373
|
-
}
|
|
3374
|
-
function aggregateBeginFrameReuse(perfs) {
|
|
3375
|
-
const noDamageFrames = perfs.reduce((sum, p) => sum + (p.beginFrameNoDamage ?? 0), 0);
|
|
3376
|
-
const hasDamageFrames = perfs.reduce((sum, p) => sum + (p.beginFrameHasDamage ?? 0), 0);
|
|
3377
|
-
if (noDamageFrames + hasDamageFrames === 0) return void 0;
|
|
3378
|
-
return { noDamageFrames, hasDamageFrames };
|
|
3379
|
-
}
|
|
3380
|
-
function buildRenderPerfSummary(input) {
|
|
3381
|
-
return {
|
|
3382
|
-
renderId: input.job.id,
|
|
3383
|
-
totalElapsedMs: input.totalElapsedMs,
|
|
3384
|
-
// RenderPerfSummary surfaces fps as a decimal because it lands in JSON
|
|
3385
|
-
// payloads (CLI telemetry, regression-harness reports) where a single
|
|
3386
|
-
// number is friendlier than `{num,den}`. Callers needing the rational
|
|
3387
|
-
// back can read `job.config.fps`.
|
|
3388
|
-
fps: fpsToNumber4(input.job.config.fps),
|
|
3389
|
-
quality: input.job.config.quality,
|
|
3390
|
-
workers: input.workerCount,
|
|
3391
|
-
workerSizing: input.workerSizing,
|
|
3392
|
-
chunkedEncode: input.enableChunkedEncode,
|
|
3393
|
-
chunkSizeFrames: input.enableChunkedEncode ? input.chunkedEncodeSize : null,
|
|
3394
|
-
compositionDurationSeconds: input.compositionDurationSeconds,
|
|
3395
|
-
totalFrames: input.totalFrames,
|
|
3396
|
-
resolution: { width: input.outputWidth, height: input.outputHeight },
|
|
3397
|
-
videoCount: input.videoCount,
|
|
3398
|
-
audioCount: input.audioCount,
|
|
3399
|
-
stages: input.perfStages,
|
|
3400
|
-
videoExtractBreakdown: input.videoExtractBreakdown,
|
|
3401
|
-
tmpPeakBytes: input.tmpPeakBytes,
|
|
3402
|
-
captureCalibration: input.captureCalibration ? {
|
|
3403
|
-
sampledFrames: input.captureCalibration.samples.map((sample) => sample.frameIndex),
|
|
3404
|
-
p95Ms: input.captureCalibration.estimate.p95Ms,
|
|
3405
|
-
multiplier: input.captureCalibration.estimate.multiplier,
|
|
3406
|
-
reasons: input.captureCalibration.estimate.reasons
|
|
3407
|
-
} : void 0,
|
|
3408
|
-
captureAttempts: input.captureAttempts.length > 0 ? input.captureAttempts : void 0,
|
|
3409
|
-
hdrDiagnostics: input.hdrDiagnostics.videoExtractionFailures > 0 || input.hdrDiagnostics.imageDecodeFailures > 0 ? { ...input.hdrDiagnostics } : void 0,
|
|
3410
|
-
hdrPerf: input.hdrPerf ? finalizeHdrPerf(input.hdrPerf) : void 0,
|
|
3411
|
-
observability: input.observability,
|
|
3412
|
-
captureAvgMs: input.totalFrames > 0 ? Math.round(
|
|
3413
|
-
(input.perfStages.captureFrameMs ?? input.perfStages.captureMs ?? 0) / input.totalFrames
|
|
3414
|
-
) : void 0,
|
|
3415
|
-
subTimelineWait: worstSubTimelineWaitOutcome(input.dedupPerfs),
|
|
3416
|
-
captureP50Ms: (() => {
|
|
3417
|
-
const withSamples = input.dedupPerfs.filter((p) => (p.p50TotalMs ?? 0) > 0);
|
|
3418
|
-
if (withSamples.length === 0) return void 0;
|
|
3419
|
-
return withSamples.reduce((a, b) => b.frames > a.frames ? b : a).p50TotalMs;
|
|
3420
|
-
})(),
|
|
3421
|
-
peakRssMb: Math.round(input.peakRssBytes / (1024 * 1024)),
|
|
3422
|
-
peakHeapUsedMb: Math.round(input.peakHeapUsedBytes / (1024 * 1024)),
|
|
3423
|
-
staticDedup: aggregateDedup(input.dedupPerfs),
|
|
3424
|
-
chromeMemory: aggregateChromeMemory(input.dedupPerfs),
|
|
3425
|
-
beginFrameReuse: aggregateBeginFrameReuse(input.dedupPerfs),
|
|
3426
|
-
drawElement: aggregateDrawElement(
|
|
3427
|
-
input.dedupPerfs,
|
|
3428
|
-
input.drawElement ?? { selfVerifyFallback: false }
|
|
3429
|
-
),
|
|
3430
|
-
host: {
|
|
3431
|
-
platform: platform(),
|
|
3432
|
-
arch: arch(),
|
|
3433
|
-
cpuCount: cpus().length,
|
|
3434
|
-
totalMemMb: Math.round(totalmem() / (1024 * 1024)),
|
|
3435
|
-
nodeVersion: process.version,
|
|
3436
|
-
gpuDisabled: input.gpuDisabled
|
|
3437
|
-
}
|
|
3438
|
-
};
|
|
3439
|
-
}
|
|
3440
|
-
|
|
3441
|
-
// src/services/render/stages/captureStreamingStage.ts
|
|
3442
3445
|
var DEFAULT_CAPTURE_STALL_MS = 6e4;
|
|
3443
3446
|
var DE_STALL_POLL_MS = 5e3;
|
|
3444
3447
|
var STALL_ADVICE = "Chrome stopped answering. If another app is keeping the GPU or CPU busy (a 3D render, a game, another export), let it finish or render one job at a time, then retry.";
|
|
3448
|
+
function poolFailure(error, probeSession) {
|
|
3449
|
+
return wrapCaptureStageError(error, probeSession?.browserConsoleBuffer ?? []);
|
|
3450
|
+
}
|
|
3445
3451
|
var ParallelCaptureStallError = class extends Error {
|
|
3446
3452
|
variant;
|
|
3447
3453
|
constructor(args) {
|
|
@@ -3888,7 +3894,7 @@ async function runCaptureStreamingStage(input) {
|
|
|
3888
3894
|
}
|
|
3889
3895
|
);
|
|
3890
3896
|
} catch (err) {
|
|
3891
|
-
if (parallelDrainError) throw parallelDrainError;
|
|
3897
|
+
if (parallelDrainError) throw poolFailure(parallelDrainError, probeSession);
|
|
3892
3898
|
if (stalled && abortSignal?.aborted !== true) {
|
|
3893
3899
|
throw new ParallelCaptureStallError({
|
|
3894
3900
|
variant: "pool",
|
|
@@ -3899,13 +3905,15 @@ async function runCaptureStreamingStage(input) {
|
|
|
3899
3905
|
phaseSummary: phaseSummary()
|
|
3900
3906
|
});
|
|
3901
3907
|
}
|
|
3902
|
-
throw err;
|
|
3908
|
+
throw poolFailure(err, probeSession);
|
|
3903
3909
|
} finally {
|
|
3904
3910
|
clearInterval(stallTimer);
|
|
3905
3911
|
abortSignal?.removeEventListener("abort", forwardParentAbort);
|
|
3906
3912
|
}
|
|
3907
|
-
if (parallelDrainError) throw parallelDrainError;
|
|
3913
|
+
if (parallelDrainError) throw poolFailure(parallelDrainError, probeSession);
|
|
3908
3914
|
pushWorkerDedupPerfs(workerResults, dedupPerfs);
|
|
3915
|
+
const workerPageErrors = [];
|
|
3916
|
+
pushWorkerPageErrors(workerResults, workerPageErrors);
|
|
3909
3917
|
if (parallelGuardRan) {
|
|
3910
3918
|
deDrainStats = parallelStats;
|
|
3911
3919
|
}
|
|
@@ -3915,6 +3923,7 @@ async function runCaptureStreamingStage(input) {
|
|
|
3915
3923
|
await closeCaptureSession(probeSession);
|
|
3916
3924
|
probeSession = null;
|
|
3917
3925
|
}
|
|
3926
|
+
lastBrowserConsole = withWorkerPageErrors(lastBrowserConsole, workerPageErrors);
|
|
3918
3927
|
} else {
|
|
3919
3928
|
const videoInjector = createRenderVideoFrameInjector();
|
|
3920
3929
|
const session = probeSession ?? await createCaptureSession(
|
|
@@ -4361,8 +4370,9 @@ async function runCaptureSegmentedStage(input) {
|
|
|
4361
4370
|
|
|
4362
4371
|
// src/services/render/segmentManifest.ts
|
|
4363
4372
|
import { createHash as createHash2 } from "node:crypto";
|
|
4364
|
-
import { existsSync as existsSync7, mkdirSync as mkdirSync4, readFileSync as readFileSync4,
|
|
4373
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync4, readFileSync as readFileSync4, statSync as statSync3, writeFileSync as writeFileSync3 } from "node:fs";
|
|
4365
4374
|
import { join as join10 } from "node:path";
|
|
4375
|
+
import { renameWithRetry as renameWithRetry2 } from "@hyperframes/engine";
|
|
4366
4376
|
var MANIFEST_FILENAME = "segments.json";
|
|
4367
4377
|
function computeSegmentPlanHash(input) {
|
|
4368
4378
|
const ordered = [
|
|
@@ -4418,7 +4428,7 @@ function writeSegmentManifest(segmentDir, manifest) {
|
|
|
4418
4428
|
mkdirSync4(segmentDir, { recursive: true });
|
|
4419
4429
|
const tmp = join10(segmentDir, `${MANIFEST_FILENAME}.${process.pid}.tmp`);
|
|
4420
4430
|
writeFileSync3(tmp, JSON.stringify(manifest, null, 2), "utf-8");
|
|
4421
|
-
|
|
4431
|
+
renameWithRetry2(tmp, join10(segmentDir, MANIFEST_FILENAME));
|
|
4422
4432
|
}
|
|
4423
4433
|
async function probeSegmentFrameCount(path, probe) {
|
|
4424
4434
|
try {
|
|
@@ -5470,19 +5480,11 @@ import {
|
|
|
5470
5480
|
|
|
5471
5481
|
// src/services/animatedGifPrep.ts
|
|
5472
5482
|
import { createHash as createHash4 } from "node:crypto";
|
|
5473
|
-
import {
|
|
5474
|
-
copyFileSync as copyFileSync2,
|
|
5475
|
-
existsSync as existsSync8,
|
|
5476
|
-
mkdirSync as mkdirSync5,
|
|
5477
|
-
readFileSync as readFileSync5,
|
|
5478
|
-
renameSync as renameSync3,
|
|
5479
|
-
rmSync as rmSync6,
|
|
5480
|
-
statSync as statSync4
|
|
5481
|
-
} from "node:fs";
|
|
5483
|
+
import { copyFileSync as copyFileSync2, existsSync as existsSync8, mkdirSync as mkdirSync5, readFileSync as readFileSync5, rmSync as rmSync6, statSync as statSync4 } from "node:fs";
|
|
5482
5484
|
import { dirname as dirname5, isAbsolute as isAbsolute2, join as join12, resolve as resolve5 } from "node:path";
|
|
5483
5485
|
import { parseHTML as parseHTML3 } from "linkedom";
|
|
5484
5486
|
import { parseAnimatedGifMetadata } from "@hyperframes/core";
|
|
5485
|
-
import { DEFAULT_VP9_CPU_USED, runFfmpeg as runFfmpeg2 } from "@hyperframes/engine";
|
|
5487
|
+
import { DEFAULT_VP9_CPU_USED, runFfmpeg as runFfmpeg2, renameWithRetry as renameWithRetry3 } from "@hyperframes/engine";
|
|
5486
5488
|
var PREPARED_GIF_SUBDIR = "_animated_gif";
|
|
5487
5489
|
var CACHE_SCHEMA = "hfgif-v1";
|
|
5488
5490
|
function splitUrlSuffix(src) {
|
|
@@ -5661,7 +5663,7 @@ async function ensurePreparedWebm(input) {
|
|
|
5661
5663
|
throw new Error("Animated GIF transcode produced an empty output");
|
|
5662
5664
|
}
|
|
5663
5665
|
if (!isUsableFile(input.cachePath)) {
|
|
5664
|
-
|
|
5666
|
+
renameWithRetry3(tmpPath, input.cachePath);
|
|
5665
5667
|
} else {
|
|
5666
5668
|
rmSync6(tmpPath, { force: true });
|
|
5667
5669
|
}
|
|
@@ -8730,7 +8732,7 @@ import {
|
|
|
8730
8732
|
|
|
8731
8733
|
// src/services/render/audioPadTrim.ts
|
|
8732
8734
|
import { spawn } from "node:child_process";
|
|
8733
|
-
import { mkdtempSync as mkdtempSync3,
|
|
8735
|
+
import { mkdtempSync as mkdtempSync3, rmSync as rmSync7 } from "node:fs";
|
|
8734
8736
|
import { dirname as dirname7, join as join17 } from "node:path";
|
|
8735
8737
|
import {
|
|
8736
8738
|
DEFAULT_CONFIG,
|
|
@@ -8739,6 +8741,7 @@ import {
|
|
|
8739
8741
|
extractAudioMetadata as extractAudioMetadata3,
|
|
8740
8742
|
getFfprobeBinary,
|
|
8741
8743
|
ManagedChildProcess,
|
|
8744
|
+
renameWithRetry as renameWithRetry4,
|
|
8742
8745
|
runFfmpeg as runFfmpeg4,
|
|
8743
8746
|
trackChildProcess
|
|
8744
8747
|
} from "@hyperframes/engine";
|
|
@@ -8994,7 +8997,7 @@ async function enforceAacTruePeak(input) {
|
|
|
8994
8997
|
}
|
|
8995
8998
|
if (truePeakDbfs <= AAC_DELIVERY_TRUE_PEAK_DBFS) {
|
|
8996
8999
|
if (measuredPath !== correctedPath) return { success: true };
|
|
8997
|
-
|
|
9000
|
+
renameWithRetry4(correctedPath, input.audioPath);
|
|
8998
9001
|
return { success: true, loweredDb: Number((-attenuationDb).toFixed(2)) };
|
|
8999
9002
|
}
|
|
9000
9003
|
if (pass === MAX_TRUE_PEAK_CORRECTION_PASSES) break;
|
|
@@ -9184,6 +9187,7 @@ async function runAudioStage(input) {
|
|
|
9184
9187
|
const result = await mixAudioForDelivery(input, duration, pcmSourcePath);
|
|
9185
9188
|
let audioLoweredDb;
|
|
9186
9189
|
if (result.hasAudio) {
|
|
9190
|
+
const guardStart = Date.now();
|
|
9187
9191
|
const peak = await constrainAacTruePeak({
|
|
9188
9192
|
audioPath: result.audioOutputPath,
|
|
9189
9193
|
sourcePath: pcmSourcePath,
|
|
@@ -9193,6 +9197,7 @@ async function runAudioStage(input) {
|
|
|
9193
9197
|
});
|
|
9194
9198
|
if (!peak.success) throw encoderFailureError("Audio true-peak check failed", peak);
|
|
9195
9199
|
audioLoweredDb = peak.loweredDb;
|
|
9200
|
+
input.log?.info("[audio] phases", { ...result.audioPhaseMs, guard: Date.now() - guardStart });
|
|
9196
9201
|
}
|
|
9197
9202
|
return { ...result, audioLoweredDb, audioProcessMs: Date.now() - stageStart };
|
|
9198
9203
|
} finally {
|
|
@@ -9218,6 +9223,7 @@ async function mixAudioForDelivery(input, duration, pcmSourcePath) {
|
|
|
9218
9223
|
let hasAudio = false;
|
|
9219
9224
|
let audioError;
|
|
9220
9225
|
let audioFailures;
|
|
9226
|
+
let audioPhaseMs;
|
|
9221
9227
|
if (audios.length > 0) {
|
|
9222
9228
|
let audioResult;
|
|
9223
9229
|
try {
|
|
@@ -9267,6 +9273,7 @@ async function mixAudioForDelivery(input, duration, pcmSourcePath) {
|
|
|
9267
9273
|
assertAudioNotInterrupted(audioResult.failures);
|
|
9268
9274
|
hasAudio = audioResult.success;
|
|
9269
9275
|
audioFailures = audioResult.failures;
|
|
9276
|
+
audioPhaseMs = audioResult.phaseMs;
|
|
9270
9277
|
if (!hasAudio) {
|
|
9271
9278
|
audioError = audioResult.error ?? "audio mix failed for an unknown reason";
|
|
9272
9279
|
for (const failure of audioResult.failures ?? []) {
|
|
@@ -9285,7 +9292,8 @@ async function mixAudioForDelivery(input, duration, pcmSourcePath) {
|
|
|
9285
9292
|
audioOutputPath,
|
|
9286
9293
|
hasAudio,
|
|
9287
9294
|
audioError,
|
|
9288
|
-
audioFailures
|
|
9295
|
+
audioFailures,
|
|
9296
|
+
audioPhaseMs
|
|
9289
9297
|
};
|
|
9290
9298
|
}
|
|
9291
9299
|
|
|
@@ -9414,6 +9422,7 @@ async function runCaptureStage(input) {
|
|
|
9414
9422
|
let { workerCount } = plan;
|
|
9415
9423
|
const { forceScreenshot } = plan;
|
|
9416
9424
|
let lastBrowserConsole = [];
|
|
9425
|
+
const workerPageErrors = [];
|
|
9417
9426
|
let captureBeyondViewport = probeSession?.options.captureBeyondViewport;
|
|
9418
9427
|
const captureCfg = cfg.forceScreenshot === forceScreenshot ? cfg : { ...cfg, forceScreenshot };
|
|
9419
9428
|
if (frameRange !== void 0) {
|
|
@@ -9451,6 +9460,7 @@ async function runCaptureStage(input) {
|
|
|
9451
9460
|
abortSignal,
|
|
9452
9461
|
frameRangeStart: frameRange?.startFrame,
|
|
9453
9462
|
dedupPerfs,
|
|
9463
|
+
pageErrorLines: workerPageErrors,
|
|
9454
9464
|
onProgress: (progress) => {
|
|
9455
9465
|
if (progress.latestWorkerPhase) {
|
|
9456
9466
|
if (progress.capturedFrames === 0) reportWorkerStartup(job, progress, onProgress);
|
|
@@ -9471,6 +9481,11 @@ async function runCaptureStage(input) {
|
|
|
9471
9481
|
},
|
|
9472
9482
|
cfg: captureCfg,
|
|
9473
9483
|
log
|
|
9484
|
+
}).catch((error) => {
|
|
9485
|
+
throw wrapCaptureStageError(
|
|
9486
|
+
error,
|
|
9487
|
+
withWorkerPageErrors(probeSession?.browserConsoleBuffer ?? [], workerPageErrors)
|
|
9488
|
+
);
|
|
9474
9489
|
});
|
|
9475
9490
|
captureAttempts.push(...attempts);
|
|
9476
9491
|
const lastAttempt = attempts[attempts.length - 1];
|
|
@@ -9483,6 +9498,7 @@ async function runCaptureStage(input) {
|
|
|
9483
9498
|
await closeCaptureSession5(probeSession);
|
|
9484
9499
|
probeSession = null;
|
|
9485
9500
|
}
|
|
9501
|
+
lastBrowserConsole = withWorkerPageErrors(lastBrowserConsole, workerPageErrors);
|
|
9486
9502
|
} else {
|
|
9487
9503
|
const sequential = await runSequentialDiskCapture(
|
|
9488
9504
|
input,
|
|
@@ -10798,7 +10814,7 @@ function videoEncoderOptions(input, engineCfg) {
|
|
|
10798
10814
|
};
|
|
10799
10815
|
}
|
|
10800
10816
|
function canEncodeWhileCapturing(input, workerCount, cpuCount) {
|
|
10801
|
-
return workerCount > 1 && workerCount < cpuCount && !input.isPngSequence && !input.isGif && !input.enableChunkedEncode && input.preset.codec === "h264" && !input.preset.hdr && input.job.config.useGpu !== true && input.captureImageFormat === "jpeg"
|
|
10817
|
+
return workerCount > 1 && workerCount < cpuCount && !input.isPngSequence && !input.isGif && !input.enableChunkedEncode && input.preset.codec === "h264" && !input.preset.hdr && input.job.config.useGpu !== true && input.captureImageFormat === "jpeg";
|
|
10802
10818
|
}
|
|
10803
10819
|
async function readLandedFrame(workerPath, mergedPath) {
|
|
10804
10820
|
if (workerPath !== void 0) {
|
|
@@ -11453,6 +11469,7 @@ async function executeDiskCaptureWithAdaptiveRetry(options) {
|
|
|
11453
11469
|
options.cfg
|
|
11454
11470
|
);
|
|
11455
11471
|
pushWorkerDedupPerfs(workerResults, options.dedupPerfs);
|
|
11472
|
+
if (options.pageErrorLines) pushWorkerPageErrors(workerResults, options.pageErrorLines);
|
|
11456
11473
|
} finally {
|
|
11457
11474
|
await mergeWorkerFrames(attemptWorkDir, tasks, options.framesDir);
|
|
11458
11475
|
}
|
|
@@ -14069,7 +14086,9 @@ import {
|
|
|
14069
14086
|
getEncoderPreset as getEncoderPreset4,
|
|
14070
14087
|
normalizeVp9CpuUsed,
|
|
14071
14088
|
resolveConfig as resolveConfig3,
|
|
14072
|
-
declareContentAddressedUrl
|
|
14089
|
+
declareContentAddressedUrl,
|
|
14090
|
+
renameWithRetry as renameWithRetry6,
|
|
14091
|
+
declareProbeFactsUrl
|
|
14073
14092
|
} from "@hyperframes/engine";
|
|
14074
14093
|
|
|
14075
14094
|
// src/services/distributed/planFrameCost.ts
|
|
@@ -14139,6 +14158,7 @@ var FIELD_DELIMITER = Buffer.from([0]);
|
|
|
14139
14158
|
import { appendRenderProvenanceArgs, describeFfmpegFailure as describeFfmpegFailure3, runFfmpeg as runFfmpeg6 } from "@hyperframes/engine";
|
|
14140
14159
|
|
|
14141
14160
|
// src/services/distributed/mp4Stitch.ts
|
|
14161
|
+
import { renameWithRetry as renameWithRetry5 } from "@hyperframes/engine";
|
|
14142
14162
|
var SCAN_BYTES = 64 * 1024;
|
|
14143
14163
|
|
|
14144
14164
|
// src/services/distributed/chunkAudio.ts
|