hyperframes 0.8.176 → 0.8.178
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/bin/hyperframes.mjs +3 -0
- package/dist/{add-YZGUHLDP.js → add-C4GN5ZDP.js} +12 -12
- package/dist/{animatedGifPrep-6SPYXSHE.js → animatedGifPrep-S6XXOOXK.js} +7 -7
- package/dist/api.d.ts +2 -0
- package/dist/api.js +15 -15
- package/dist/{asset-YPC34MTV.js → asset-WTZ44Q7G.js} +2 -2
- package/dist/{assetCataloger-5GGNQC3Y.js → assetCataloger-MSAMR77T.js} +7 -7
- package/dist/{audio-33JHU37L.js → audio-ZSWOKO3D.js} +14 -14
- package/dist/{auth-UUIHOS2D.js → auth-EUSWPXME.js} +1 -1
- package/dist/{autoUpdate-F747BE3R.js → autoUpdate-WWXRJ2W7.js} +2 -2
- package/dist/{backgroundChecks-3YLO2CSC.js → backgroundChecks-B2IJHAP6.js} +3 -3
- package/dist/backgroundChecksWorker.js +3 -3
- package/dist/{batchRender-KXXTVNPB.js → batchRender-OOQYGH5A.js} +4 -4
- package/dist/{beats-DQDV2ZFS.js → beats-OJT75KQY.js} +5 -5
- package/dist/{benchmark-ZPPZEIHZ.js → benchmark-EZTB4ITW.js} +9 -9
- package/dist/{browser-ZFLEP3E6.js → browser-DNHBS5C7.js} +9 -8
- package/dist/{bundleWithLocalizedFonts-PMRGOQWD.js → bundleWithLocalizedFonts-GJAML42J.js} +2 -2
- package/dist/{capture-6XCCIPT4.js → capture-YRS6SZ6B.js} +11 -11
- package/dist/{capture-5OW6VNXU.js → capture-ZBGAJYVH.js} +2 -2
- package/dist/captureCompositionFrame-Z33NWUED.js +88 -0
- package/dist/{catalog-3A6KKCWF.js → catalog-YF23PXV2.js} +25 -17
- package/dist/{catch-up-KPGCLN4C.js → catch-up-YZZDUDRQ.js} +5 -5
- package/dist/{check-I3XLXS77.js → check-NVGQ5PMF.js} +60 -49
- package/dist/{checkBrowser-KX7LNAFA.js → checkBrowser-JX22QQDH.js} +79 -59
- package/dist/{chunk-42T7OP4O.js → chunk-32GKQ73S.js} +1 -1
- package/dist/{chunk-3Q4Y33FT.js → chunk-3EJYUZHW.js} +20 -18
- package/dist/{chunk-L6XT6GSV.js → chunk-52L2L46Q.js} +1 -1
- package/dist/chunk-537IYAEE.js +80 -0
- package/dist/{chunk-USEUH5VV.js → chunk-5PK3RLSB.js} +2 -2
- package/dist/{chunk-GVIH4ZQY.js → chunk-5RS2FIZU.js} +1 -1
- package/dist/{chunk-VER46LXI.js → chunk-62OXHKLS.js} +2 -2
- package/dist/{chunk-T76PLPD6.js → chunk-634HSJ3J.js} +2 -1
- package/dist/{chunk-HVMHVW5G.js → chunk-74Z2T3YM.js} +1 -1
- package/dist/{chunk-5TGVURKQ.js → chunk-7IAVKLNC.js} +1 -1
- package/dist/{chunk-L3LJVYXS.js → chunk-A2BB2XQU.js} +2 -2
- package/dist/{chunk-DQY6WTF7.js → chunk-A3RUVTGB.js} +1 -1
- package/dist/{chunk-OYEDHVSI.js → chunk-AFKVI7FJ.js} +1 -1
- package/dist/{chunk-VEQ7DKPG.js → chunk-AHS5QYKF.js} +1 -1
- package/dist/{chunk-FFDC5OWV.js → chunk-ALVXFXUG.js} +5 -3
- package/dist/{chunk-OMUKSCWE.js → chunk-AR5MS234.js} +13 -13
- package/dist/{chunk-R2TVJ4DW.js → chunk-AYEWZYYC.js} +1 -1
- package/dist/{chunk-TNDNFZOK.js → chunk-BGKZ37BC.js} +2 -2
- package/dist/{chunk-LY2GLSOS.js → chunk-BJJ3QF7T.js} +1 -1
- package/dist/{chunk-5EA4C6RA.js → chunk-BNGRVR3Y.js} +6 -6
- package/dist/{chunk-EEVCXPUA.js → chunk-C4FH67KI.js} +2 -2
- package/dist/{chunk-MG66UO4N.js → chunk-CJRGV2JW.js} +1 -1
- package/dist/{chunk-7LU4ZHYV.js → chunk-DKGZR7QA.js} +1 -1
- package/dist/{chunk-XRKMITSS.js → chunk-E24HSMZV.js} +12 -51
- package/dist/{chunk-44XBAKKT.js → chunk-EBKIF46T.js} +2 -2
- package/dist/{chunk-RBOVQRMR.js → chunk-EINNFZAW.js} +7 -13
- package/dist/{chunk-EOOEC32M.js → chunk-EVMY7IPL.js} +22 -0
- package/dist/{chunk-PL4WM5XE.js → chunk-FIAQ4J45.js} +2 -2
- package/dist/{chunk-J53AJK3Q.js → chunk-FTWOVWHR.js} +2 -2
- package/dist/{chunk-X6ZRZWPZ.js → chunk-G3M4BIFN.js} +1 -1
- package/dist/{chunk-VDUTZXIJ.js → chunk-HFUMZZ4T.js} +5 -5
- package/dist/{chunk-MDTMWUJI.js → chunk-HNMRB77F.js} +1 -1
- package/dist/{chunk-GMJ3ILLW.js → chunk-ICMXC3MI.js} +7 -24
- package/dist/{chunk-LZT3NUTE.js → chunk-IE6O2VXV.js} +1 -1
- package/dist/{chunk-HTC3VGU3.js → chunk-J4GE3BCG.js} +29 -10
- package/dist/{chunk-X4PK5ZXP.js → chunk-LO4DHZLH.js} +3 -3
- package/dist/{chunk-NGRNAF5X.js → chunk-N66NVE65.js} +1 -1
- package/dist/{chunk-7XX4QGQV.js → chunk-N6S6V2DY.js} +52 -16
- package/dist/{chunk-LEILKM2N.js → chunk-O7PFPCQF.js} +193 -65
- package/dist/{chunk-KUOUUG33.js → chunk-ORM7SJ7K.js} +85 -43
- package/dist/chunk-PLNQW2C6.js +3805 -0
- package/dist/{chunk-JNL3RMDG.js → chunk-PU33GPG4.js} +1 -1
- package/dist/{chunk-W47D3KOB.js → chunk-RHWJKSGH.js} +1 -1
- package/dist/{chunk-B7DJQFAC.js → chunk-RTABHL2G.js} +3 -3
- package/dist/{chunk-K535ASAM.js → chunk-TINAVSGR.js} +1 -1
- package/dist/{chunk-C6TPGUWD.js → chunk-TTVHYD5R.js} +2 -2
- package/dist/{chunk-GOOB64LO.js → chunk-U2AIXPAQ.js} +2 -2
- package/dist/{chunk-BVXZYFAL.js → chunk-UIXHQ4QG.js} +7 -7
- package/dist/{chunk-QWCXGTOH.js → chunk-UOHQV6AV.js} +24 -12
- package/dist/{chunk-SURF34CK.js → chunk-UQEBSY5U.js} +1 -1
- package/dist/{chunk-5ZSLJXQX.js → chunk-UWPUEI5U.js} +2 -2
- package/dist/{chunk-BTCHRQNV.js → chunk-V6WIQWUB.js} +3 -3
- package/dist/{chunk-OUMYTLPP.js → chunk-VCDWVVDV.js} +11 -7
- package/dist/{chunk-YWSXFFO3.js → chunk-VU4JLRNH.js} +156 -76
- package/dist/{chunk-MLRCTTSD.js → chunk-XBZOYP4D.js} +96 -11
- package/dist/{chunk-X6HYBA4A.js → chunk-XSQWXUK2.js} +1 -1
- package/dist/{chunk-SSE6NWZI.js → chunk-Y6JLEN3P.js} +14 -14
- package/dist/{chunk-KRKSY2AE.js → chunk-YAPJOCSH.js} +1 -1
- package/dist/{chunk-NWEER3QY.js → chunk-YH7VQAKX.js} +2 -2
- package/dist/{chunk-DZMWNCHM.js → chunk-ZAJO3YCQ.js} +2 -2
- package/dist/{chunk-T6NA6TR3.js → chunk-ZAO7FTQM.js} +2 -2
- package/dist/{clean-6REGQY3I.js → clean-ODNP4ELD.js} +23 -23
- package/dist/cli.js +53 -53
- package/dist/{cloud-RAQZPMNP.js → cloud-2DACBBEP.js} +4 -4
- package/dist/{cloudrun-P35BPQCO.js → cloudrun-QSVGI2TT.js} +5 -5
- package/dist/commands/contrast-audit.browser.js +166 -22
- package/dist/{compare-XYFSHHMQ.js → compare-HMMGOM4F.js} +34 -34
- package/dist/{compiler-5TFPJPQQ.js → compiler-CQ6OKYT5.js} +2 -2
- package/dist/{component-CRAO6Q2E.js → component-C6OLXSIK.js} +3 -3
- package/dist/{compositions-4SHILZZX.js → compositions-MOGZ4ASK.js} +11 -11
- package/dist/{delete-ZS4AHMTY.js → delete-MDAYHORQ.js} +2 -2
- package/dist/{dist-U2HCECNB.js → dist-MHJYD5IZ.js} +6 -4
- package/dist/{doctor-OL4FYABY.js → doctor-VEKKYMQT.js} +12 -12
- package/dist/{events-Z3XZCRFZ.js → events-CSKJXRJU.js} +4 -4
- package/dist/{events-LIJBGTTX.js → events-SKMTX6HF.js} +2 -2
- package/dist/{feedback-OE6SB2VE.js → feedback-64AKUFHZ.js} +7 -7
- package/dist/{ffmpeg-CSJLJAQ3.js → ffmpeg-64E4VH6W.js} +7 -7
- package/dist/{figma-DMUCMO67.js → figma-YEY76ZPG.js} +3 -3
- package/dist/fontLocalizeCli.js +10 -10
- package/dist/{get-NQOQVUI5.js → get-YJS76PGZ.js} +2 -2
- package/dist/{gpuPolicy-C6JWEX7F.js → gpuPolicy-IGZOHHMX.js} +7 -7
- package/dist/{grade-compare-HLTHHQGH.js → grade-compare-35UEA52Z.js} +35 -35
- package/dist/{help-ZAXWHAYF.js → help-I5TCDUVH.js} +1 -1
- package/dist/{history-CMY7ZEEW.js → history-7BKIWSP2.js} +11 -11
- package/dist/hyperframe-runtime.js +57 -55
- package/dist/hyperframe.manifest.json +1 -1
- package/dist/hyperframe.runtime.iife.js +57 -55
- package/dist/hyperframes-player.global.js +1 -1
- package/dist/{info-STR7EYI3.js → info-UEPOM2LV.js} +8 -8
- package/dist/{init-YSMKK5VG.js → init-HIB66K2S.js} +27 -27
- package/dist/{inspect-QV6DC6GO.js → inspect-634XIKDS.js} +33 -33
- package/dist/{installer-NY5E5HCO.js → installer-ADKWK4I4.js} +5 -5
- package/dist/{keyframes-HN3DW5FG.js → keyframes-7BJX3EVE.js} +7 -7
- package/dist/{lambda-PG3JKNWS.js → lambda-Q4TRSMHZ.js} +8 -8
- package/dist/{layout-O4QAR2XY.js → layout-6DUVSHEB.js} +33 -33
- package/dist/{lint-AY55R4UR.js → lint-UPFD4JQZ.js} +7 -7
- package/dist/{list-TH2KCVNN.js → list-M6OMQXJX.js} +2 -2
- package/dist/{login-TRCMRV4B.js → login-QH6JDXDP.js} +4 -4
- package/dist/{manager-2J4XGDZ3.js → manager-B4MSVFMK.js} +12 -10
- package/dist/{manager-HEUPD2YB.js → manager-V2QCCPOJ.js} +4 -3
- package/dist/{media-treatment-ET5QQSWP.js → media-treatment-SHFTIG4K.js} +14 -14
- package/dist/{models-RFUUSCG6.js → models-USEFHJFY.js} +11 -11
- package/dist/{motionShot-2ET565ZV.js → motionShot-HRM6NMT4.js} +15 -15
- package/dist/{normalize-audio-LUOJSD3W.js → normalize-audio-EP3HPQZB.js} +9 -9
- package/dist/{open-MVEOYQRQ.js → open-HXZEXQ4X.js} +12 -12
- package/dist/{parakeetRunner-3TG7EHWA.js → parakeetRunner-D5RSHQB2.js} +12 -12
- package/dist/{pipeline-JWGTH2BJ.js → pipeline-BDG52SPL.js} +8 -8
- package/dist/{play-I3WJPYXK.js → play-LSRQ6R66.js} +24 -24
- package/dist/{preflight-4WTT4D5X.js → preflight-GBPRLIM6.js} +9 -9
- package/dist/{present-DUZBKUYH.js → present-2VKAE63Q.js} +19 -19
- package/dist/{preview-7J5TBTRP.js → preview-MWH5CHTN.js} +18 -18
- package/dist/{producer-UZZQX6IJ.js → producer-W24FRIN7.js} +1 -1
- package/dist/{projectConfig-HDALEM6S.js → projectConfig-NQQDEDAK.js} +7 -7
- package/dist/{publication-NX4VC7UU.js → publication-7DW4IJPC.js} +3 -3
- package/dist/{publish-AZRRQUXM.js → publish-FJKJ74IF.js} +10 -10
- package/dist/{remove-background-OX5WZTXY.js → remove-background-JBOJAUIM.js} +9 -9
- package/dist/{render-HGT3EGIK.js → render-5TTZDI5N.js} +7 -14
- package/dist/{render-IYTGM6DE.js → render-BROS2AIU.js} +9 -9
- package/dist/{render-JUS2ROIN.js → render-JCYFNDWT.js} +42 -42
- package/dist/{render-batch-MUCDZ2WF.js → render-batch-FW56ZFGW.js} +8 -17
- package/dist/renderSetupWorker.js +2 -2
- package/dist/{resolver-FLQ42X2Y.js → resolver-UW6NYBJA.js} +5 -5
- package/dist/{sherpa-PRI3JLUP.js → sherpa-GWYCXYEP.js} +11 -11
- package/dist/skills/media-use/references/operations.md +3 -1
- package/dist/{skills-CZ6VW5SZ.js → skills-YNM5SIHQ.js} +6 -6
- package/dist/{skillsUpdateCheck-K4UKUAOC.js → skillsUpdateCheck-FNC6VALY.js} +3 -3
- package/dist/{snapshot-MPE4GIMJ.js → snapshot-6EMEL4O3.js} +44 -44
- package/dist/{src-SGPA7DM7.js → src-VUIKXEFU.js} +9 -9
- package/dist/{src-JGPFLYBL.js → src-XRFOS5LP.js} +6 -6
- package/dist/{staticProjectServer-DG4VZO4G.js → staticProjectServer-COEAKTGH.js} +17 -17
- package/dist/studio/assets/{hyperframes-player-DBHpVw8L.js → hyperframes-player-Dfw61RJK.js} +1 -1
- package/dist/studio/assets/{index-BkDF4Z-5.js → index-Bi6yVTq9.js} +118 -117
- package/dist/studio/assets/{index-DHRXpmtI.js → index-eTRj5rY2.js} +1 -1
- package/dist/studio/index.html +1 -1
- package/dist/{studio-api-RGNBVLLL.js → studio-api-455XWQPD.js} +12 -12
- package/dist/{studioServer-FWACRD3Y.js → studioServer-ZP2LJT7H.js} +57 -72
- package/dist/{telemetry-CHJA5JFQ.js → telemetry-HJQ7IO6R.js} +4 -4
- package/dist/{timeline-TZDMQBSM.js → timeline-CYW3YKMX.js} +23 -23
- package/dist/{tokens-B5KI7FBA.js → tokens-VOARLAAH.js} +2 -2
- package/dist/{transcribe-M7NO6XBP.js → transcribe-F6UOG57Z.js} +12 -12
- package/dist/{transcribe-VHUDXZET.js → transcribe-FJGNOR6R.js} +17 -16
- package/dist/{updateCheck-NMD6AFFG.js → updateCheck-IOLCO3XV.js} +2 -2
- package/dist/{upgrade-WGFMGJ5O.js → upgrade-BVW67SB7.js} +2 -2
- package/dist/{urlDownloader-FZ5ISJES.js → urlDownloader-QF7EBQC2.js} +6 -6
- package/dist/{validate-NM3GLUWX.js → validate-3NHIT4VT.js} +25 -25
- package/dist/{video-7CDAIWYC.js → video-2KGC3RIQ.js} +7 -7
- package/package.json +1 -2
- package/dist/chunk-EEXE43II.js +0 -3805
- package/dist/chunk-TWWSYAKJ.js +0 -24
- package/dist/{deploy-NKWMPAMH.js → deploy-3TTQZGTF.js} +4 -4
- package/dist/{destroy-UKP522AE.js → destroy-BEL232I5.js} +3 -3
|
@@ -8,8 +8,9 @@ import {
|
|
|
8
8
|
parseEncoderOptions
|
|
9
9
|
} from "./chunk-KLIKCX6Q.js";
|
|
10
10
|
import {
|
|
11
|
+
RENDER_TEMP_DIR,
|
|
11
12
|
createStudioPositionSeekReapplyScript
|
|
12
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-EVMY7IPL.js";
|
|
13
14
|
import {
|
|
14
15
|
GENERIC_FAMILIES,
|
|
15
16
|
collectFontFamilyCustomProperties,
|
|
@@ -22,7 +23,7 @@ import {
|
|
|
22
23
|
EncoderInterruptedError,
|
|
23
24
|
encoderFailureError,
|
|
24
25
|
prepareAnimatedGifInputs
|
|
25
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-FIAQ4J45.js";
|
|
26
27
|
import {
|
|
27
28
|
BROWSER_GPU_NOT_SOFTWARE,
|
|
28
29
|
CaptureFailure,
|
|
@@ -151,7 +152,7 @@ import {
|
|
|
151
152
|
validateEngineConfigSnapshot,
|
|
152
153
|
verifyDiskDrawElementSamples,
|
|
153
154
|
writeCapturedFrame
|
|
154
|
-
} from "./chunk-
|
|
155
|
+
} from "./chunk-VU4JLRNH.js";
|
|
155
156
|
import {
|
|
156
157
|
assignBundledRuntimeCompositionIds,
|
|
157
158
|
buildVariablesByCompScript,
|
|
@@ -164,7 +165,7 @@ import {
|
|
|
164
165
|
isTemplateEntry,
|
|
165
166
|
parsesAsScript,
|
|
166
167
|
prepareFlattenedInnerRoot
|
|
167
|
-
} from "./chunk-
|
|
168
|
+
} from "./chunk-PU33GPG4.js";
|
|
168
169
|
import {
|
|
169
170
|
LOW_MEMORY_TOTAL_MB_THRESHOLD,
|
|
170
171
|
getCgroupMemoryLimitMb,
|
|
@@ -190,7 +191,7 @@ import {
|
|
|
190
191
|
resolveAbsoluteMediaStartSeconds,
|
|
191
192
|
resolveAuthoredTimingWindow,
|
|
192
193
|
toFps
|
|
193
|
-
} from "./chunk-
|
|
194
|
+
} from "./chunk-AHS5QYKF.js";
|
|
194
195
|
import {
|
|
195
196
|
COMPOSITION_SOURCE_URL,
|
|
196
197
|
HF_COLOR_GRADING_ATTR,
|
|
@@ -218,7 +219,7 @@ import {
|
|
|
218
219
|
shouldClampResolvedMediaDuration,
|
|
219
220
|
sourceTimeAt,
|
|
220
221
|
styleElementsFor
|
|
221
|
-
} from "./chunk-
|
|
222
|
+
} from "./chunk-PLNQW2C6.js";
|
|
222
223
|
import {
|
|
223
224
|
MAX_AUDIO_GAIN
|
|
224
225
|
} from "./chunk-UJKQWGFF.js";
|
|
@@ -236,10 +237,10 @@ import {
|
|
|
236
237
|
import {
|
|
237
238
|
redactKnownPaths,
|
|
238
239
|
redactTelemetryString
|
|
239
|
-
} from "./chunk-
|
|
240
|
+
} from "./chunk-634HSJ3J.js";
|
|
240
241
|
import {
|
|
241
242
|
chromeMajorCeiling
|
|
242
|
-
} from "./chunk-
|
|
243
|
+
} from "./chunk-537IYAEE.js";
|
|
243
244
|
import {
|
|
244
245
|
lintHyperframeHtml
|
|
245
246
|
} from "./chunk-GK2FIKIQ.js";
|
|
@@ -1582,7 +1583,6 @@ import { hostname, uptime } from "os";
|
|
|
1582
1583
|
import { dirname as dirname3, join as join4 } from "path";
|
|
1583
1584
|
var OWNER_FILE = "owner.json";
|
|
1584
1585
|
var TRANSACTION_BACKUP = "backup";
|
|
1585
|
-
var RENDER_TEMP_DIR = /^(work-[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}|hf-render|\..+\.hf-transaction)-[A-Za-z0-9]{6}$/;
|
|
1586
1586
|
var RENDER_JOB_DIR = /^[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}$/;
|
|
1587
1587
|
function pidScope() {
|
|
1588
1588
|
const attempt = (read) => {
|
|
@@ -5756,7 +5756,7 @@ function detectShaderTransitionUsage(html) {
|
|
|
5756
5756
|
}
|
|
5757
5757
|
return false;
|
|
5758
5758
|
}
|
|
5759
|
-
async function resolveMediaDuration(src, mediaStart, playbackRate, baseDir, downloadDir, tagName, elementIdentity, log) {
|
|
5759
|
+
async function resolveMediaDuration(src, mediaStart, playbackRate, baseDir, downloadDir, tagName, elementIdentity, log, urlByAbsentLocalPath) {
|
|
5760
5760
|
let filePath = src;
|
|
5761
5761
|
if (isHttpUrl(src)) {
|
|
5762
5762
|
if (!existsSync9(downloadDir)) mkdirSync5(downloadDir, { recursive: true });
|
|
@@ -5770,8 +5770,9 @@ async function resolveMediaDuration(src, mediaStart, playbackRate, baseDir, down
|
|
|
5770
5770
|
} else {
|
|
5771
5771
|
filePath = decodedUrlPath(src);
|
|
5772
5772
|
if (!filePath.startsWith("/")) filePath = join12(baseDir, filePath);
|
|
5773
|
+
filePath = urlByAbsentLocalPath?.get(filePath) ?? filePath;
|
|
5773
5774
|
}
|
|
5774
|
-
if (!existsSync9(filePath)) {
|
|
5775
|
+
if (!isHttpUrl(filePath) && !existsSync9(filePath)) {
|
|
5775
5776
|
return { duration: null, resolvedPath: filePath };
|
|
5776
5777
|
}
|
|
5777
5778
|
const withSrcContext = (error) => {
|
|
@@ -5834,7 +5835,7 @@ function markInferredVariableMediaDurations(html, unresolvedMedia) {
|
|
|
5834
5835
|
}
|
|
5835
5836
|
return changed ? document2.toString() : html;
|
|
5836
5837
|
}
|
|
5837
|
-
async function compileHtmlFile(html, baseDir, downloadDir, log) {
|
|
5838
|
+
async function compileHtmlFile(html, baseDir, downloadDir, log, urlByAbsentLocalPath) {
|
|
5838
5839
|
const { html: staticCompiled, unresolved } = compileTimingAttrs(html);
|
|
5839
5840
|
const mediaUnresolved = unresolved.filter(
|
|
5840
5841
|
(el) => (el.tagName === "video" || el.tagName === "audio") && el.src
|
|
@@ -5850,7 +5851,8 @@ async function compileHtmlFile(html, baseDir, downloadDir, log) {
|
|
|
5850
5851
|
downloadDir,
|
|
5851
5852
|
el.tagName,
|
|
5852
5853
|
el.id,
|
|
5853
|
-
log
|
|
5854
|
+
log,
|
|
5855
|
+
urlByAbsentLocalPath
|
|
5854
5856
|
).then(({ duration }) => ({ id: el.id, duration }))
|
|
5855
5857
|
)
|
|
5856
5858
|
);
|
|
@@ -5892,7 +5894,7 @@ async function compileHtmlFile(html, baseDir, downloadDir, log) {
|
|
|
5892
5894
|
compiledHtml = compiledHtml.replace(/(<audio\b[^>]*)\s+crossorigin(?:=["'][^"']*["'])?/gi, "$1");
|
|
5893
5895
|
return { html: compiledHtml, unresolvedCompositions };
|
|
5894
5896
|
}
|
|
5895
|
-
async function parseSubCompositions(html, projectDir, downloadDir, visited = /* @__PURE__ */ new Set()) {
|
|
5897
|
+
async function parseSubCompositions(html, projectDir, downloadDir, visited = /* @__PURE__ */ new Set(), urlByAbsentLocalPath) {
|
|
5896
5898
|
const subCompositions = /* @__PURE__ */ new Map();
|
|
5897
5899
|
const { document: document2 } = parseHTML(html);
|
|
5898
5900
|
const compEls = document2.querySelectorAll("[data-composition-src]");
|
|
@@ -5918,13 +5920,16 @@ async function parseSubCompositions(html, projectDir, downloadDir, visited = /*
|
|
|
5918
5920
|
const { html: compiledSub } = await compileHtmlFile(
|
|
5919
5921
|
item.rawSubHtml,
|
|
5920
5922
|
dirname5(item.filePath),
|
|
5921
|
-
downloadDir
|
|
5923
|
+
downloadDir,
|
|
5924
|
+
void 0,
|
|
5925
|
+
urlByAbsentLocalPath
|
|
5922
5926
|
);
|
|
5923
5927
|
const nested = await parseSubCompositions(
|
|
5924
5928
|
compiledSub,
|
|
5925
5929
|
projectDir,
|
|
5926
5930
|
downloadDir,
|
|
5927
|
-
item.nestedVisited
|
|
5931
|
+
item.nestedVisited,
|
|
5932
|
+
urlByAbsentLocalPath
|
|
5928
5933
|
);
|
|
5929
5934
|
return {
|
|
5930
5935
|
srcPath: item.srcPath,
|
|
@@ -6682,9 +6687,16 @@ async function compileForRender(projectDir, htmlPath, downloadDir, options = {})
|
|
|
6682
6687
|
rawHtml,
|
|
6683
6688
|
projectDir,
|
|
6684
6689
|
downloadDir,
|
|
6685
|
-
options.log
|
|
6690
|
+
options.log,
|
|
6691
|
+
options.urlByAbsentLocalPath
|
|
6692
|
+
);
|
|
6693
|
+
const { subCompositions } = await parseSubCompositions(
|
|
6694
|
+
compiledHtml,
|
|
6695
|
+
projectDir,
|
|
6696
|
+
downloadDir,
|
|
6697
|
+
void 0,
|
|
6698
|
+
options.urlByAbsentLocalPath
|
|
6686
6699
|
);
|
|
6687
|
-
const { subCompositions } = await parseSubCompositions(compiledHtml, projectDir, downloadDir);
|
|
6688
6700
|
const fullHtml = ensureFullDocument(compiledHtml);
|
|
6689
6701
|
const inlinedHtml = inlineSubCompositions2(
|
|
6690
6702
|
fullHtml,
|
|
@@ -7180,6 +7192,7 @@ async function runCompileStage(input) {
|
|
|
7180
7192
|
allowSystemFontCapture,
|
|
7181
7193
|
abortSignal,
|
|
7182
7194
|
variables: input.variables,
|
|
7195
|
+
urlByAbsentLocalPath: input.urlByAbsentLocalPath,
|
|
7183
7196
|
animatedGifCacheDir: cfg.extractCacheDir ? join13(cfg.extractCacheDir, "animated-gif") : void 0,
|
|
7184
7197
|
ffmpegProcessTimeout: cfg.ffmpegProcessTimeout
|
|
7185
7198
|
});
|
|
@@ -8148,7 +8161,8 @@ async function runExtractVideosStage(input) {
|
|
|
8148
8161
|
abortSignal,
|
|
8149
8162
|
assertNotAborted,
|
|
8150
8163
|
materializeSymlinks,
|
|
8151
|
-
deferRangeExtraction
|
|
8164
|
+
deferRangeExtraction,
|
|
8165
|
+
urlByAbsentLocalPath
|
|
8152
8166
|
} = input;
|
|
8153
8167
|
const stage2Start = Date.now();
|
|
8154
8168
|
const extractionPolicy = resolveVideoExtractionPolicy();
|
|
@@ -8242,7 +8256,8 @@ async function runExtractVideosStage(input) {
|
|
|
8242
8256
|
maxTransientRetries: extractionPolicy.maxTransientRetries,
|
|
8243
8257
|
collectProbeFailures: extractionPolicy.failureMode === "enforce",
|
|
8244
8258
|
deferRangeExtraction,
|
|
8245
|
-
contentKeyedDirs: [join15(compiledDir, REMOTE_MEDIA_SUBDIR)]
|
|
8259
|
+
contentKeyedDirs: [join15(compiledDir, REMOTE_MEDIA_SUBDIR)],
|
|
8260
|
+
urlByAbsentLocalPath
|
|
8246
8261
|
},
|
|
8247
8262
|
abortSignal,
|
|
8248
8263
|
cfg,
|
|
@@ -8320,6 +8335,7 @@ async function runAudioStage(input) {
|
|
|
8320
8335
|
audioGain,
|
|
8321
8336
|
audios,
|
|
8322
8337
|
masterFxChain,
|
|
8338
|
+
urlByAbsentLocalPath,
|
|
8323
8339
|
abortSignal,
|
|
8324
8340
|
assertNotAborted,
|
|
8325
8341
|
log
|
|
@@ -8339,7 +8355,7 @@ async function runAudioStage(input) {
|
|
|
8339
8355
|
audioOutputPath,
|
|
8340
8356
|
duration,
|
|
8341
8357
|
abortSignal,
|
|
8342
|
-
{ ffmpegProcessTimeout, audioGain, masterFxChain },
|
|
8358
|
+
{ ffmpegProcessTimeout, audioGain, masterFxChain, urlByAbsentLocalPath },
|
|
8343
8359
|
compiledDir
|
|
8344
8360
|
);
|
|
8345
8361
|
} catch (err) {
|
|
@@ -13539,6 +13555,8 @@ function buildChunkCaptureOptions(input) {
|
|
|
13539
13555
|
// The controller's snapshot, so the first capture sees the in-process renderer's `__hfVariables`.
|
|
13540
13556
|
variables: encoder.variables,
|
|
13541
13557
|
subTimelineWaitMemo: {},
|
|
13558
|
+
skipReadinessVideoIds: input.skipReadinessVideoIds,
|
|
13559
|
+
videoMetadataHints: input.videoMetadataHints,
|
|
13542
13560
|
...videoCaptureBeyondViewport !== void 0 ? { captureBeyondViewport: videoCaptureBeyondViewport } : {},
|
|
13543
13561
|
// A fixed warmup count keeps `beginFrameTimeTicks` host-independent.
|
|
13544
13562
|
lockWarmupTicks: true,
|
|
@@ -13547,6 +13565,19 @@ function buildChunkCaptureOptions(input) {
|
|
|
13547
13565
|
}
|
|
13548
13566
|
async function extractDeferredVideoFramesForChunk(input) {
|
|
13549
13567
|
const deferred = input.planVideos.extracted.filter((video) => video.deferredRange);
|
|
13568
|
+
const remoteSources = input.remoteSources ?? {};
|
|
13569
|
+
for (const path of Object.keys(remoteSources)) {
|
|
13570
|
+
if (!deferred.some((video) => video.deferredRange.sourcePath === path)) {
|
|
13571
|
+
throw new RenderChunkValidationError(
|
|
13572
|
+
MISSING_PLAN_ARTIFACT,
|
|
13573
|
+
`[renderChunk] ${path} is read by URL but no deferred video uses it`
|
|
13574
|
+
);
|
|
13575
|
+
}
|
|
13576
|
+
defaultLogger.info("[renderChunk] reading video by URL", {
|
|
13577
|
+
path,
|
|
13578
|
+
url: remoteSources[path].split("?")[0]
|
|
13579
|
+
});
|
|
13580
|
+
}
|
|
13550
13581
|
if (deferred.length === 0) return [];
|
|
13551
13582
|
const table = createFrameLookupTable(
|
|
13552
13583
|
input.planVideos.videos,
|
|
@@ -13574,8 +13605,9 @@ async function extractDeferredVideoFramesForChunk(input) {
|
|
|
13574
13605
|
return { ...video, outputDir, framePaths: /* @__PURE__ */ new Map(), ownedByLookup: false };
|
|
13575
13606
|
}
|
|
13576
13607
|
const range = video.deferredRange;
|
|
13577
|
-
const
|
|
13578
|
-
|
|
13608
|
+
const remoteUrl = remoteSources[range.sourcePath];
|
|
13609
|
+
const sourcePath = remoteUrl ?? join27(input.planDir, ...range.sourcePath.split("/"));
|
|
13610
|
+
if (remoteUrl === void 0 && !existsSync17(sourcePath)) {
|
|
13579
13611
|
throw new RenderChunkValidationError(
|
|
13580
13612
|
MISSING_PLAN_ARTIFACT,
|
|
13581
13613
|
`[renderChunk] planDir is missing the source for video ${JSON.stringify(video.videoId)}: ${range.sourcePath}`
|
|
@@ -13915,6 +13947,16 @@ function collectPlanAssetShas(planDir, digests) {
|
|
|
13915
13947
|
}
|
|
13916
13948
|
return { compositionHtml, assets };
|
|
13917
13949
|
}
|
|
13950
|
+
var PLAN_REMOTE_FILES_RELATIVE_PATH = "meta/remote-files.json";
|
|
13951
|
+
function writePlanRemoteFiles(planDir, files) {
|
|
13952
|
+
if (files.length === 0) return;
|
|
13953
|
+
const sorted = [...files].sort((a, b) => a.path < b.path ? -1 : 1);
|
|
13954
|
+
writeFileSync6(join29(planDir, PLAN_REMOTE_FILES_RELATIVE_PATH), JSON.stringify(sorted), "utf-8");
|
|
13955
|
+
}
|
|
13956
|
+
function readPlanRemoteFiles(planDir) {
|
|
13957
|
+
const path = join29(planDir, PLAN_REMOTE_FILES_RELATIVE_PATH);
|
|
13958
|
+
return existsSync18(path) ? JSON.parse(readFileSync9(path, "utf-8")) : [];
|
|
13959
|
+
}
|
|
13918
13960
|
function recomputePlanHashFromPlanDir(planDir, digests) {
|
|
13919
13961
|
const planJsonPath = join29(planDir, "plan.json");
|
|
13920
13962
|
const encoderJsonPath = join29(planDir, "meta", "encoder.json");
|
|
@@ -14496,7 +14538,7 @@ function createVideoSourceShipper(input) {
|
|
|
14496
14538
|
let result = null;
|
|
14497
14539
|
for (const root of stagedRel === null ? [input.workCompiledDir, input.projectDir] : []) {
|
|
14498
14540
|
const rel = pathInside(root, srcPath);
|
|
14499
|
-
if (rel !== null && existsSync19(join31(input.planDir, "compiled", rel))) {
|
|
14541
|
+
if (rel !== null && (existsSync19(join31(input.planDir, "compiled", rel)) || input.isRemote(srcPath))) {
|
|
14500
14542
|
result = ["compiled", ...rel.split(sep2)].join("/");
|
|
14501
14543
|
break;
|
|
14502
14544
|
}
|
|
@@ -14574,8 +14616,17 @@ async function buildLocalExecutionPlan(projectDir, config, executionPlanDir, opt
|
|
|
14574
14616
|
logPlanStage(log, "copy", stageStarted);
|
|
14575
14617
|
const finalCompiledDir = join31(planDir, "compiled");
|
|
14576
14618
|
const needsAlpha = outputNeedsAlpha(config.format);
|
|
14619
|
+
const remoteFiles = Object.entries(options.remoteFiles ?? {});
|
|
14620
|
+
const remoteLocalPath = (rel) => join31(projectDir, ...rel.split("/"));
|
|
14621
|
+
const urlByAbsentLocalPath = new Map(
|
|
14622
|
+
remoteFiles.map(([rel, file]) => [remoteLocalPath(rel), file.url])
|
|
14623
|
+
);
|
|
14624
|
+
const localPathByUrl = new Map(
|
|
14625
|
+
remoteFiles.map(([rel, file]) => [file.url, remoteLocalPath(rel)])
|
|
14626
|
+
);
|
|
14577
14627
|
stageStarted = Date.now();
|
|
14578
14628
|
const compileResult = await runCompileStage({
|
|
14629
|
+
urlByAbsentLocalPath,
|
|
14579
14630
|
projectDir,
|
|
14580
14631
|
workDir,
|
|
14581
14632
|
htmlPath,
|
|
@@ -14635,7 +14686,7 @@ async function buildLocalExecutionPlan(projectDir, config, executionPlanDir, opt
|
|
|
14635
14686
|
if (probeResult.fileServer) closeFileServerSafely(probeResult.fileServer, "plan", log);
|
|
14636
14687
|
if (probeResult.probeSession) {
|
|
14637
14688
|
try {
|
|
14638
|
-
const { closeCaptureSession: closeCaptureSession2 } = await import("./src-
|
|
14689
|
+
const { closeCaptureSession: closeCaptureSession2 } = await import("./src-XRFOS5LP.js");
|
|
14639
14690
|
await closeCaptureSession2(probeResult.probeSession);
|
|
14640
14691
|
} catch (err) {
|
|
14641
14692
|
log.warn("[plan] probe session close failed", {
|
|
@@ -14663,7 +14714,8 @@ async function buildLocalExecutionPlan(projectDir, config, executionPlanDir, opt
|
|
|
14663
14714
|
abortSignal,
|
|
14664
14715
|
assertNotAborted,
|
|
14665
14716
|
materializeSymlinks: true,
|
|
14666
|
-
deferRangeExtraction: options.deferVideoExtraction
|
|
14717
|
+
deferRangeExtraction: options.deferVideoExtraction,
|
|
14718
|
+
urlByAbsentLocalPath
|
|
14667
14719
|
});
|
|
14668
14720
|
logPlanStage(log, "extract", stageStarted);
|
|
14669
14721
|
if (extractResult.failureToEnforce) throw extractResult.failureToEnforce;
|
|
@@ -14686,7 +14738,8 @@ async function buildLocalExecutionPlan(projectDir, config, executionPlanDir, opt
|
|
|
14686
14738
|
planDir,
|
|
14687
14739
|
projectDir,
|
|
14688
14740
|
workCompiledDir: compiledDir,
|
|
14689
|
-
workVideoFramesDir: stagedVideoFrames
|
|
14741
|
+
workVideoFramesDir: stagedVideoFrames,
|
|
14742
|
+
isRemote: (srcPath) => urlByAbsentLocalPath.has(srcPath)
|
|
14690
14743
|
});
|
|
14691
14744
|
const sourceRoots = [
|
|
14692
14745
|
[stagedVideoFrames, "video-frames"],
|
|
@@ -14696,17 +14749,28 @@ async function buildLocalExecutionPlan(projectDir, config, executionPlanDir, opt
|
|
|
14696
14749
|
const planVideosJson = buildPlanVideosJson({
|
|
14697
14750
|
videos: composition.videos,
|
|
14698
14751
|
compositionEnd: job.duration ?? Number.NaN,
|
|
14699
|
-
extracted: (extractResult.extractionResult?.extracted ?? []).map((ext) =>
|
|
14700
|
-
|
|
14701
|
-
|
|
14702
|
-
|
|
14703
|
-
|
|
14704
|
-
|
|
14705
|
-
|
|
14706
|
-
|
|
14707
|
-
|
|
14752
|
+
extracted: (extractResult.extractionResult?.extracted ?? []).map((ext) => {
|
|
14753
|
+
const sourcePath = localPathByUrl.get(ext.srcPath) ?? ext.srcPath;
|
|
14754
|
+
return {
|
|
14755
|
+
videoId: ext.videoId,
|
|
14756
|
+
srcPath: stableSourcePath(sourceRoots, sourcePath),
|
|
14757
|
+
framePattern: ext.framePattern,
|
|
14758
|
+
fps: ext.fps,
|
|
14759
|
+
totalFrames: ext.totalFrames,
|
|
14760
|
+
metadata: ext.metadata,
|
|
14761
|
+
...ext.deferredRange ? { deferredRange: { ...ext.deferredRange, sourcePath: shipVideoSource(sourcePath) } } : {}
|
|
14762
|
+
};
|
|
14763
|
+
})
|
|
14708
14764
|
});
|
|
14709
14765
|
mkdirSync10(join31(planDir, "meta"), { recursive: true });
|
|
14766
|
+
writePlanRemoteFiles(
|
|
14767
|
+
planDir,
|
|
14768
|
+
remoteFiles.map(([rel, { sha256, sizeBytes }]) => ({
|
|
14769
|
+
path: `compiled/${rel}`,
|
|
14770
|
+
sha256,
|
|
14771
|
+
sizeBytes
|
|
14772
|
+
}))
|
|
14773
|
+
);
|
|
14710
14774
|
writeFileSync7(
|
|
14711
14775
|
join31(planDir, PLAN_VIDEOS_META_RELATIVE_PATH),
|
|
14712
14776
|
JSON.stringify(planVideosJson, null, 2),
|
|
@@ -14721,6 +14785,7 @@ async function buildLocalExecutionPlan(projectDir, config, executionPlanDir, opt
|
|
|
14721
14785
|
projectDir,
|
|
14722
14786
|
workDir,
|
|
14723
14787
|
compiledDir: finalCompiledDir,
|
|
14788
|
+
urlByAbsentLocalPath,
|
|
14724
14789
|
duration: audioSeconds,
|
|
14725
14790
|
ffmpegProcessTimeout: cfg.ffmpegProcessTimeout,
|
|
14726
14791
|
audioGain: cfg.audioGain,
|
|
@@ -16205,7 +16270,7 @@ function startServer(options = {}) {
|
|
|
16205
16270
|
});
|
|
16206
16271
|
async function shutdown(signal) {
|
|
16207
16272
|
log.info(`Received ${signal}, shutting down`);
|
|
16208
|
-
const { drainBrowserPool } = await import("./src-
|
|
16273
|
+
const { drainBrowserPool } = await import("./src-XRFOS5LP.js");
|
|
16209
16274
|
await drainBrowserPool().catch(() => {
|
|
16210
16275
|
});
|
|
16211
16276
|
const handle = await Promise.race([
|
|
@@ -16472,17 +16537,20 @@ function artifactTargets(path, videoDependencies, chunksCarryAudio2) {
|
|
|
16472
16537
|
if (path === "plan.json" || path === "meta/chunks.json" || path === "meta/encoder.json") {
|
|
16473
16538
|
return { chunks: "all", assembler: true };
|
|
16474
16539
|
}
|
|
16475
|
-
if (path
|
|
16476
|
-
return { chunks: "all", assembler: false };
|
|
16477
|
-
}
|
|
16478
|
-
if (path.startsWith("video-frames/") || path.startsWith("video-sources/")) {
|
|
16540
|
+
if (path.startsWith("video-frames/") || path.startsWith("video-sources/") || path.startsWith("compiled/") && videoDependencies?.has(path)) {
|
|
16479
16541
|
return {
|
|
16480
16542
|
chunks: videoDependencies === null ? "all" : videoDependencies.get(path) ?? [],
|
|
16481
16543
|
assembler: false
|
|
16482
16544
|
};
|
|
16483
16545
|
}
|
|
16546
|
+
if (path === "meta/composition.json" || path === "meta/videos.json" || path.startsWith("compiled/")) {
|
|
16547
|
+
return { chunks: "all", assembler: false };
|
|
16548
|
+
}
|
|
16484
16549
|
return { chunks: "all", assembler: true };
|
|
16485
16550
|
}
|
|
16551
|
+
function isPlanV2DeferredSourceArtifact(artifact) {
|
|
16552
|
+
return artifact.path.startsWith("compiled/") && artifact.chunks !== "all";
|
|
16553
|
+
}
|
|
16486
16554
|
function listVideoFramePaths(executionPlanDir, videos) {
|
|
16487
16555
|
return videos.extracted.map((video) => {
|
|
16488
16556
|
const outputDir = resolveExtractedVideoOutputDir(executionPlanDir, video.videoId);
|
|
@@ -16645,14 +16713,17 @@ function publishBlobFor(absolutePath, digests) {
|
|
|
16645
16713
|
};
|
|
16646
16714
|
}
|
|
16647
16715
|
async function putBlobs(publisher, blobs) {
|
|
16716
|
+
await putTasks(blobs.map((blob) => () => publisher.putBlob(blob)));
|
|
16717
|
+
}
|
|
16718
|
+
async function putTasks(tasks) {
|
|
16648
16719
|
const uploadSlots = 32;
|
|
16649
16720
|
let next = 0;
|
|
16650
16721
|
let failure;
|
|
16651
16722
|
const upload = async () => {
|
|
16652
|
-
while (!failure && next <
|
|
16653
|
-
const
|
|
16723
|
+
while (!failure && next < tasks.length) {
|
|
16724
|
+
const task = tasks[next++];
|
|
16654
16725
|
try {
|
|
16655
|
-
await
|
|
16726
|
+
await task();
|
|
16656
16727
|
} catch (reason) {
|
|
16657
16728
|
failure ??= { reason };
|
|
16658
16729
|
}
|
|
@@ -16707,6 +16778,15 @@ function buildPlanV2Publication(executionPlanDir, digests) {
|
|
|
16707
16778
|
...targets
|
|
16708
16779
|
});
|
|
16709
16780
|
}
|
|
16781
|
+
const storedBlobs = /* @__PURE__ */ new Map();
|
|
16782
|
+
for (const remote of readPlanRemoteFiles(executionPlanDir)) {
|
|
16783
|
+
const { sha256, sizeBytes } = remote;
|
|
16784
|
+
if (!blobs.has(sha256)) storedBlobs.set(sha256, { sha256, sizeBytes });
|
|
16785
|
+
artifacts.push({
|
|
16786
|
+
...remote,
|
|
16787
|
+
...artifactTargets(remote.path, videoDependencyPlan.dependencies, chunksCarryAudio2)
|
|
16788
|
+
});
|
|
16789
|
+
}
|
|
16710
16790
|
const base = {
|
|
16711
16791
|
protocol: PLAN_PROTOCOL_V2,
|
|
16712
16792
|
// Retain the established manifest key byte-for-byte. It now acts as the
|
|
@@ -16728,7 +16808,8 @@ function buildPlanV2Publication(executionPlanDir, digests) {
|
|
|
16728
16808
|
...base,
|
|
16729
16809
|
planHash: computeManifestHash(base)
|
|
16730
16810
|
},
|
|
16731
|
-
blobs: [...blobs.values()]
|
|
16811
|
+
blobs: [...blobs.values()],
|
|
16812
|
+
storedBlobs: [...storedBlobs.values()]
|
|
16732
16813
|
};
|
|
16733
16814
|
}
|
|
16734
16815
|
function createPlanV2FromExecutionPlan(executionPlanDir, planV2Dir) {
|
|
@@ -16736,6 +16817,9 @@ function createPlanV2FromExecutionPlan(executionPlanDir, planV2Dir) {
|
|
|
16736
16817
|
throw new PlanV2IntegrityError(`output directory already exists: ${planV2Dir}`);
|
|
16737
16818
|
}
|
|
16738
16819
|
const publication = buildPlanV2Publication(executionPlanDir);
|
|
16820
|
+
if (publication.storedBlobs.length > 0) {
|
|
16821
|
+
throw new PlanV2IntegrityError("a local plan v2 directory cannot reference remote files");
|
|
16822
|
+
}
|
|
16739
16823
|
mkdirSync13(dirname14(planV2Dir), { recursive: true });
|
|
16740
16824
|
const tempDir = mkdtempSync6(join37(dirname14(planV2Dir), ".plan-v2-build-"));
|
|
16741
16825
|
try {
|
|
@@ -16765,8 +16849,14 @@ async function publishExecutionPlan(executionPlanDir, publisher, { digests, log
|
|
|
16765
16849
|
let stageStarted = Date.now();
|
|
16766
16850
|
const publication = buildPlanV2Publication(executionPlanDir, digests);
|
|
16767
16851
|
logPlanStage(log, "publication", stageStarted);
|
|
16852
|
+
if (publication.storedBlobs.length > 0 && !publisher.referenceStoredBlob) {
|
|
16853
|
+
throw new PlanV2IntegrityError("this publisher cannot reference remote files");
|
|
16854
|
+
}
|
|
16768
16855
|
stageStarted = Date.now();
|
|
16769
|
-
await
|
|
16856
|
+
await putTasks([
|
|
16857
|
+
...publication.blobs.map((blob) => () => publisher.putBlob(blob)),
|
|
16858
|
+
...publication.storedBlobs.map((blob) => () => publisher.referenceStoredBlob(blob))
|
|
16859
|
+
]);
|
|
16770
16860
|
logPlanStage(log, "upload", stageStarted);
|
|
16771
16861
|
stageStarted = Date.now();
|
|
16772
16862
|
await publisher.commitManifest(canonicalJsonStringify(publication.manifest));
|
|
@@ -16790,6 +16880,7 @@ async function planV2WithPublisher(projectDir, config, publisher, options = {})
|
|
|
16790
16880
|
await buildLocalExecutionPlan(projectDir, config, stagingRoot, {
|
|
16791
16881
|
executionPlanSizeLimitBytes: Number.MAX_SAFE_INTEGER,
|
|
16792
16882
|
deferVideoExtraction: true,
|
|
16883
|
+
remoteFiles: options.remoteFiles,
|
|
16793
16884
|
digests,
|
|
16794
16885
|
// artifactTargets ships every compiled/ file to all chunks, so each is in the manifest.
|
|
16795
16886
|
whileAudioMixes: () => putBlobs(
|
|
@@ -16992,14 +17083,16 @@ function verifyBlob(planV2Dir, artifact) {
|
|
|
16992
17083
|
}
|
|
16993
17084
|
return sourcePath;
|
|
16994
17085
|
}
|
|
16995
|
-
function materializePlanV2Target(planV2Dir, target, destinationDir) {
|
|
17086
|
+
function materializePlanV2Target(planV2Dir, target, destinationDir, options = {}) {
|
|
16996
17087
|
if (existsSync24(destinationDir)) {
|
|
16997
17088
|
throw new PlanV2IntegrityError(`materialization destination already exists: ${destinationDir}`);
|
|
16998
17089
|
}
|
|
16999
17090
|
const manifest = readPlanV2Manifest(planV2Dir);
|
|
17000
17091
|
const artifacts = listPlanV2ArtifactsForTarget(manifest, target);
|
|
17092
|
+
const remoteSources = options.remoteSources ?? {};
|
|
17093
|
+
assertRemoteSources(remoteSources, artifacts);
|
|
17001
17094
|
const audioArtifact = artifacts.find((artifact) => isPlanAudioArtifactPath(artifact.path));
|
|
17002
|
-
const verified = artifacts.map((artifact) => ({
|
|
17095
|
+
const verified = artifacts.filter((artifact) => !Object.hasOwn(remoteSources, artifact.path)).map((artifact) => ({
|
|
17003
17096
|
artifact,
|
|
17004
17097
|
sourcePath: verifyBlob(planV2Dir, artifact)
|
|
17005
17098
|
}));
|
|
@@ -17014,7 +17107,11 @@ function materializePlanV2Target(planV2Dir, target, destinationDir) {
|
|
|
17014
17107
|
if (target.role === "chunk") materializeExtractedVideoDirectories(tempDir);
|
|
17015
17108
|
writeFileSync10(
|
|
17016
17109
|
join37(tempDir, PLAN_V2_MATERIALIZATION_MARKER),
|
|
17017
|
-
canonicalJsonStringify({
|
|
17110
|
+
canonicalJsonStringify({
|
|
17111
|
+
manifest,
|
|
17112
|
+
target,
|
|
17113
|
+
...Object.keys(remoteSources).length > 0 ? { remoteSources } : {}
|
|
17114
|
+
}),
|
|
17018
17115
|
"utf-8"
|
|
17019
17116
|
);
|
|
17020
17117
|
renameSync6(tempDir, destinationDir);
|
|
@@ -17035,7 +17132,22 @@ function materializePlanV2Target(planV2Dir, target, destinationDir) {
|
|
|
17035
17132
|
audioPath: target.role === "assembler" ? audioArtifact ? join37(destinationDir, audioArtifact.path) : null : null
|
|
17036
17133
|
};
|
|
17037
17134
|
}
|
|
17135
|
+
function assertRemoteSources(remoteSources, artifacts) {
|
|
17136
|
+
if (!isRecord3(remoteSources)) throw new PlanV2IntegrityError("remoteSources must be an object");
|
|
17137
|
+
for (const [path, url] of Object.entries(remoteSources)) {
|
|
17138
|
+
const artifact = artifacts.find((candidate) => candidate.path === path);
|
|
17139
|
+
if (!artifact || !isPlanV2DeferredSourceArtifact(artifact)) {
|
|
17140
|
+
throw new PlanV2IntegrityError(`remote source is not a selected deferred video: ${path}`);
|
|
17141
|
+
}
|
|
17142
|
+
if (typeof url !== "string" || !/^https?:\/\//.test(url)) {
|
|
17143
|
+
throw new PlanV2IntegrityError(`remote source for ${path} must be an http(s) URL`);
|
|
17144
|
+
}
|
|
17145
|
+
}
|
|
17146
|
+
}
|
|
17038
17147
|
function validatePlanV2MaterializedTarget(planDir, expectedTarget) {
|
|
17148
|
+
return readValidatedPlanV2Materialization(planDir, expectedTarget)?.manifest ?? null;
|
|
17149
|
+
}
|
|
17150
|
+
function readValidatedPlanV2Materialization(planDir, expectedTarget) {
|
|
17039
17151
|
const markerPath = join37(planDir, PLAN_V2_MATERIALIZATION_MARKER);
|
|
17040
17152
|
if (!existsSync24(markerPath)) return null;
|
|
17041
17153
|
const marker = readJsonFile(markerPath, "materialization marker");
|
|
@@ -17050,7 +17162,10 @@ function validatePlanV2MaterializedTarget(planDir, expectedTarget) {
|
|
|
17050
17162
|
}
|
|
17051
17163
|
const manifest = parsePlanV2Manifest(marker.manifest);
|
|
17052
17164
|
const required = listPlanV2ArtifactsForTarget(manifest, expectedTarget);
|
|
17165
|
+
const remoteSources = marker.remoteSources ?? {};
|
|
17166
|
+
assertRemoteSources(remoteSources, required);
|
|
17053
17167
|
for (const artifact of required) {
|
|
17168
|
+
if (Object.hasOwn(remoteSources, artifact.path)) continue;
|
|
17054
17169
|
const path = join37(planDir, ...artifact.path.split("/"));
|
|
17055
17170
|
if (!existsSync24(path) || statSync9(path).size !== artifact.sizeBytes) {
|
|
17056
17171
|
throw new PlanV2IntegrityError(
|
|
@@ -17061,7 +17176,7 @@ function validatePlanV2MaterializedTarget(planDir, expectedTarget) {
|
|
|
17061
17176
|
throw new PlanV2IntegrityError(`materialized artifact hash mismatch: ${artifact.path}`);
|
|
17062
17177
|
}
|
|
17063
17178
|
}
|
|
17064
|
-
return manifest;
|
|
17179
|
+
return { manifest, remoteSources };
|
|
17065
17180
|
}
|
|
17066
17181
|
|
|
17067
17182
|
// ../producer/src/services/distributed/planV2Execution.ts
|
|
@@ -17909,10 +18024,12 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
|
|
|
17909
18024
|
const plan2 = JSON.parse(readFileSync13(planJsonPath, "utf-8"));
|
|
17910
18025
|
readPlanProtocolV1(plan2, DISTRIBUTED_RENDER_CAPABILITIES.roles.chunk);
|
|
17911
18026
|
const planHashStarted = Date.now();
|
|
17912
|
-
const
|
|
18027
|
+
const v2Materialization = readValidatedPlanV2Materialization(planDir, {
|
|
17913
18028
|
role: "chunk",
|
|
17914
18029
|
chunkIndex
|
|
17915
18030
|
});
|
|
18031
|
+
const v2Manifest = v2Materialization?.manifest ?? null;
|
|
18032
|
+
const remoteSources = v2Materialization?.remoteSources ?? {};
|
|
17916
18033
|
for (const required of [encoderJsonPath, chunksJsonPath]) {
|
|
17917
18034
|
if (!existsSync26(required)) {
|
|
17918
18035
|
throw new RenderChunkValidationError(
|
|
@@ -18014,6 +18131,24 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
|
|
|
18014
18131
|
const framesDir = join40(workDir, "captured-frames");
|
|
18015
18132
|
mkdirSync16(framesDir, { recursive: true });
|
|
18016
18133
|
const videoFramesDir = `${workDir}.video-frames`;
|
|
18134
|
+
const deferredVideoFrames = planVideos ? await extractDeferredVideoFramesForChunk({
|
|
18135
|
+
planDir,
|
|
18136
|
+
planVideos,
|
|
18137
|
+
frames: Array.from(
|
|
18138
|
+
{ length: slice.endFrame - slice.startFrame },
|
|
18139
|
+
(_, i) => slice.startFrame + i
|
|
18140
|
+
),
|
|
18141
|
+
fps: { num: plan2.dimensions.fpsNum, den: plan2.dimensions.fpsDen },
|
|
18142
|
+
outputRoot: videoFramesDir,
|
|
18143
|
+
cfg,
|
|
18144
|
+
remoteSources
|
|
18145
|
+
}) : [];
|
|
18146
|
+
const remoteVideoIds = new Set(
|
|
18147
|
+
planVideos?.extracted.filter(
|
|
18148
|
+
(video) => video.deferredRange && Object.hasOwn(remoteSources, video.deferredRange.sourcePath)
|
|
18149
|
+
).map((video) => video.videoId)
|
|
18150
|
+
);
|
|
18151
|
+
const remoteVideos = deferredVideoFrames.filter((video) => remoteVideoIds.has(video.videoId));
|
|
18017
18152
|
const videoFrameLookup = planVideos && planVideos.extracted.length > 0 ? createFrameLookupTable(
|
|
18018
18153
|
planVideos.videos,
|
|
18019
18154
|
[
|
|
@@ -18022,17 +18157,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
|
|
|
18022
18157
|
planVideos.extracted.filter((video) => !video.deferredRange),
|
|
18023
18158
|
v2Manifest === null ? "dense-v1" : "sparse-v2"
|
|
18024
18159
|
),
|
|
18025
|
-
...
|
|
18026
|
-
planDir,
|
|
18027
|
-
planVideos,
|
|
18028
|
-
frames: Array.from(
|
|
18029
|
-
{ length: slice.endFrame - slice.startFrame },
|
|
18030
|
-
(_, i) => slice.startFrame + i
|
|
18031
|
-
),
|
|
18032
|
-
fps: { num: plan2.dimensions.fpsNum, den: plan2.dimensions.fpsDen },
|
|
18033
|
-
outputRoot: videoFramesDir,
|
|
18034
|
-
cfg
|
|
18035
|
-
})
|
|
18160
|
+
...deferredVideoFrames
|
|
18036
18161
|
],
|
|
18037
18162
|
resolveRenderFpsConfig(job.config.fps).value
|
|
18038
18163
|
) : null;
|
|
@@ -18050,7 +18175,10 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
|
|
|
18050
18175
|
dimensions: plan2.dimensions,
|
|
18051
18176
|
encoder,
|
|
18052
18177
|
videoCount: planVideos?.videos.length ?? 0,
|
|
18053
|
-
html: readFileSync13(join40(compiledDir, "index.html"), "utf-8")
|
|
18178
|
+
html: readFileSync13(join40(compiledDir, "index.html"), "utf-8"),
|
|
18179
|
+
// The plan ships a deferred source only to chunks that show it; don't wait on the rest.
|
|
18180
|
+
skipReadinessVideoIds: deferredVideoFrames.filter((video) => video.framePaths.size === 0 || remoteVideoIds.has(video.videoId)).map((video) => video.videoId),
|
|
18181
|
+
videoMetadataHints: collectVideoMetadataHints(remoteVideos)
|
|
18054
18182
|
});
|
|
18055
18183
|
const chunkWorkerCount = calculateOptimalWorkers(framesInChunk, void 0, cfg);
|
|
18056
18184
|
let session = null;
|
|
@@ -18369,9 +18497,9 @@ async function assembleV2(planV2Dir, chunkPaths, outputPath, options) {
|
|
|
18369
18497
|
}
|
|
18370
18498
|
|
|
18371
18499
|
// ../producer/src/services/distributed/projectHash.ts
|
|
18372
|
-
import { readdirSync as readdirSync12, readFileSync as readFileSync14 } from "fs";
|
|
18500
|
+
import { readdirSync as readdirSync12, readFileSync as readFileSync14, realpathSync as realpathSync2, statSync as statSync11 } from "fs";
|
|
18373
18501
|
import { createHash as createHash7 } from "crypto";
|
|
18374
|
-
import { join as join42
|
|
18502
|
+
import { join as join42 } from "path";
|
|
18375
18503
|
|
|
18376
18504
|
export {
|
|
18377
18505
|
createConsoleLogger,
|