hyperframes 0.8.192 → 0.8.194
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/{add-TZU2UW7A.js → add-47UAIWY4.js} +12 -12
- package/dist/{animatedGifPrep-NLAXC3VV.js → animatedGifPrep-TFSQZWK6.js} +8 -7
- package/dist/api.js +18 -17
- package/dist/{asset-JAJXA6LB.js → asset-AU7PZHXA.js} +2 -2
- package/dist/{assetCataloger-4WTX3J4I.js → assetCataloger-HC5N6WPT.js} +8 -7
- package/dist/{audio-XLWC7JKS.js → audio-7AWMZWBM.js} +14 -13
- package/dist/{auth-5K6X3NPJ.js → auth-GXH3QNDJ.js} +1 -1
- package/dist/{autoUpdate-RNV7SKGB.js → autoUpdate-GVGP5O2I.js} +3 -3
- package/dist/{backgroundChecks-QXLVZVGX.js → backgroundChecks-IUJM2Q35.js} +3 -3
- package/dist/backgroundChecksWorker.js +3 -3
- package/dist/{batchRender-THKSPDZR.js → batchRender-3XS2Y2Y4.js} +4 -4
- package/dist/{beats-K7CGCFVL.js → beats-U64B4S7Z.js} +9 -9
- package/dist/{benchmark-PHRDIXNL.js → benchmark-2YUPAI76.js} +9 -9
- package/dist/{browser-GN6R5ZSK.js → browser-DBFH7KXM.js} +5 -5
- package/dist/{bundleWithLocalizedFonts-C325UNR4.js → bundleWithLocalizedFonts-XWL7KSQJ.js} +2 -2
- package/dist/{capture-BZ7APOGQ.js → capture-E4VW75NM.js} +2 -2
- package/dist/{capture-6UBQFHZQ.js → capture-YWH7BPBI.js} +13 -12
- package/dist/{captureCompositionFrame-VORSCTWC.js → captureCompositionFrame-IG6S2OHG.js} +13 -12
- package/dist/{catalog-PHU2RUZ3.js → catalog-LZIZLZ34.js} +12 -12
- package/dist/{catch-up-HCNRM46J.js → catch-up-ZVNPIACY.js} +4 -4
- package/dist/{check-TJ5ZLB4I.js → check-EKEOD4UM.js} +38 -37
- package/dist/{checkBrowser-DWP7ZXJ7.js → checkBrowser-MYH6HPHH.js} +33 -32
- package/dist/{chunk-XF77MK3J.js → chunk-2AJU7PZ6.js} +1 -1
- package/dist/chunk-2D5WP2NI.js +3901 -0
- package/dist/{chunk-FBVUAH7N.js → chunk-2OYYNKJ4.js} +1 -1
- package/dist/{chunk-R2U2G4OS.js → chunk-37IHQVNQ.js} +1 -1
- package/dist/{chunk-IMSI7IFW.js → chunk-3OSBSUN3.js} +18 -18
- package/dist/{chunk-RHYOWDI6.js → chunk-3S3CXF4W.js} +2 -2
- package/dist/{chunk-YMQQXPD5.js → chunk-452UK7E7.js} +5 -12
- package/dist/{chunk-L2YGSAOL.js → chunk-4FVNEXSV.js} +3 -3
- package/dist/{chunk-7UZC4N62.js → chunk-4GMDL4N5.js} +1 -1
- package/dist/{chunk-YWRQHRDY.js → chunk-4PIPQPCW.js} +7 -7
- package/dist/{chunk-J2ASTCU6.js → chunk-4VSV56F2.js} +2 -2
- package/dist/{chunk-NXMYHJAL.js → chunk-4VYPICIA.js} +29 -1
- package/dist/{chunk-QX4TB4NH.js → chunk-52YJKWV3.js} +379 -127
- package/dist/{chunk-GANST5K3.js → chunk-54PZ2EQZ.js} +1 -1
- package/dist/{chunk-5IPKQHOL.js → chunk-B3GG3HJB.js} +1 -1
- package/dist/{chunk-2MCXIY4B.js → chunk-B7RJV74O.js} +28 -11
- package/dist/{chunk-VOM2HLUI.js → chunk-BK5YCT54.js} +3 -3
- package/dist/{chunk-RWGASWT7.js → chunk-BL4U6U52.js} +1 -0
- package/dist/{chunk-T6O5OLN2.js → chunk-BYADARIC.js} +2 -2
- package/dist/{chunk-VNPADTDD.js → chunk-CEUBYYVJ.js} +2 -2
- package/dist/{chunk-JCDYDF54.js → chunk-CEZH4AQT.js} +12 -2
- package/dist/{chunk-BY6OQ6XP.js → chunk-CZNSLFYD.js} +3 -1
- package/dist/{chunk-SBBQFPCJ.js → chunk-DT3JESJ6.js} +1 -1
- package/dist/{chunk-3CXIX6XS.js → chunk-DVQDBWQG.js} +4 -4
- package/dist/{chunk-K2AKVYNR.js → chunk-EB3XXHNO.js} +2 -2
- package/dist/{chunk-3FV5BVWS.js → chunk-EY7GKVPS.js} +2 -2
- package/dist/{chunk-W24SZ5FL.js → chunk-F2ASNL2K.js} +6 -9
- package/dist/{chunk-ODBYZIOH.js → chunk-F3B7CE3Q.js} +14 -14
- package/dist/{chunk-E3P3LJG6.js → chunk-FLREUEHW.js} +28 -11
- package/dist/{chunk-6XVKMBUA.js → chunk-FUA22HO4.js} +1 -1
- package/dist/{chunk-AEXVVABM.js → chunk-GAFEU6AB.js} +13 -10
- package/dist/{chunk-DIKAPMMF.js → chunk-GQVTTWZF.js} +144 -39
- package/dist/{chunk-7LLRMYP6.js → chunk-HCLBM2LQ.js} +2 -2
- package/dist/{chunk-AMZJFCOX.js → chunk-HG5ECUOR.js} +5 -5
- package/dist/{chunk-KZOZN4PI.js → chunk-HPGQPRHY.js} +3 -3
- package/dist/{chunk-BPKLUHFT.js → chunk-HQD7ODQB.js} +5 -5
- package/dist/{chunk-SK7TR7BL.js → chunk-JU4T4VAA.js} +4 -4
- package/dist/{chunk-MGBUWPXX.js → chunk-JVTWX5G3.js} +33 -8
- package/dist/{chunk-2J3NA3OB.js → chunk-JXTPNUSO.js} +83 -51
- package/dist/{chunk-2VXY3PEF.js → chunk-K2VXPQKC.js} +107 -94
- package/dist/chunk-K4MJX7SR.js +17 -0
- package/dist/{chunk-XX2PA4L3.js → chunk-KDEV5RIE.js} +7 -3
- package/dist/{chunk-MVIJTXN5.js → chunk-LMIDZIW2.js} +12 -12
- package/dist/{chunk-6WNLQI63.js → chunk-LOGKDQ3G.js} +3 -3
- package/dist/{chunk-IW5G323T.js → chunk-LTGTN2TH.js} +8 -9
- package/dist/{chunk-MEE4NTPZ.js → chunk-LZ4WPR3B.js} +2 -2
- package/dist/{chunk-32NB4VMH.js → chunk-M2VXARYK.js} +3 -2
- package/dist/{chunk-7RSY7SZN.js → chunk-MCFPMUMT.js} +2 -2
- package/dist/{chunk-BEOK6F26.js → chunk-MGSNFWGR.js} +2 -2
- package/dist/{chunk-ZEMDV6W2.js → chunk-MO6RTNYD.js} +1 -1
- package/dist/{chunk-7JJMT6LN.js → chunk-N33FO44R.js} +1 -1
- package/dist/{chunk-A4OI5ZNX.js → chunk-N3M3IU6S.js} +1 -1
- package/dist/{chunk-CXRZBWSH.js → chunk-NVVIFW3C.js} +10 -10
- package/dist/{chunk-E5V6WEMK.js → chunk-O2ILONGK.js} +10 -10
- package/dist/{chunk-4HCJOFMB.js → chunk-OJNNKHAZ.js} +94 -22
- package/dist/{chunk-QWLES6YV.js → chunk-PEHST4UY.js} +3 -3
- package/dist/{chunk-BV6YE455.js → chunk-POFJH2IS.js} +1 -1
- package/dist/{chunk-AR46ND2Q.js → chunk-PXK3ICU6.js} +1 -1
- package/dist/{chunk-LOKCBZYF.js → chunk-Q4HKC3O7.js} +3 -3
- package/dist/{chunk-J2BSUF6X.js → chunk-QJQTWTM7.js} +8 -3
- package/dist/{chunk-QFPBRZJD.js → chunk-ROEW726S.js} +1 -1
- package/dist/{chunk-OQL4AJ4X.js → chunk-RUPGFW5B.js} +6 -6
- package/dist/{chunk-5TRFLZ5Z.js → chunk-RZWJJCI7.js} +2 -2
- package/dist/{chunk-2HP5GIQ3.js → chunk-SNECH6QA.js} +1 -1
- package/dist/{chunk-REUL2KH2.js → chunk-ST35C4K6.js} +1 -1
- package/dist/{chunk-4E75LHAL.js → chunk-ST4SHO3S.js} +1 -1
- package/dist/{chunk-ULTKB5FC.js → chunk-TDYKVJTU.js} +548 -429
- package/dist/{chunk-WOKVXK4J.js → chunk-VHIBBDEI.js} +1 -1
- package/dist/{chunk-EKGGSAWR.js → chunk-VPON6DF2.js} +5 -5
- package/dist/{chunk-VRAXIQ6I.js → chunk-XYGULBFV.js} +2 -2
- package/dist/{chunk-PFRG5P32.js → chunk-Y3BT27Y7.js} +1 -1
- package/dist/{clean-2RNCTDBT.js → clean-NS2SDRK7.js} +21 -20
- package/dist/cli.js +54 -54
- package/dist/{cloud-NFIKESNZ.js → cloud-K4XQPWTY.js} +4 -4
- package/dist/{cloudrun-7224BCX3.js → cloudrun-BKOKXTXV.js} +6 -6
- package/dist/{compare-HL44MXVX.js → compare-ZAV773OL.js} +31 -30
- package/dist/{compiler-WF5QTXV7.js → compiler-CWHFCE3H.js} +5 -5
- package/dist/{component-ZBZXSJBR.js → component-OXA2ZWX3.js} +3 -3
- package/dist/{compositions-76P7LDDX.js → compositions-NKRVWCPE.js} +12 -11
- package/dist/{contactSheet-43ISAESM.js → contactSheet-5APX35L3.js} +1 -1
- package/dist/{delete-4YZBYOHJ.js → delete-HZ2LBCLC.js} +2 -2
- package/dist/{deploy-UGUUGYLF.js → deploy-FNDTZFF7.js} +1 -1
- package/dist/{deterministicFonts-RO2TCMLZ.js → deterministicFonts-RADD3BSX.js} +2 -2
- package/dist/{dist-5KKCRFPT.js → dist-2YTN2UGY.js} +3 -3
- package/dist/{dist-QQ26RUDV.js → dist-7OCZHNLY.js} +1 -1
- package/dist/{doctor-GGVUK4NB.js → doctor-6QWJGO5P.js} +14 -13
- package/dist/{events-V2VU4J3B.js → events-HTHOBIUN.js} +3 -3
- package/dist/{events-OXPTHVDB.js → events-MBKHVGXX.js} +2 -2
- package/dist/{feedback-HFZ5SCUK.js → feedback-X5QWTLEX.js} +8 -8
- package/dist/{ffmpeg-3VHY7GO3.js → ffmpeg-7GESJCCT.js} +9 -8
- package/dist/{figma-7SEZTLBJ.js → figma-SXOHFVJI.js} +3 -3
- package/dist/fontLocalizeCli.js +11 -10
- package/dist/{get-Y2S2PXCM.js → get-T2HI5FCK.js} +2 -2
- package/dist/{gpuPolicy-UHPOWRV5.js → gpuPolicy-5FABKW5G.js} +8 -7
- package/dist/{grade-compare-4VTXSQM5.js → grade-compare-JATGHA6Q.js} +37 -35
- package/dist/{gsapParser-UP3PNPC2.js → gsapParser-IEUSLYDJ.js} +11 -11
- package/dist/{gsapParserAcorn-OOTY2MVN.js → gsapParserAcorn-LZJKCFQI.js} +1 -1
- package/dist/{help-HXNOACHI.js → help-G6CIKCGS.js} +1 -1
- package/dist/{history-XDJUI4LC.js → history-CSJUHYTD.js} +9 -8
- package/dist/hyperframe.manifest.json +1 -1
- package/dist/hyperframe.runtime.iife.js +71 -65
- package/dist/hyperframes-player.global.js +3 -3
- package/dist/hyperframes-slideshow.global.js +1 -1
- package/dist/{info-KYRI3EZV.js → info-MTTUMW2C.js} +8 -8
- package/dist/{init-IL7EWMT5.js → init-LJYNI5EK.js} +30 -29
- package/dist/{inspect-TBNH23UC.js → inspect-HGDM2VJE.js} +31 -30
- package/dist/{installer-O2YMFSI4.js → installer-3XHURUDG.js} +5 -5
- package/dist/{keyframes-4GF62KAJ.js → keyframes-MSU7N53X.js} +59 -33
- package/dist/{lambda-JFL6M4XZ.js → lambda-2I2TIUSD.js} +8 -8
- package/dist/{layout-7MAEFR65.js → layout-KWOXZMN7.js} +31 -30
- package/dist/{lint-4AYHKYAM.js → lint-N53TLHFG.js} +7 -7
- package/dist/{lintProject-52SLJPRC.js → lintProject-EOUZA4EG.js} +1 -1
- package/dist/{list-3DP3D3MW.js → list-SHYPQC7U.js} +2 -2
- package/dist/{login-T54WQYRQ.js → login-TEB6PA3Y.js} +4 -4
- package/dist/{manager-MZIJY73J.js → manager-COSJVRAE.js} +2 -2
- package/dist/{manager-QROK2IH3.js → manager-PLRSZH5G.js} +10 -9
- package/dist/{media-treatment-4CXF7MSG.js → media-treatment-XTUKMIGE.js} +15 -14
- package/dist/{models-IS3I6JKU.js → models-4WKAPP2L.js} +14 -13
- package/dist/{motionShot-DVYJZOTQ.js → motionShot-PTKB4ILH.js} +17 -16
- package/dist/{normalize-audio-4527JIK4.js → normalize-audio-3NG326I2.js} +6 -6
- package/dist/{open-5JE46SAX.js → open-6S2LMF7R.js} +12 -12
- package/dist/{parakeetRunner-7JIJGJJ7.js → parakeetRunner-OEI35DVO.js} +15 -14
- package/dist/{pipeline-YEN3WFD2.js → pipeline-543FUKH4.js} +10 -9
- package/dist/{play-WFX67I7M.js → play-ETEGHP3B.js} +21 -21
- package/dist/{preflight-D377HVUZ.js → preflight-Y5IYUF2T.js} +11 -10
- package/dist/{present-XTSEKAC7.js → present-ZRSLMJ6J.js} +17 -17
- package/dist/{preview-5XH7EK6O.js → preview-CEJ3SVTY.js} +100 -65
- package/dist/{producer-TFFYF4ZM.js → producer-JFVFIV26.js} +1 -1
- package/dist/{projectConfig-6YUJHMCL.js → projectConfig-7EK3BS72.js} +7 -7
- package/dist/{publication-JK33Y55E.js → publication-Y54GYFMV.js} +3 -3
- package/dist/{publish-JHDGXWXU.js → publish-S3UJTPCV.js} +10 -10
- package/dist/{remove-background-P44MYAPJ.js → remove-background-YTATNQSI.js} +11 -10
- package/dist/{render-RBINWWP5.js → render-IIPXMSBO.js} +35 -34
- package/dist/{render-RJ3I4E3A.js → render-RN3W6YL4.js} +17 -16
- package/dist/{render-HJ34EGMN.js → render-WNIG4B3J.js} +6 -6
- package/dist/{render-batch-3D6XQYUC.js → render-batch-OYS3UQDB.js} +6 -6
- package/dist/renderSetupWorker.js +42 -4
- package/dist/{resolver-HCLTFZUW.js → resolver-OVCXVEDX.js} +5 -5
- package/dist/{sherpa-IPOUJM6Q.js → sherpa-NCSFD7S3.js} +14 -13
- package/dist/skills/hyperframes/references/format.md +1 -0
- package/dist/skills/media-use/scripts/lib/duck.mjs +18 -2
- package/dist/skills/media-use/scripts/lib/duck.test.mjs +79 -0
- package/dist/{skills-P67QEERC.js → skills-IUV3K3X7.js} +5 -5
- package/dist/{skillsUpdateCheck-IFMLRVIF.js → skillsUpdateCheck-NACBXMWW.js} +3 -3
- package/dist/{snapshot-4YM4NNWJ.js → snapshot-7S5USJ2I.js} +52 -46
- package/dist/{src-DCD3YMXX.js → src-CAR6PHI4.js} +10 -9
- package/dist/{src-SSV66L3F.js → src-HITT6NWG.js} +19 -6
- package/dist/{staticProjectServer-C7PPGLEQ.js → staticProjectServer-QR6VZBPT.js} +18 -18
- package/dist/studio/assets/{hyperframes-player-ChN3cOr0.js → hyperframes-player-DLOUZUct.js} +1 -1
- package/dist/studio/assets/{index-CHu83hHM.js → index-CAQ7OcNJ.js} +163 -163
- package/dist/studio/assets/{index-BYbFcRR0.js → index-D9kA6JUX.js} +1 -1
- package/dist/studio/index.html +1 -1
- package/dist/{studio-api-6YZ7PIQR.js → studio-api-HVNOJILH.js} +13 -11
- package/dist/{studioServer-EWHSE4GC.js → studioServer-3BG5FRJL.js} +53 -52
- package/dist/{telemetry-GGLBHZRZ.js → telemetry-PET2GFQG.js} +3 -3
- package/dist/{timeline-NKHQJXJ2.js → timeline-PVIC2Z5K.js} +20 -19
- package/dist/{tokens-FWNNDJ6R.js → tokens-4N46PWSF.js} +2 -2
- package/dist/{transcribe-TRPKXZ7L.js → transcribe-2DVBS7MH.js} +19 -18
- package/dist/{transcribe-VD2TMMC2.js → transcribe-IDC7JTM4.js} +13 -12
- package/dist/{updateCheck-CUPS6LU3.js → updateCheck-QRDVXU7I.js} +2 -2
- package/dist/{upgrade-23XO6MEX.js → upgrade-5CNE3TBH.js} +2 -2
- package/dist/{urlDownloader-YOAOONCK.js → urlDownloader-P2I25DFC.js} +7 -6
- package/dist/{validate-BWIW24G5.js → validate-CLR5PEOV.js} +25 -24
- package/dist/{video-XRXJS4GC.js → video-3CKZZBOB.js} +8 -7
- package/dist/warmCheck.js +38 -37
- package/package.json +1 -1
- package/dist/chunk-B2XLXD7V.js +0 -3897
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
renderFrameIdForRenderId,
|
|
27
27
|
resolveAuthoredTimingWindow,
|
|
28
28
|
toFps
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-JVTWX5G3.js";
|
|
30
30
|
import {
|
|
31
31
|
AUDIO_GROUP_RENDER_ID_ATTR,
|
|
32
32
|
COLOR_GRADING_SOURCE_HIDDEN_ATTR,
|
|
@@ -63,7 +63,7 @@ import {
|
|
|
63
63
|
sourceTimeAt,
|
|
64
64
|
timeAtSourceTime,
|
|
65
65
|
volumeSegmentSampleCount
|
|
66
|
-
} from "./chunk-
|
|
66
|
+
} from "./chunk-2D5WP2NI.js";
|
|
67
67
|
import {
|
|
68
68
|
clampAudioGain,
|
|
69
69
|
clipGain,
|
|
@@ -73,6 +73,9 @@ import {
|
|
|
73
73
|
redactTelemetryString,
|
|
74
74
|
redactUrlQueryStrings
|
|
75
75
|
} from "./chunk-634HSJ3J.js";
|
|
76
|
+
import {
|
|
77
|
+
withHyperframesBrowserMarker
|
|
78
|
+
} from "./chunk-K4MJX7SR.js";
|
|
76
79
|
import {
|
|
77
80
|
browserPathFromEnv,
|
|
78
81
|
chromeMajorCeiling,
|
|
@@ -83,7 +86,7 @@ import {
|
|
|
83
86
|
} from "./chunk-4UMPIPCQ.js";
|
|
84
87
|
import {
|
|
85
88
|
resolveReferencedStart
|
|
86
|
-
} from "./chunk-
|
|
89
|
+
} from "./chunk-K2VXPQKC.js";
|
|
87
90
|
import {
|
|
88
91
|
FFMPEG_PATH_ENV,
|
|
89
92
|
FFPROBE_PATH_ENV,
|
|
@@ -765,7 +768,7 @@ var BrowserLeasePool = class _BrowserLeasePool {
|
|
|
765
768
|
for (const entry of entries) this.requestClose(entry, false);
|
|
766
769
|
const settle = Promise.all(entries.map((entry) => entry.closePromise));
|
|
767
770
|
const bound = new Promise(
|
|
768
|
-
(
|
|
771
|
+
(resolve2) => setTimeout(resolve2, _BrowserLeasePool.DRAIN_FORCE_CLOSE_MS).unref()
|
|
769
772
|
);
|
|
770
773
|
this.drainPromise = Promise.race([settle, bound]).then(() => {
|
|
771
774
|
for (const entry of entries) if (this.entries.has(entry)) this.requestClose(entry, true);
|
|
@@ -864,11 +867,11 @@ var BrowserLeasePool = class _BrowserLeasePool {
|
|
|
864
867
|
await Promise.race([
|
|
865
868
|
this.options.close(result.browser).catch(() => {
|
|
866
869
|
}),
|
|
867
|
-
new Promise((
|
|
870
|
+
new Promise((resolve2) => {
|
|
868
871
|
entry.forceClose = () => {
|
|
869
872
|
entry.forceClose = void 0;
|
|
870
873
|
this.options.forceClose(result.browser);
|
|
871
|
-
|
|
874
|
+
resolve2();
|
|
872
875
|
};
|
|
873
876
|
})
|
|
874
877
|
]);
|
|
@@ -918,7 +921,7 @@ async function probeHardwareWebGlInfo(ppt, options) {
|
|
|
918
921
|
const launchOptions = {
|
|
919
922
|
...sigintLaunchOptions(),
|
|
920
923
|
headless: true,
|
|
921
|
-
args: options.args,
|
|
924
|
+
args: withHyperframesBrowserMarker(options.args),
|
|
922
925
|
defaultViewport: { width: 64, height: 64 },
|
|
923
926
|
executablePath: options.executablePath,
|
|
924
927
|
env: options.env,
|
|
@@ -1366,7 +1369,7 @@ async function launchBrowser(fingerprint) {
|
|
|
1366
1369
|
browser = await ppt.launch({
|
|
1367
1370
|
...sigintLaunchOptions(),
|
|
1368
1371
|
headless: true,
|
|
1369
|
-
args:
|
|
1372
|
+
args: withHyperframesBrowserMarker(fingerprint.args),
|
|
1370
1373
|
defaultViewport: null,
|
|
1371
1374
|
executablePath: fingerprint.executablePath,
|
|
1372
1375
|
env,
|
|
@@ -1396,7 +1399,7 @@ async function launchBrowser(fingerprint) {
|
|
|
1396
1399
|
browser = await ppt.launch({
|
|
1397
1400
|
...sigintLaunchOptions(),
|
|
1398
1401
|
headless: true,
|
|
1399
|
-
args: stripBeginFrameFlags([...fingerprint.args]),
|
|
1402
|
+
args: withHyperframesBrowserMarker(stripBeginFrameFlags([...fingerprint.args])),
|
|
1400
1403
|
defaultViewport: null,
|
|
1401
1404
|
executablePath: fingerprint.executablePath,
|
|
1402
1405
|
env,
|
|
@@ -1477,6 +1480,7 @@ function getLowMemoryFlags() {
|
|
|
1477
1480
|
}
|
|
1478
1481
|
var CANVAS_DRAW_ELEMENT_FEATURE_FLAG = "--enable-features=CanvasDrawElement";
|
|
1479
1482
|
var WEBGPU_FLAG = "--enable-unsafe-webgpu";
|
|
1483
|
+
var DISABLE_DXC_FLAG = "--disable-dawn-features=use_dxc";
|
|
1480
1484
|
function usesSoftwareWebGpu(requiresWebGpu, config) {
|
|
1481
1485
|
return !!requiresWebGpu && !!config?.allowSoftwareWebGpu && !(config.disableGpu ?? DEFAULT_CONFIG.disableGpu) && (config.browserGpuMode ?? DEFAULT_CONFIG.browserGpuMode) === "software";
|
|
1482
1486
|
}
|
|
@@ -1532,6 +1536,9 @@ function buildChromeArgs(options, config) {
|
|
|
1532
1536
|
];
|
|
1533
1537
|
if (browserGpuMode !== "software" || options.requiresWebGpu) {
|
|
1534
1538
|
chromeArgs.push(WEBGPU_FLAG);
|
|
1539
|
+
if (platform === "win32") {
|
|
1540
|
+
chromeArgs.push(DISABLE_DXC_FLAG);
|
|
1541
|
+
}
|
|
1535
1542
|
}
|
|
1536
1543
|
if (softwareWebGpu) chromeArgs.push("--use-vulkan=swiftshader");
|
|
1537
1544
|
if (browserGpuMode === "software" && !softwareWebGpu) {
|
|
@@ -1580,7 +1587,7 @@ async function assertWebGpuAdapterAvailable(page, requiresWebGpu, softwareWebGpu
|
|
|
1580
1587
|
try {
|
|
1581
1588
|
const adapter = await Promise.race([
|
|
1582
1589
|
navigator.gpu.requestAdapter(),
|
|
1583
|
-
new Promise((
|
|
1590
|
+
new Promise((resolve2) => setTimeout(() => resolve2(null), timeoutMs))
|
|
1584
1591
|
]);
|
|
1585
1592
|
return !!adapter && (acceptFallback || !adapter.info.isFallbackAdapter);
|
|
1586
1593
|
} catch {
|
|
@@ -2583,8 +2590,8 @@ async function describePageMotionBlur(page) {
|
|
|
2583
2590
|
}
|
|
2584
2591
|
async function describePageMotionBlurAtEnd(page, timeoutMs = 1500) {
|
|
2585
2592
|
let timer;
|
|
2586
|
-
const stuck = new Promise((
|
|
2587
|
-
timer = setTimeout(() =>
|
|
2593
|
+
const stuck = new Promise((resolve2) => {
|
|
2594
|
+
timer = setTimeout(() => resolve2(null), timeoutMs);
|
|
2588
2595
|
});
|
|
2589
2596
|
try {
|
|
2590
2597
|
const r = await Promise.race([readPageMotionBlur(page), stuck]);
|
|
@@ -2703,8 +2710,8 @@ async function probeBeginFrameLiveness(page, timeoutMs, frameTimeTicks, interval
|
|
|
2703
2710
|
try {
|
|
2704
2711
|
return await Promise.race([
|
|
2705
2712
|
client.send("HeadlessExperimental.beginFrame", params).then(() => true).catch(() => false),
|
|
2706
|
-
new Promise((
|
|
2707
|
-
timer = setTimeout(() =>
|
|
2713
|
+
new Promise((resolve2) => {
|
|
2714
|
+
timer = setTimeout(() => resolve2(false), timeoutMs);
|
|
2708
2715
|
})
|
|
2709
2716
|
]);
|
|
2710
2717
|
} finally {
|
|
@@ -3503,7 +3510,7 @@ async function produceDrawElementFrame(page, width, height, quality = 80, syncTo
|
|
|
3503
3510
|
);
|
|
3504
3511
|
}
|
|
3505
3512
|
const frameId = ++state.nextId;
|
|
3506
|
-
const encodeResult = new Promise((
|
|
3513
|
+
const encodeResult = new Promise((resolve2, reject) => {
|
|
3507
3514
|
const timer = setTimeout(() => {
|
|
3508
3515
|
if (state.pending.delete(frameId)) {
|
|
3509
3516
|
reject(new Error(`drawElement worker encode timed out (frame ${frameId})`));
|
|
@@ -3512,7 +3519,7 @@ async function produceDrawElementFrame(page, width, height, quality = 80, syncTo
|
|
|
3512
3519
|
state.pending.set(frameId, {
|
|
3513
3520
|
resolve: (b) => {
|
|
3514
3521
|
clearTimeout(timer);
|
|
3515
|
-
|
|
3522
|
+
resolve2(b);
|
|
3516
3523
|
},
|
|
3517
3524
|
reject: (e) => {
|
|
3518
3525
|
clearTimeout(timer);
|
|
@@ -3668,7 +3675,7 @@ async function produceDrawElementFrameBatch(page, times, width, height, quality
|
|
|
3668
3675
|
for (let i = 0; i < times.length; i++) {
|
|
3669
3676
|
const frameId = ++state.nextId;
|
|
3670
3677
|
fids.push(frameId);
|
|
3671
|
-
const p = new Promise((
|
|
3678
|
+
const p = new Promise((resolve2, reject) => {
|
|
3672
3679
|
const timer = setTimeout(() => {
|
|
3673
3680
|
if (state.pending.delete(frameId)) {
|
|
3674
3681
|
reject(new Error(`drawElement worker encode timed out (frame ${frameId})`));
|
|
@@ -3677,7 +3684,7 @@ async function produceDrawElementFrameBatch(page, times, width, height, quality
|
|
|
3677
3684
|
state.pending.set(frameId, {
|
|
3678
3685
|
resolve: (b) => {
|
|
3679
3686
|
clearTimeout(timer);
|
|
3680
|
-
|
|
3687
|
+
resolve2(b);
|
|
3681
3688
|
},
|
|
3682
3689
|
reject: (e) => {
|
|
3683
3690
|
clearTimeout(timer);
|
|
@@ -3952,9 +3959,9 @@ async function initThreeDProjectionInPage() {
|
|
|
3952
3959
|
const toDataUrl = async (url) => {
|
|
3953
3960
|
const resp = await fetch(url);
|
|
3954
3961
|
const blob = await resp.blob();
|
|
3955
|
-
return new Promise((
|
|
3962
|
+
return new Promise((resolve2, reject) => {
|
|
3956
3963
|
const r = new FileReader();
|
|
3957
|
-
r.onload = () =>
|
|
3964
|
+
r.onload = () => resolve2(String(r.result));
|
|
3958
3965
|
r.onerror = () => reject(new Error(`FileReader failed for ${url}`));
|
|
3959
3966
|
r.readAsDataURL(blob);
|
|
3960
3967
|
});
|
|
@@ -4798,6 +4805,7 @@ var CaptureFailure = class extends Error {
|
|
|
4798
4805
|
kind;
|
|
4799
4806
|
cause;
|
|
4800
4807
|
workerDiagnostics;
|
|
4808
|
+
pageErrorLines;
|
|
4801
4809
|
constructor(input) {
|
|
4802
4810
|
super(input.message);
|
|
4803
4811
|
this.name = "CaptureFailure";
|
|
@@ -4808,6 +4816,7 @@ var CaptureFailure = class extends Error {
|
|
|
4808
4816
|
(diagnostic) => Object.freeze({ ...diagnostic, lines: Object.freeze([...diagnostic.lines]) })
|
|
4809
4817
|
)
|
|
4810
4818
|
);
|
|
4819
|
+
this.pageErrorLines = Object.freeze([...input.pageErrorLines ?? []]);
|
|
4811
4820
|
if (input.cause instanceof Error && input.cause.stack) this.stack = input.cause.stack;
|
|
4812
4821
|
}
|
|
4813
4822
|
};
|
|
@@ -4893,32 +4902,37 @@ function ioError(error, message) {
|
|
|
4893
4902
|
)
|
|
4894
4903
|
) || BROKEN_PIPE_MESSAGE.test(message) || hasIoOperationFailure(message);
|
|
4895
4904
|
}
|
|
4905
|
+
var ORDERED_KIND_RULES = [
|
|
4906
|
+
[
|
|
4907
|
+
"memory_exhaustion",
|
|
4908
|
+
(message) => BUN_MEMORY_EXHAUSTION_EXACT_MESSAGE.test(message.trim()) || BUN_MEMORY_EXHAUSTION_WRAPPED_WORKER_MESSAGE.test(message) || matchesAny(message, MEMORY_EXHAUSTION_ERROR_PATTERNS)
|
|
4909
|
+
],
|
|
4910
|
+
["verification", (message) => matchesAny(message, VERIFICATION_ERROR_PATTERNS)],
|
|
4911
|
+
["protocol_timeout", (message) => matchesAny(message, PROTOCOL_TIMEOUT_PATTERNS)],
|
|
4912
|
+
["transient_browser", (message) => matchesAny(message, TRANSIENT_BROWSER_ERROR_PATTERNS)],
|
|
4913
|
+
["authoring", (message) => matchesAny(message, AUTHORING_ERROR_PATTERNS)]
|
|
4914
|
+
];
|
|
4915
|
+
function classifyKind(error, message, signal) {
|
|
4916
|
+
if (signal?.aborted || /(?:render|capture)?_?cancelled|AbortError/i.test(message)) {
|
|
4917
|
+
return "cancelled";
|
|
4918
|
+
}
|
|
4919
|
+
const rule = ORDERED_KIND_RULES.find(([, matches]) => matches(message));
|
|
4920
|
+
if (rule) return rule[0];
|
|
4921
|
+
return ioError(error, message) ? "io" : "authoring";
|
|
4922
|
+
}
|
|
4896
4923
|
function classifyCaptureFailure(error, options = {}) {
|
|
4897
|
-
|
|
4898
|
-
|
|
4924
|
+
const prior = error instanceof CaptureFailure ? error : void 0;
|
|
4925
|
+
if (prior && !(options.workerDiagnostics || options.pageErrorLines || options.signal?.aborted)) {
|
|
4926
|
+
return prior;
|
|
4899
4927
|
}
|
|
4900
4928
|
const message = messageOf(error);
|
|
4901
|
-
|
|
4902
|
-
if (options.signal?.aborted || /(?:render|capture)?_?cancelled|AbortError/i.test(message)) {
|
|
4903
|
-
kind = "cancelled";
|
|
4904
|
-
} else if (BUN_MEMORY_EXHAUSTION_EXACT_MESSAGE.test(message.trim()) || BUN_MEMORY_EXHAUSTION_WRAPPED_WORKER_MESSAGE.test(message) || matchesAny(message, MEMORY_EXHAUSTION_ERROR_PATTERNS)) {
|
|
4905
|
-
kind = "memory_exhaustion";
|
|
4906
|
-
} else if (matchesAny(message, VERIFICATION_ERROR_PATTERNS)) {
|
|
4907
|
-
kind = "verification";
|
|
4908
|
-
} else if (matchesAny(message, PROTOCOL_TIMEOUT_PATTERNS)) {
|
|
4909
|
-
kind = "protocol_timeout";
|
|
4910
|
-
} else if (matchesAny(message, TRANSIENT_BROWSER_ERROR_PATTERNS)) {
|
|
4911
|
-
kind = "transient_browser";
|
|
4912
|
-
} else if (matchesAny(message, AUTHORING_ERROR_PATTERNS)) {
|
|
4913
|
-
kind = "authoring";
|
|
4914
|
-
} else {
|
|
4915
|
-
kind = ioError(error, message) ? "io" : "authoring";
|
|
4916
|
-
}
|
|
4929
|
+
const kind = classifyKind(error, message, options.signal);
|
|
4917
4930
|
return new CaptureFailure({
|
|
4918
4931
|
kind,
|
|
4919
4932
|
message,
|
|
4920
4933
|
cause: error,
|
|
4921
|
-
workerDiagnostics: options.workerDiagnostics ??
|
|
4934
|
+
workerDiagnostics: options.workerDiagnostics ?? prior?.workerDiagnostics,
|
|
4935
|
+
pageErrorLines: options.pageErrorLines ?? prior?.pageErrorLines
|
|
4922
4936
|
});
|
|
4923
4937
|
}
|
|
4924
4938
|
function isTransientBrowserError(error) {
|
|
@@ -5139,7 +5153,7 @@ function formatHttpErrorDiagnostic(input) {
|
|
|
5139
5153
|
return `[Browser:HTTP${input.status}] ${input.method} ${sanitizeDiagnosticUrl(input.url)} resource=${input.resourceType}${statusText}`;
|
|
5140
5154
|
}
|
|
5141
5155
|
var LOCKED_WARMUP_TICKS = 60;
|
|
5142
|
-
var realSleep = (ms) => new Promise((
|
|
5156
|
+
var realSleep = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
5143
5157
|
function warmupFrameTimeTicks(state, intervalMs) {
|
|
5144
5158
|
return state.ticks * intervalMs;
|
|
5145
5159
|
}
|
|
@@ -5203,12 +5217,14 @@ async function driveWarmupTicks(options, state) {
|
|
|
5203
5217
|
} else {
|
|
5204
5218
|
if (!state.running) return;
|
|
5205
5219
|
}
|
|
5220
|
+
let ticked = false;
|
|
5206
5221
|
try {
|
|
5207
5222
|
await options.tick(state.ticks * options.intervalMs, options.intervalMs);
|
|
5208
5223
|
state.ticks += 1;
|
|
5224
|
+
ticked = true;
|
|
5209
5225
|
} catch {
|
|
5210
5226
|
}
|
|
5211
|
-
await sleep(options.intervalMs);
|
|
5227
|
+
if (!(options.lockWarmupTicks && !state.running && ticked)) await sleep(options.intervalMs);
|
|
5212
5228
|
}
|
|
5213
5229
|
}
|
|
5214
5230
|
function resolveCaptureSessionOptions(options, browserVersion, platform = process.platform) {
|
|
@@ -5225,10 +5241,10 @@ async function waitForCloseWithTimeout(promise) {
|
|
|
5225
5241
|
() => void 0,
|
|
5226
5242
|
() => void 0
|
|
5227
5243
|
),
|
|
5228
|
-
new Promise((
|
|
5244
|
+
new Promise((resolve2) => {
|
|
5229
5245
|
timer = setTimeout(() => {
|
|
5230
5246
|
timedOut = true;
|
|
5231
|
-
|
|
5247
|
+
resolve2();
|
|
5232
5248
|
}, CAPTURE_SESSION_CLOSE_TIMEOUT_MS);
|
|
5233
5249
|
})
|
|
5234
5250
|
]);
|
|
@@ -5717,7 +5733,7 @@ async function pollHfReady(page, timeoutMs, intervalMs = 100) {
|
|
|
5717
5733
|
}
|
|
5718
5734
|
}
|
|
5719
5735
|
}
|
|
5720
|
-
await new Promise((
|
|
5736
|
+
await new Promise((resolve2) => setTimeout(resolve2, intervalMs));
|
|
5721
5737
|
}
|
|
5722
5738
|
const diag = await evaluateHfDiagnostic(page);
|
|
5723
5739
|
if (diag.hasSeek && diag.duration === 0) {
|
|
@@ -5847,7 +5863,7 @@ async function pollSubCompositionTimelines(page, timeoutMs, {
|
|
|
5847
5863
|
);
|
|
5848
5864
|
break;
|
|
5849
5865
|
}
|
|
5850
|
-
await new Promise((
|
|
5866
|
+
await new Promise((resolve2) => setTimeout(resolve2, intervalMs));
|
|
5851
5867
|
}
|
|
5852
5868
|
const pendingIds = ready && knownUnregisteredIds.length === 0 ? [] : await listUnregisteredTimelineIds(page);
|
|
5853
5869
|
if (ready && pendingIds.length > 0 && (getScriptLoadFailures?.() ?? []).length > 0) {
|
|
@@ -5891,7 +5907,7 @@ async function pollVideosReady(page, skipIds, timeoutMs, intervalMs = 100) {
|
|
|
5891
5907
|
const deadline = Date.now() + timeoutMs;
|
|
5892
5908
|
while (Date.now() < deadline) {
|
|
5893
5909
|
if (await check()) return true;
|
|
5894
|
-
await new Promise((
|
|
5910
|
+
await new Promise((resolve2) => setTimeout(resolve2, intervalMs));
|
|
5895
5911
|
}
|
|
5896
5912
|
return check();
|
|
5897
5913
|
}
|
|
@@ -5914,7 +5930,7 @@ async function pollImagesReady(page, timeoutMs, intervalMs = 100) {
|
|
|
5914
5930
|
const deadline = Date.now() + timeoutMs;
|
|
5915
5931
|
while (Date.now() < deadline) {
|
|
5916
5932
|
if (await check()) return true;
|
|
5917
|
-
await new Promise((
|
|
5933
|
+
await new Promise((resolve2) => setTimeout(resolve2, intervalMs));
|
|
5918
5934
|
}
|
|
5919
5935
|
return check();
|
|
5920
5936
|
}
|
|
@@ -6095,7 +6111,7 @@ async function waitForOptionalTailwindReady(page, timeoutMs) {
|
|
|
6095
6111
|
page.evaluate(
|
|
6096
6112
|
`Promise.resolve(window.__tailwindReady).then(() => true, () => false)`
|
|
6097
6113
|
),
|
|
6098
|
-
new Promise((
|
|
6114
|
+
new Promise((resolve2) => setTimeout(() => resolve2(false), timeoutMs))
|
|
6099
6115
|
]);
|
|
6100
6116
|
if (!ready) {
|
|
6101
6117
|
throw new Error(
|
|
@@ -7838,7 +7854,7 @@ import {
|
|
|
7838
7854
|
writeFileSync as writeFileSync2,
|
|
7839
7855
|
writeSync
|
|
7840
7856
|
} from "fs";
|
|
7841
|
-
import { join as join6, dirname as dirname2, extname } from "path";
|
|
7857
|
+
import { join as join6, dirname as dirname2, extname, resolve } from "path";
|
|
7842
7858
|
|
|
7843
7859
|
// ../engine/src/utils/gpuEncoder.ts
|
|
7844
7860
|
import { spawn } from "child_process";
|
|
@@ -7854,8 +7870,8 @@ var ManagedChildProcess = class {
|
|
|
7854
7870
|
this.options = options;
|
|
7855
7871
|
this.now = options.now ?? Date.now;
|
|
7856
7872
|
this.startedAtMs = this.now();
|
|
7857
|
-
this.outcomePromise = new Promise((
|
|
7858
|
-
this.resolveOutcome =
|
|
7873
|
+
this.outcomePromise = new Promise((resolve2) => {
|
|
7874
|
+
this.resolveOutcome = resolve2;
|
|
7859
7875
|
});
|
|
7860
7876
|
child.stderr?.on("data", this.onStderr);
|
|
7861
7877
|
child.once("spawn", this.onSpawn);
|
|
@@ -8608,6 +8624,10 @@ var withoutQuery = (url) => url.split(/[?#]/, 1)[0] ?? url;
|
|
|
8608
8624
|
function declareContentAddressedUrl(url, sha256) {
|
|
8609
8625
|
contentAddressedUrls.set(withoutQuery(url), sha256);
|
|
8610
8626
|
}
|
|
8627
|
+
var probeFactsUrls = /* @__PURE__ */ new Map();
|
|
8628
|
+
function declareProbeFactsUrl(url, factsUrl) {
|
|
8629
|
+
probeFactsUrls.set(withoutQuery(url), factsUrl);
|
|
8630
|
+
}
|
|
8611
8631
|
function mediaFileIdentity(filePath) {
|
|
8612
8632
|
if (/^https?:\/\//i.test(filePath)) {
|
|
8613
8633
|
const sha256 = contentAddressedUrls.get(withoutQuery(filePath));
|
|
@@ -8636,6 +8656,75 @@ function writeMetadataCache(cache, key, identity, promise) {
|
|
|
8636
8656
|
}
|
|
8637
8657
|
);
|
|
8638
8658
|
}
|
|
8659
|
+
var PROBE_FACTS_VERSION = "v2";
|
|
8660
|
+
var PROBE_JSON_ARGS = ["-print_format", "json", "-show_format", "-show_streams"];
|
|
8661
|
+
var storedFacts = /* @__PURE__ */ new Map();
|
|
8662
|
+
function readStoredFacts(filePath) {
|
|
8663
|
+
if (!/^https?:\/\//i.test(filePath)) return void 0;
|
|
8664
|
+
const factsUrl = probeFactsUrls.get(withoutQuery(filePath));
|
|
8665
|
+
if (!factsUrl) return void 0;
|
|
8666
|
+
let facts = storedFacts.get(factsUrl);
|
|
8667
|
+
if (!facts) {
|
|
8668
|
+
facts = (async () => {
|
|
8669
|
+
try {
|
|
8670
|
+
const response = await fetch(factsUrl, { signal: AbortSignal.timeout(1e4) });
|
|
8671
|
+
if (!response.ok) return null;
|
|
8672
|
+
const parsed = JSON.parse(await response.text());
|
|
8673
|
+
return Array.isArray(parsed.ffprobe?.streams) ? parsed : null;
|
|
8674
|
+
} catch {
|
|
8675
|
+
return null;
|
|
8676
|
+
}
|
|
8677
|
+
})();
|
|
8678
|
+
storedFacts.set(factsUrl, facts);
|
|
8679
|
+
}
|
|
8680
|
+
return facts;
|
|
8681
|
+
}
|
|
8682
|
+
function readProbeJson(filePath, signal) {
|
|
8683
|
+
const pending = readStoredFacts(filePath);
|
|
8684
|
+
if (!pending) return runFfprobe(filePath, PROBE_JSON_ARGS, signal);
|
|
8685
|
+
return pending.then(
|
|
8686
|
+
(stored) => stored ? JSON.stringify(stored.ffprobe) : runFfprobe(filePath, PROBE_JSON_ARGS, signal)
|
|
8687
|
+
);
|
|
8688
|
+
}
|
|
8689
|
+
var runtimeFfprobeMajor;
|
|
8690
|
+
function ffprobeMajor() {
|
|
8691
|
+
runtimeFfprobeMajor ??= new Promise((resolve2) => {
|
|
8692
|
+
let out = "";
|
|
8693
|
+
const binary = getFfprobeBinary();
|
|
8694
|
+
const proc = spawn3(binary, ["-version"], { stdio: ["ignore", "pipe", "ignore"] });
|
|
8695
|
+
proc.stdout.on("data", (chunk) => out += String(chunk));
|
|
8696
|
+
proc.on("error", () => resolve2(void 0));
|
|
8697
|
+
proc.on("close", () => resolve2(Number(/version n?(\d+)/.exec(out)?.[1]) || void 0));
|
|
8698
|
+
});
|
|
8699
|
+
return runtimeFfprobeMajor;
|
|
8700
|
+
}
|
|
8701
|
+
async function buildProbeFactsText(filePath, signal) {
|
|
8702
|
+
const facts = {
|
|
8703
|
+
ffprobe: parseProbeJson(await runFfprobe(filePath, PROBE_JSON_ARGS, signal)),
|
|
8704
|
+
ffprobeMajor: await ffprobeMajor()
|
|
8705
|
+
};
|
|
8706
|
+
try {
|
|
8707
|
+
const metadata = await extractMediaMetadata(filePath);
|
|
8708
|
+
const window2 = resolveStreamWindow(filePath, {
|
|
8709
|
+
videoStreamStartSeconds: metadata.videoStreamStartSeconds,
|
|
8710
|
+
videoStreamDurationSeconds: resolvePlayableVideoDuration(metadata) - (metadata.videoStreamLeadSeconds ?? 0)
|
|
8711
|
+
});
|
|
8712
|
+
if (window2.videoStreamDurationSeconds > 0) {
|
|
8713
|
+
facts.finalFrame = {
|
|
8714
|
+
streamStart: window2.videoStreamStartSeconds,
|
|
8715
|
+
streamDuration: window2.videoStreamDurationSeconds,
|
|
8716
|
+
seconds: await extractFinalVideoFrameTimestamp(filePath, window2, signal),
|
|
8717
|
+
lastPacketSeconds: await extractFinalPacketDuration(filePath, window2, signal)
|
|
8718
|
+
};
|
|
8719
|
+
}
|
|
8720
|
+
} catch {
|
|
8721
|
+
if (signal?.aborted) throw signal.reason;
|
|
8722
|
+
}
|
|
8723
|
+
return JSON.stringify(facts);
|
|
8724
|
+
}
|
|
8725
|
+
function resolvePlayableVideoDuration(metadata) {
|
|
8726
|
+
return Number.isFinite(metadata.videoStreamDurationSeconds) && metadata.videoStreamDurationSeconds > 0 ? (metadata.videoStreamLeadSeconds ?? 0) + metadata.videoStreamDurationSeconds : metadata.durationSeconds;
|
|
8727
|
+
}
|
|
8639
8728
|
async function probeMediaOutput(filePath, signal) {
|
|
8640
8729
|
let cache = mediaProbeOutputCache;
|
|
8641
8730
|
if (signal) {
|
|
@@ -8651,11 +8740,7 @@ async function probeMediaOutput(filePath, signal) {
|
|
|
8651
8740
|
}
|
|
8652
8741
|
return cached.promise;
|
|
8653
8742
|
}
|
|
8654
|
-
const promise =
|
|
8655
|
-
filePath,
|
|
8656
|
-
["-print_format", "json", "-show_format", "-show_streams"],
|
|
8657
|
-
signal
|
|
8658
|
-
).then(parseProbeJson);
|
|
8743
|
+
const promise = readProbeJson(filePath, signal).then(parseProbeJson);
|
|
8659
8744
|
if (identity !== null) {
|
|
8660
8745
|
cache.set(filePath, { identity, promise });
|
|
8661
8746
|
if (!signal && cache.size > MEDIA_PROBE_OUTPUT_CACHE_MAX_ENTRIES) {
|
|
@@ -8911,6 +8996,43 @@ function resolveStreamWindow(filePath, metadata) {
|
|
|
8911
8996
|
const cacheKey = `${filePath}\0${String(videoStreamStartSeconds)}\0${String(videoStreamDurationSeconds)}`;
|
|
8912
8997
|
return { videoStreamStartSeconds, videoStreamDurationSeconds, cacheKey };
|
|
8913
8998
|
}
|
|
8999
|
+
function readStoredFinalFrame(filePath, metadata) {
|
|
9000
|
+
const { videoStreamStartSeconds, videoStreamDurationSeconds } = resolveStreamWindow(
|
|
9001
|
+
filePath,
|
|
9002
|
+
metadata
|
|
9003
|
+
);
|
|
9004
|
+
return readStoredFacts(filePath)?.then(async (facts) => {
|
|
9005
|
+
const stored = facts?.finalFrame;
|
|
9006
|
+
if (facts?.ffprobeMajor !== void 0 && facts.ffprobeMajor !== await ffprobeMajor())
|
|
9007
|
+
return void 0;
|
|
9008
|
+
return stored && stored.streamStart === videoStreamStartSeconds && stored.streamDuration === videoStreamDurationSeconds ? stored : void 0;
|
|
9009
|
+
});
|
|
9010
|
+
}
|
|
9011
|
+
async function extractFinalPacketDuration(filePath, window2, signal) {
|
|
9012
|
+
const streamEnd = window2.videoStreamStartSeconds + window2.videoStreamDurationSeconds;
|
|
9013
|
+
const intervalStart = Math.max(window2.videoStreamStartSeconds, streamEnd - 1);
|
|
9014
|
+
const stdout = await runFfprobe(
|
|
9015
|
+
filePath,
|
|
9016
|
+
[
|
|
9017
|
+
"-select_streams",
|
|
9018
|
+
"v:0",
|
|
9019
|
+
"-read_intervals",
|
|
9020
|
+
`${intervalStart}%${streamEnd}`,
|
|
9021
|
+
"-show_entries",
|
|
9022
|
+
"packet=pts_time,duration_time",
|
|
9023
|
+
"-of",
|
|
9024
|
+
"csv=p=0"
|
|
9025
|
+
],
|
|
9026
|
+
signal,
|
|
9027
|
+
{ retainTail: true, maxChars: 64 * 1024 }
|
|
9028
|
+
);
|
|
9029
|
+
const packets = stdout.split("\n").map((line) => line.trim().split(",").map(Number)).filter(([pts, duration]) => Number.isFinite(pts) && Number.isFinite(duration));
|
|
9030
|
+
const last = packets.reduce(
|
|
9031
|
+
(best, packet) => !best || packet[0] > best[0] ? packet : best,
|
|
9032
|
+
void 0
|
|
9033
|
+
);
|
|
9034
|
+
return last?.[1];
|
|
9035
|
+
}
|
|
8914
9036
|
async function extractFinalVideoFrameTimestamp(filePath, metadata, signal) {
|
|
8915
9037
|
const {
|
|
8916
9038
|
videoStreamStartSeconds,
|
|
@@ -8926,6 +9048,9 @@ async function extractFinalVideoFrameTimestamp(filePath, metadata, signal) {
|
|
|
8926
9048
|
const cached = readMetadataCache(probeCache, cacheKey, identity);
|
|
8927
9049
|
if (cached) return cached;
|
|
8928
9050
|
const probePromise = (async () => {
|
|
9051
|
+
const pendingStored = readStoredFinalFrame(filePath, metadata);
|
|
9052
|
+
const stored = pendingStored && await pendingStored;
|
|
9053
|
+
if (stored) return stored.seconds;
|
|
8929
9054
|
if (!(videoDurationSeconds > 0) || !Number.isFinite(videoDurationSeconds)) {
|
|
8930
9055
|
throw new Error(
|
|
8931
9056
|
`[FFmpeg] Cannot locate final video frame for invalid duration ${String(videoDurationSeconds)}`
|
|
@@ -9570,7 +9695,7 @@ var concatListSeq = 0;
|
|
|
9570
9695
|
function writeConcatList(dir, inputPaths) {
|
|
9571
9696
|
concatListSeq += 1;
|
|
9572
9697
|
const listPath = join6(dir, `concat-list-${process.pid}-${concatListSeq}.txt`);
|
|
9573
|
-
const body = inputPaths.map((p) => `file '${p.replace(/'/g, "'\\''")}'`).join("\n");
|
|
9698
|
+
const body = inputPaths.map((p) => `file '${resolve(p).replace(/'/g, "'\\''")}'`).join("\n");
|
|
9574
9699
|
writeFileSync2(listPath, body, "utf-8");
|
|
9575
9700
|
return listPath;
|
|
9576
9701
|
}
|
|
@@ -9931,12 +10056,12 @@ function createFrameReorderBuffer(startFrame, endFrame) {
|
|
|
9931
10056
|
let cursor = startFrame;
|
|
9932
10057
|
let aborted = null;
|
|
9933
10058
|
const pending = /* @__PURE__ */ new Map();
|
|
9934
|
-
const enqueueAt = (frame,
|
|
10059
|
+
const enqueueAt = (frame, resolve2, reject) => {
|
|
9935
10060
|
const list = pending.get(frame);
|
|
9936
10061
|
if (list === void 0) {
|
|
9937
|
-
pending.set(frame, [{ resolve, reject }]);
|
|
10062
|
+
pending.set(frame, [{ resolve: resolve2, reject }]);
|
|
9938
10063
|
} else {
|
|
9939
|
-
list.push({ resolve, reject });
|
|
10064
|
+
list.push({ resolve: resolve2, reject });
|
|
9940
10065
|
}
|
|
9941
10066
|
};
|
|
9942
10067
|
const flushAt = (frame) => {
|
|
@@ -9945,31 +10070,31 @@ function createFrameReorderBuffer(startFrame, endFrame) {
|
|
|
9945
10070
|
pending.delete(frame);
|
|
9946
10071
|
for (const waiter of list) waiter.resolve();
|
|
9947
10072
|
};
|
|
9948
|
-
const waitForFrame = (frame) => new Promise((
|
|
10073
|
+
const waitForFrame = (frame) => new Promise((resolve2, reject) => {
|
|
9949
10074
|
if (aborted) {
|
|
9950
10075
|
reject(aborted);
|
|
9951
10076
|
return;
|
|
9952
10077
|
}
|
|
9953
10078
|
if (frame === cursor) {
|
|
9954
|
-
|
|
10079
|
+
resolve2();
|
|
9955
10080
|
return;
|
|
9956
10081
|
}
|
|
9957
|
-
enqueueAt(frame,
|
|
10082
|
+
enqueueAt(frame, resolve2, reject);
|
|
9958
10083
|
});
|
|
9959
10084
|
const advanceTo = (frame) => {
|
|
9960
10085
|
cursor = frame;
|
|
9961
10086
|
flushAt(frame);
|
|
9962
10087
|
};
|
|
9963
|
-
const waitForAllDone = () => new Promise((
|
|
10088
|
+
const waitForAllDone = () => new Promise((resolve2, reject) => {
|
|
9964
10089
|
if (aborted) {
|
|
9965
10090
|
reject(aborted);
|
|
9966
10091
|
return;
|
|
9967
10092
|
}
|
|
9968
10093
|
if (cursor >= endFrame) {
|
|
9969
|
-
|
|
10094
|
+
resolve2();
|
|
9970
10095
|
return;
|
|
9971
10096
|
}
|
|
9972
|
-
enqueueAt(endFrame,
|
|
10097
|
+
enqueueAt(endFrame, resolve2, reject);
|
|
9973
10098
|
});
|
|
9974
10099
|
const abort = (err) => {
|
|
9975
10100
|
if (aborted) return;
|
|
@@ -10264,8 +10389,8 @@ async function spawnStreamingEncoder(outputPath, options, signal, config) {
|
|
|
10264
10389
|
}
|
|
10265
10390
|
const stdin = ffmpeg.stdin;
|
|
10266
10391
|
if (stdin && !stdin.destroyed) {
|
|
10267
|
-
await new Promise((
|
|
10268
|
-
stdin.end(() =>
|
|
10392
|
+
await new Promise((resolve2) => {
|
|
10393
|
+
stdin.end(() => resolve2());
|
|
10269
10394
|
});
|
|
10270
10395
|
}
|
|
10271
10396
|
const outcome = await exitPromise;
|
|
@@ -10403,14 +10528,14 @@ import { cpus } from "os";
|
|
|
10403
10528
|
function createConcurrencyLimit(limit) {
|
|
10404
10529
|
let active = 0;
|
|
10405
10530
|
const waiting = [];
|
|
10406
|
-
const waitForSlot = (signal) => new Promise((
|
|
10531
|
+
const waitForSlot = (signal) => new Promise((resolve2) => {
|
|
10407
10532
|
const granted = () => {
|
|
10408
10533
|
signal?.removeEventListener("abort", aborted);
|
|
10409
|
-
|
|
10534
|
+
resolve2(true);
|
|
10410
10535
|
};
|
|
10411
10536
|
const aborted = () => {
|
|
10412
10537
|
waiting.splice(waiting.indexOf(granted), 1);
|
|
10413
|
-
|
|
10538
|
+
resolve2(false);
|
|
10414
10539
|
};
|
|
10415
10540
|
waiting.push(granted);
|
|
10416
10541
|
signal?.addEventListener("abort", aborted, { once: true });
|
|
@@ -10713,10 +10838,10 @@ async function waitForCacheLock(signal) {
|
|
|
10713
10838
|
if (signal?.aborted) {
|
|
10714
10839
|
throw new UrlDownloadError("cancelled", false, "Download cancelled");
|
|
10715
10840
|
}
|
|
10716
|
-
await new Promise((
|
|
10841
|
+
await new Promise((resolve2, reject) => {
|
|
10717
10842
|
const timeout = setTimeout(() => {
|
|
10718
10843
|
signal?.removeEventListener("abort", onAbort);
|
|
10719
|
-
|
|
10844
|
+
resolve2();
|
|
10720
10845
|
}, CACHE_LOCK_POLL_MS);
|
|
10721
10846
|
const onAbort = () => {
|
|
10722
10847
|
clearTimeout(timeout);
|
|
@@ -11528,12 +11653,52 @@ import {
|
|
|
11528
11653
|
lstatSync as lstatSync2,
|
|
11529
11654
|
mkdirSync as mkdirSync5,
|
|
11530
11655
|
readdirSync as readdirSync5,
|
|
11531
|
-
renameSync,
|
|
11532
11656
|
rmSync as rmSync3,
|
|
11533
11657
|
statSync as statSync6,
|
|
11534
11658
|
utimesSync,
|
|
11535
11659
|
writeFileSync as writeFileSync3
|
|
11536
11660
|
} from "fs";
|
|
11661
|
+
|
|
11662
|
+
// ../engine/src/utils/renameWithRetry.ts
|
|
11663
|
+
import { renameSync } from "fs";
|
|
11664
|
+
import { rename } from "fs/promises";
|
|
11665
|
+
var RETRYABLE = /* @__PURE__ */ new Set(["EPERM", "EACCES", "EBUSY"]);
|
|
11666
|
+
var BACKOFF_MS = [10, 20, 40, 80, 160, 320, 640];
|
|
11667
|
+
function isRetryable(error, platform) {
|
|
11668
|
+
if (platform !== "win32") return false;
|
|
11669
|
+
return RETRYABLE.has(error?.code ?? "");
|
|
11670
|
+
}
|
|
11671
|
+
function sleepSync(ms) {
|
|
11672
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
11673
|
+
}
|
|
11674
|
+
function renameWithRetry(from, to, options = {}) {
|
|
11675
|
+
const doRename = options.rename ?? renameSync;
|
|
11676
|
+
const platform = options.platform ?? process.platform;
|
|
11677
|
+
for (let attempt = 0; ; attempt++) {
|
|
11678
|
+
try {
|
|
11679
|
+
doRename(from, to);
|
|
11680
|
+
return;
|
|
11681
|
+
} catch (error) {
|
|
11682
|
+
if (attempt >= BACKOFF_MS.length || !isRetryable(error, platform)) throw error;
|
|
11683
|
+
sleepSync(BACKOFF_MS[attempt]);
|
|
11684
|
+
}
|
|
11685
|
+
}
|
|
11686
|
+
}
|
|
11687
|
+
async function renameWithRetryAsync(from, to, options = {}) {
|
|
11688
|
+
const doRename = options.rename ?? rename;
|
|
11689
|
+
const platform = options.platform ?? process.platform;
|
|
11690
|
+
for (let attempt = 0; ; attempt++) {
|
|
11691
|
+
try {
|
|
11692
|
+
await doRename(from, to);
|
|
11693
|
+
return;
|
|
11694
|
+
} catch (error) {
|
|
11695
|
+
if (attempt >= BACKOFF_MS.length || !isRetryable(error, platform)) throw error;
|
|
11696
|
+
await new Promise((resolve2) => setTimeout(resolve2, BACKOFF_MS[attempt]));
|
|
11697
|
+
}
|
|
11698
|
+
}
|
|
11699
|
+
}
|
|
11700
|
+
|
|
11701
|
+
// ../engine/src/services/extractionCache.ts
|
|
11537
11702
|
import { join as join9 } from "path";
|
|
11538
11703
|
var COMPLETE_SENTINEL = ".hf-complete";
|
|
11539
11704
|
var GC_MARKER = ".hf-last-gc";
|
|
@@ -11608,7 +11773,7 @@ function publishCacheEntry(entry, partialDir) {
|
|
|
11608
11773
|
return { dir: partialDir, published: false };
|
|
11609
11774
|
}
|
|
11610
11775
|
try {
|
|
11611
|
-
|
|
11776
|
+
renameWithRetry(partialDir, entry.dir);
|
|
11612
11777
|
return { dir: entry.dir, published: true };
|
|
11613
11778
|
} catch (err) {
|
|
11614
11779
|
if (!isTargetExistsRenameError(err)) return { dir: partialDir, published: false };
|
|
@@ -11621,7 +11786,7 @@ function publishCacheEntry(entry, partialDir) {
|
|
|
11621
11786
|
return { dir: partialDir, published: false };
|
|
11622
11787
|
}
|
|
11623
11788
|
try {
|
|
11624
|
-
|
|
11789
|
+
renameWithRetry(partialDir, entry.dir);
|
|
11625
11790
|
return { dir: entry.dir, published: true };
|
|
11626
11791
|
} catch {
|
|
11627
11792
|
return adoptPublishedWinner(entry, partialDir) ?? { dir: partialDir, published: false };
|
|
@@ -11806,6 +11971,24 @@ function extractionFrameCountForDuration(durationSeconds, fps, isVFR) {
|
|
|
11806
11971
|
const frames = Number(frameCount);
|
|
11807
11972
|
return Math.max(1, Number.isSafeInteger(frames) ? frames : Number.MAX_SAFE_INTEGER);
|
|
11808
11973
|
}
|
|
11974
|
+
function exactSourceRate(probed) {
|
|
11975
|
+
const nominal = Math.round(probed * 1.001);
|
|
11976
|
+
return [nominal, nominal * 1e3 / 1001].find((rate) => Math.abs(rate - probed) <= 5e-3 + 1e-9) ?? null;
|
|
11977
|
+
}
|
|
11978
|
+
function tailFramesFromFinalFrame(input) {
|
|
11979
|
+
const sourceRate = exactSourceRate(input.sourceFps);
|
|
11980
|
+
if (!sourceRate || !(input.outputFps > 0)) return null;
|
|
11981
|
+
const lead = input.streamLeadSeconds;
|
|
11982
|
+
if (lead !== 0 && !(Math.abs((input.lastPacketSeconds ?? NaN) - 1 / sourceRate) <= 1e-4)) {
|
|
11983
|
+
return null;
|
|
11984
|
+
}
|
|
11985
|
+
const seek = input.startTime + input.firstFrame / input.outputFps;
|
|
11986
|
+
const slots = (lead + input.finalFrameSeconds + 1 / sourceRate - seek) * input.outputFps;
|
|
11987
|
+
const distanceToSlot = Math.abs(slots - Math.round(slots));
|
|
11988
|
+
if (distanceToSlot >= 5e-5 && distanceToSlot < 5e-4) return null;
|
|
11989
|
+
const count = Math.min(input.tailFrames, Math.ceil(slots - 5e-5));
|
|
11990
|
+
return count > 0 ? count : null;
|
|
11991
|
+
}
|
|
11809
11992
|
var DOWNLOAD_SUBDIR = "_downloads";
|
|
11810
11993
|
var EXTRACT_CACHE_MIN_AGE_MS = 60 * 60 * 1e3;
|
|
11811
11994
|
var GC_STALENESS_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -12180,6 +12363,8 @@ function undoTickRoundingOnTheSourceFrameGrid(seek, lead) {
|
|
|
12180
12363
|
}
|
|
12181
12364
|
var EXTRACTION_SLOTS = Math.max(1, Math.floor(cpus().length / 2));
|
|
12182
12365
|
var inExtractionSlot = createConcurrencyLimit(EXTRACTION_SLOTS);
|
|
12366
|
+
var TAIL_PROBE_SLOTS = Math.max(1, Number(process.env.HF_TAIL_PROBE_SLOTS) || 16);
|
|
12367
|
+
var inTailProbeSlot = createConcurrencyLimit(TAIL_PROBE_SLOTS);
|
|
12183
12368
|
function splitFrameRanges(ranges, segmentFrames) {
|
|
12184
12369
|
const segments = [];
|
|
12185
12370
|
for (const range of ranges) {
|
|
@@ -12193,7 +12378,7 @@ function splitFrameRanges(ranges, segmentFrames) {
|
|
|
12193
12378
|
return segments;
|
|
12194
12379
|
}
|
|
12195
12380
|
async function runSegmentedExtraction(job) {
|
|
12196
|
-
const { decodeArgs, filterAndEncodeArgs, videoPath, startTime, fps, segments } = job;
|
|
12381
|
+
const { decodeArgs, filterAndEncodeArgs, videoPath, startTime, fps, segments, gate } = job;
|
|
12197
12382
|
const segmentCount = segments.length;
|
|
12198
12383
|
const failed = new AbortController();
|
|
12199
12384
|
const signal = job.runOptions.signal ? AbortSignal.any([job.runOptions.signal, failed.signal]) : failed.signal;
|
|
@@ -12204,7 +12389,7 @@ async function runSegmentedExtraction(job) {
|
|
|
12204
12389
|
const index = next++;
|
|
12205
12390
|
const { firstFrame, frames } = segments[index];
|
|
12206
12391
|
const seek = startTime + firstFrame / fps;
|
|
12207
|
-
const result = await
|
|
12392
|
+
const result = await gate(
|
|
12208
12393
|
() => runFfmpeg(
|
|
12209
12394
|
[
|
|
12210
12395
|
...decodeArgs,
|
|
@@ -12355,6 +12540,7 @@ async function extractVideoFramesRangeUnredacted(videoPath, videoId, startTime,
|
|
|
12355
12540
|
videoPath,
|
|
12356
12541
|
startTime,
|
|
12357
12542
|
fps,
|
|
12543
|
+
gate: options.tailProbe ? inTailProbeSlot : inExtractionSlot,
|
|
12358
12544
|
segments: splitFrameRanges(
|
|
12359
12545
|
options.frameRanges ?? [{ firstFrame: 0, frames: totalFrames }],
|
|
12360
12546
|
segmentFrames
|
|
@@ -12455,9 +12641,6 @@ function resolveSegmentDuration(requested, mediaStart, sourceDuration) {
|
|
|
12455
12641
|
const sourceRemaining = sourceDuration - mediaStart;
|
|
12456
12642
|
return sourceRemaining > 0 ? sourceRemaining : sourceDuration;
|
|
12457
12643
|
}
|
|
12458
|
-
function resolvePlayableVideoDuration(metadata) {
|
|
12459
|
-
return Number.isFinite(metadata.videoStreamDurationSeconds) && metadata.videoStreamDurationSeconds > 0 ? (metadata.videoStreamLeadSeconds ?? 0) + metadata.videoStreamDurationSeconds : metadata.durationSeconds;
|
|
12460
|
-
}
|
|
12461
12644
|
function canHoldFinalFramePastEof(video) {
|
|
12462
12645
|
const timelineDuration = video.end - video.start;
|
|
12463
12646
|
return !video.loop && Number.isFinite(timelineDuration) && timelineDuration > 0;
|
|
@@ -13136,23 +13319,7 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config, c
|
|
|
13136
13319
|
);
|
|
13137
13320
|
const tailFrames = Math.min(expectedFrames, Math.ceil(fps));
|
|
13138
13321
|
if (expectedFrames <= tailFrames) return null;
|
|
13139
|
-
const
|
|
13140
|
-
try {
|
|
13141
|
-
const tail = await extractVideoFramesRange(
|
|
13142
|
-
work.videoPath,
|
|
13143
|
-
work.video.id,
|
|
13144
|
-
work.extractionMediaStart,
|
|
13145
|
-
work.videoDuration,
|
|
13146
|
-
{
|
|
13147
|
-
...scopedExtractionOptions(work),
|
|
13148
|
-
frameRanges: [{ firstFrame: expectedFrames - tailFrames, frames: tailFrames }]
|
|
13149
|
-
},
|
|
13150
|
-
signal,
|
|
13151
|
-
config,
|
|
13152
|
-
probeDir
|
|
13153
|
-
);
|
|
13154
|
-
const totalFrames = expectedFrames - tailFrames + tail.totalFrames;
|
|
13155
|
-
if (totalFrames <= expectedFrames * 0.6) return null;
|
|
13322
|
+
const deferred = (totalFrames) => {
|
|
13156
13323
|
const outputDir = join10(options.outputDir, work.video.id);
|
|
13157
13324
|
mkdirSync6(outputDir, { recursive: true });
|
|
13158
13325
|
return {
|
|
@@ -13170,6 +13337,45 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config, c
|
|
|
13170
13337
|
format: work.format
|
|
13171
13338
|
}
|
|
13172
13339
|
};
|
|
13340
|
+
};
|
|
13341
|
+
if (work.extractionMediaStart + work.videoDuration + 1 <= resolvePlayableVideoDuration(work.metadata)) {
|
|
13342
|
+
return deferred(expectedFrames);
|
|
13343
|
+
}
|
|
13344
|
+
const firstTailFrame = expectedFrames - tailFrames;
|
|
13345
|
+
const storedFinalFrame = await readStoredFinalFrame(work.videoPath, work.metadata);
|
|
13346
|
+
const storedTailFrames = storedFinalFrame === void 0 ? null : tailFramesFromFinalFrame({
|
|
13347
|
+
startTime: work.extractionMediaStart,
|
|
13348
|
+
firstFrame: firstTailFrame,
|
|
13349
|
+
tailFrames,
|
|
13350
|
+
outputFps: fps,
|
|
13351
|
+
sourceFps: work.metadata.fps,
|
|
13352
|
+
finalFrameSeconds: storedFinalFrame.seconds,
|
|
13353
|
+
lastPacketSeconds: storedFinalFrame.lastPacketSeconds,
|
|
13354
|
+
streamLeadSeconds: work.metadata.videoStreamLeadSeconds ?? 0
|
|
13355
|
+
});
|
|
13356
|
+
if (storedTailFrames !== null) {
|
|
13357
|
+
const totalFrames = firstTailFrame + storedTailFrames;
|
|
13358
|
+
return totalFrames <= expectedFrames * 0.6 ? null : deferred(totalFrames);
|
|
13359
|
+
}
|
|
13360
|
+
const probeDir = join10(options.outputDir, `${work.video.id}.tail-probe`);
|
|
13361
|
+
try {
|
|
13362
|
+
const tail = await extractVideoFramesRange(
|
|
13363
|
+
work.videoPath,
|
|
13364
|
+
work.video.id,
|
|
13365
|
+
work.extractionMediaStart,
|
|
13366
|
+
work.videoDuration,
|
|
13367
|
+
{
|
|
13368
|
+
...scopedExtractionOptions(work),
|
|
13369
|
+
frameRanges: [{ firstFrame: firstTailFrame, frames: tailFrames }],
|
|
13370
|
+
tailProbe: isHttpUrl(work.videoPath)
|
|
13371
|
+
},
|
|
13372
|
+
signal,
|
|
13373
|
+
config,
|
|
13374
|
+
probeDir
|
|
13375
|
+
);
|
|
13376
|
+
const totalFrames = firstTailFrame + tail.totalFrames;
|
|
13377
|
+
if (totalFrames <= expectedFrames * 0.6) return null;
|
|
13378
|
+
return deferred(totalFrames);
|
|
13173
13379
|
} catch {
|
|
13174
13380
|
return null;
|
|
13175
13381
|
} finally {
|
|
@@ -14048,16 +14254,7 @@ async function queryElementStacking(page, nativeHdrIds) {
|
|
|
14048
14254
|
}
|
|
14049
14255
|
|
|
14050
14256
|
// ../engine/src/services/audioMixer.ts
|
|
14051
|
-
import {
|
|
14052
|
-
closeSync as closeSync4,
|
|
14053
|
-
existsSync as existsSync11,
|
|
14054
|
-
mkdirSync as mkdirSync7,
|
|
14055
|
-
mkdtempSync as mkdtempSync7,
|
|
14056
|
-
openSync as openSync4,
|
|
14057
|
-
renameSync as renameSync3,
|
|
14058
|
-
rmSync as rmSync8,
|
|
14059
|
-
writeFileSync as writeFileSync7
|
|
14060
|
-
} from "fs";
|
|
14257
|
+
import { closeSync as closeSync4, existsSync as existsSync11, mkdirSync as mkdirSync7, mkdtempSync as mkdtempSync7, openSync as openSync4, rmSync as rmSync8, writeFileSync as writeFileSync7 } from "fs";
|
|
14061
14258
|
import { join as join14, dirname as dirname7, isAbsolute, relative } from "path";
|
|
14062
14259
|
|
|
14063
14260
|
// ../engine/src/utils/notMediaPayload.ts
|
|
@@ -14176,6 +14373,7 @@ function clampFadesToDuration(fades, duration) {
|
|
|
14176
14373
|
import { cpus as cpus2 } from "os";
|
|
14177
14374
|
|
|
14178
14375
|
// ../engine/src/services/aacEncode.ts
|
|
14376
|
+
import { execFile as execFile3 } from "child_process";
|
|
14179
14377
|
import { mkdtempSync as mkdtempSync4, readFileSync as readFileSync5, rmSync as rmSync5, writeFileSync as writeFileSync4 } from "fs";
|
|
14180
14378
|
import { dirname as dirname5, join as join11 } from "path";
|
|
14181
14379
|
var SAMPLE_RATE = 48e3;
|
|
@@ -14211,12 +14409,35 @@ function planSegments(totalDuration, count) {
|
|
|
14211
14409
|
return { trim, keepFrom: cut - firstFrame, keepTo: next - firstFrame };
|
|
14212
14410
|
});
|
|
14213
14411
|
}
|
|
14412
|
+
var settsDurationSupport = /* @__PURE__ */ new Map();
|
|
14413
|
+
function supportsSettsDuration(binary = getFfmpegBinary()) {
|
|
14414
|
+
let supported = settsDurationSupport.get(binary);
|
|
14415
|
+
if (!supported) {
|
|
14416
|
+
supported = new Promise((resolve2) => {
|
|
14417
|
+
execFile3(binary, ["-hide_banner", "-h", "bsf=setts"], (error, stdout) => {
|
|
14418
|
+
resolve2(error !== null || stdout.includes("duration"));
|
|
14419
|
+
});
|
|
14420
|
+
});
|
|
14421
|
+
settsDurationSupport.set(binary, supported);
|
|
14422
|
+
}
|
|
14423
|
+
return supported;
|
|
14424
|
+
}
|
|
14425
|
+
function encodeInOnePass(input, outputPath, { signal, timeout, filter }) {
|
|
14426
|
+
const filters = [filter, `aresample=${SAMPLE_RATE}`].filter(Boolean).join(",");
|
|
14427
|
+
return runFfmpeg(["-i", input, "-af", filters, ...AAC_ARGS, "-y", outputPath], {
|
|
14428
|
+
signal,
|
|
14429
|
+
timeout
|
|
14430
|
+
});
|
|
14431
|
+
}
|
|
14214
14432
|
async function encodeAac(input, outputPath, totalDuration, {
|
|
14215
14433
|
signal,
|
|
14216
14434
|
timeout,
|
|
14217
14435
|
filter,
|
|
14218
14436
|
segments: count = aacSegmentCount(totalDuration)
|
|
14219
14437
|
}) {
|
|
14438
|
+
if (!await supportsSettsDuration()) {
|
|
14439
|
+
return encodeInOnePass(input, outputPath, { signal, timeout, filter });
|
|
14440
|
+
}
|
|
14220
14441
|
const dir = mkdtempSync4(join11(dirname5(outputPath), ".aac-segments-"));
|
|
14221
14442
|
try {
|
|
14222
14443
|
const segments = planSegments(totalDuration, count).map((segment, k) => ({
|
|
@@ -14382,7 +14603,7 @@ function audioFailureDiagnostics(values) {
|
|
|
14382
14603
|
}
|
|
14383
14604
|
|
|
14384
14605
|
// ../engine/src/services/audioVolumeEnvelope.ts
|
|
14385
|
-
import { mkdtempSync as mkdtempSync5, readFileSync as readFileSync6,
|
|
14606
|
+
import { mkdtempSync as mkdtempSync5, readFileSync as readFileSync6, rmSync as rmSync6, writeFileSync as writeFileSync5 } from "fs";
|
|
14386
14607
|
import { dirname as dirname6, join as join12 } from "path";
|
|
14387
14608
|
|
|
14388
14609
|
// ../core/dist/runtime/mediaVolumeEnvelope.js
|
|
@@ -14512,7 +14733,7 @@ function applyVolumeEnvelopeToWav(wavPath, keyframes, trackStart, baseVolume) {
|
|
|
14512
14733
|
stagingDir = mkdtempSync5(join12(dirname6(wavPath), ".hf-volume-"));
|
|
14513
14734
|
const tempPath = join12(stagingDir, "audio.wav");
|
|
14514
14735
|
writeFileSync5(tempPath, buffer, { flag: "wx" });
|
|
14515
|
-
|
|
14736
|
+
renameWithRetry(tempPath, wavPath);
|
|
14516
14737
|
return true;
|
|
14517
14738
|
} catch {
|
|
14518
14739
|
return false;
|
|
@@ -15502,6 +15723,9 @@ function volumeLaneKeyframes(automation, trackStart, duration, gain, gainAhead =
|
|
|
15502
15723
|
function parseMasterFxChain(html) {
|
|
15503
15724
|
return readMasterFxChain(parseHTML(unwrapTemplate(html)).document);
|
|
15504
15725
|
}
|
|
15726
|
+
function videoAudioId(videoId) {
|
|
15727
|
+
return `${videoId}-audio`;
|
|
15728
|
+
}
|
|
15505
15729
|
function parseAudioElements(html) {
|
|
15506
15730
|
const elements = [];
|
|
15507
15731
|
const { document: document2 } = parseHTML(unwrapTemplate(html));
|
|
@@ -15564,7 +15788,7 @@ function parseAudioElements(html) {
|
|
|
15564
15788
|
const src = resolveMediaElementSrc(el);
|
|
15565
15789
|
if (!id || !src || isHidden(el) || memberGroupHidden(el)) continue;
|
|
15566
15790
|
if (isKnownInactiveTimelineWindow(el, resolveStart(el))) continue;
|
|
15567
|
-
elements.push(build(el,
|
|
15791
|
+
elements.push(build(el, videoAudioId(id), src, "video", true));
|
|
15568
15792
|
}
|
|
15569
15793
|
return elements;
|
|
15570
15794
|
}
|
|
@@ -16010,7 +16234,7 @@ async function mixGroupMembers(memberTracks, outputPath, totalDuration, signal,
|
|
|
16010
16234
|
try {
|
|
16011
16235
|
const summed = await sumInSlices(memberTracks, scratchDir, totalDuration, signal, config);
|
|
16012
16236
|
if (!summed.success) return summed;
|
|
16013
|
-
|
|
16237
|
+
renameWithRetry(summed.track.srcPath, outputPath);
|
|
16014
16238
|
return { success: true, degradedAutomation: summed.degradedAutomation };
|
|
16015
16239
|
} finally {
|
|
16016
16240
|
rmSync8(scratchDir, { recursive: true, force: true });
|
|
@@ -16052,12 +16276,15 @@ async function mixAudioTracks(tracks, outputPath, totalDuration, signal, config)
|
|
|
16052
16276
|
}
|
|
16053
16277
|
async function mixThroughFloatSum(tracks, masterChain, outputPath, workDir, totalDuration, signal, config) {
|
|
16054
16278
|
const sumPath = join14(workDir, "master-sum.wav");
|
|
16279
|
+
const mixStart = Date.now();
|
|
16055
16280
|
const sum = await mixAudioTracks(tracks, sumPath, totalDuration, signal, config);
|
|
16056
16281
|
if (!sum.success) return { ...sum, outputPath };
|
|
16282
|
+
const masterStart = Date.now();
|
|
16057
16283
|
const encoderInput = masterChain ? (await applyAudioFxChain(sumPath, masterChain, join14(workDir, "master-fx.wav"), {
|
|
16058
16284
|
trackId: "master",
|
|
16059
16285
|
signal
|
|
16060
16286
|
})).path : sumPath;
|
|
16287
|
+
const encodeStart = Date.now();
|
|
16061
16288
|
const encoded = await encodeAac(encoderInput, outputPath, totalDuration, {
|
|
16062
16289
|
signal,
|
|
16063
16290
|
timeout: config?.ffmpegProcessTimeout ?? DEFAULT_CONFIG.ffmpegProcessTimeout
|
|
@@ -16077,8 +16304,17 @@ async function mixThroughFloatSum(tracks, masterChain, outputPath, workDir, tota
|
|
|
16077
16304
|
failures: [failure]
|
|
16078
16305
|
};
|
|
16079
16306
|
}
|
|
16080
|
-
if (config?.keepEncoderInputAt)
|
|
16081
|
-
return {
|
|
16307
|
+
if (config?.keepEncoderInputAt) renameWithRetry(encoderInput, config.keepEncoderInputAt);
|
|
16308
|
+
return {
|
|
16309
|
+
...sum,
|
|
16310
|
+
outputPath,
|
|
16311
|
+
durationMs: sum.durationMs + encoded.durationMs,
|
|
16312
|
+
phaseMs: {
|
|
16313
|
+
mix: masterStart - mixStart,
|
|
16314
|
+
master: encodeStart - masterStart,
|
|
16315
|
+
encode: Date.now() - encodeStart
|
|
16316
|
+
}
|
|
16317
|
+
};
|
|
16082
16318
|
}
|
|
16083
16319
|
async function processCompositionAudio(elements, baseDir, workDir, outputPath, totalDuration, signal, config, compiledDir) {
|
|
16084
16320
|
const startMs = Date.now();
|
|
@@ -16363,6 +16599,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
|
|
|
16363
16599
|
failures
|
|
16364
16600
|
};
|
|
16365
16601
|
};
|
|
16602
|
+
const prepareMs = Date.now() - startMs;
|
|
16366
16603
|
if (failures.length > 0) return bail();
|
|
16367
16604
|
let masterChain;
|
|
16368
16605
|
const masterFxJson = config?.masterFxChain;
|
|
@@ -16473,6 +16710,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
|
|
|
16473
16710
|
}
|
|
16474
16711
|
}
|
|
16475
16712
|
if (failures.length > 0) return bail();
|
|
16713
|
+
const groupsMs = Date.now() - startMs - prepareMs;
|
|
16476
16714
|
let mixResult;
|
|
16477
16715
|
try {
|
|
16478
16716
|
mixResult = tracks.length > 0 ? await mixThroughFloatSum(
|
|
@@ -16491,6 +16729,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
|
|
|
16491
16729
|
return {
|
|
16492
16730
|
...mixResult,
|
|
16493
16731
|
durationMs: Date.now() - startMs,
|
|
16732
|
+
phaseMs: { prepare: prepareMs, groups: groupsMs, ...mixResult.phaseMs },
|
|
16494
16733
|
// Both, when both degraded. `mixResult.error ?? degradedNote` reported only
|
|
16495
16734
|
// the outer mix and dropped the one that names which GROUPS lost their
|
|
16496
16735
|
// members' automation — two different losses, and the operator needs to
|
|
@@ -16502,18 +16741,18 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
|
|
|
16502
16741
|
// ../engine/src/services/parallelCoordinator.ts
|
|
16503
16742
|
import { cpus as cpus3, freemem } from "os";
|
|
16504
16743
|
import { existsSync as existsSync12, mkdirSync as mkdirSync8, readdirSync as readdirSync6 } from "fs";
|
|
16505
|
-
import { copyFile, readFile as readFile2
|
|
16744
|
+
import { copyFile, readFile as readFile2 } from "fs/promises";
|
|
16506
16745
|
import { join as join16 } from "path";
|
|
16507
16746
|
import { getHeapStatistics } from "v8";
|
|
16508
16747
|
|
|
16509
16748
|
// ../engine/src/utils/psnr.ts
|
|
16510
|
-
import { execFile as
|
|
16749
|
+
import { execFile as execFile4 } from "child_process";
|
|
16511
16750
|
import { mkdtemp, rm, writeFile } from "fs/promises";
|
|
16512
16751
|
import { tmpdir as tmpdir4 } from "os";
|
|
16513
16752
|
import { join as join15 } from "path";
|
|
16514
16753
|
import { promisify as promisify3 } from "util";
|
|
16515
16754
|
async function psnrDb(a, b) {
|
|
16516
|
-
const execFileP = promisify3(
|
|
16755
|
+
const execFileP = promisify3(execFile4);
|
|
16517
16756
|
const dir = await mkdtemp(join15(tmpdir4(), "hf-de-verify-"));
|
|
16518
16757
|
try {
|
|
16519
16758
|
const pa = join15(dir, "a.jpg");
|
|
@@ -16766,7 +17005,7 @@ function shouldVerifyWorkerGpu(workerId, config) {
|
|
|
16766
17005
|
}
|
|
16767
17006
|
function withParallelWorkerDeadline(promise, diagnostic, timeoutMs, signal) {
|
|
16768
17007
|
if (signal?.aborted) return Promise.reject(new Error("Parallel worker cancelled"));
|
|
16769
|
-
return new Promise((
|
|
17008
|
+
return new Promise((resolve2, reject) => {
|
|
16770
17009
|
let timer;
|
|
16771
17010
|
const cleanup = () => {
|
|
16772
17011
|
if (timer) clearTimeout(timer);
|
|
@@ -16791,7 +17030,7 @@ function withParallelWorkerDeadline(promise, diagnostic, timeoutMs, signal) {
|
|
|
16791
17030
|
promise.then(
|
|
16792
17031
|
(value) => {
|
|
16793
17032
|
cleanup();
|
|
16794
|
-
|
|
17033
|
+
resolve2(value);
|
|
16795
17034
|
},
|
|
16796
17035
|
(error) => {
|
|
16797
17036
|
cleanup();
|
|
@@ -17047,7 +17286,8 @@ async function executeWorkerTask(task, serverUrl, captureOptions, createBeforeCa
|
|
|
17047
17286
|
endFrame: task.endFrame,
|
|
17048
17287
|
frameStride: task.frameStride,
|
|
17049
17288
|
durationMs: Date.now() - startTime,
|
|
17050
|
-
perf
|
|
17289
|
+
perf,
|
|
17290
|
+
pageErrorLines: pageErrorLinesOf(activeSession)
|
|
17051
17291
|
};
|
|
17052
17292
|
} catch (error) {
|
|
17053
17293
|
const diagnostics = session ? selectWorkerDiagnostics(session.browserConsoleBuffer) : [];
|
|
@@ -17060,7 +17300,8 @@ async function executeWorkerTask(task, serverUrl, captureOptions, createBeforeCa
|
|
|
17060
17300
|
};
|
|
17061
17301
|
const failure = classifyCaptureFailure(error, {
|
|
17062
17302
|
signal,
|
|
17063
|
-
workerDiagnostics: [workerDiagnostic]
|
|
17303
|
+
workerDiagnostics: [workerDiagnostic],
|
|
17304
|
+
pageErrorLines: session ? pageErrorLinesOf(session) : void 0
|
|
17064
17305
|
});
|
|
17065
17306
|
onFailure?.(failure);
|
|
17066
17307
|
return {
|
|
@@ -17073,6 +17314,7 @@ async function executeWorkerTask(task, serverUrl, captureOptions, createBeforeCa
|
|
|
17073
17314
|
perf,
|
|
17074
17315
|
error: failure.message,
|
|
17075
17316
|
diagnostics: diagnostics.length > 0 ? diagnostics : void 0,
|
|
17317
|
+
pageErrorLines: session ? pageErrorLinesOf(session) : void 0,
|
|
17076
17318
|
failure
|
|
17077
17319
|
};
|
|
17078
17320
|
} finally {
|
|
@@ -17089,6 +17331,9 @@ function isPoolFatalWorkerFailure(failure, streaming) {
|
|
|
17089
17331
|
if (streaming) return failure.kind !== "cancelled";
|
|
17090
17332
|
return isFatalCaptureFailure(failure);
|
|
17091
17333
|
}
|
|
17334
|
+
function pageErrorLinesOf(session) {
|
|
17335
|
+
return session.browserConsoleBuffer.filter((line) => line.includes("PAGEERROR"));
|
|
17336
|
+
}
|
|
17092
17337
|
function createPoolFailureHandler(args) {
|
|
17093
17338
|
let firstFatalFailure;
|
|
17094
17339
|
return {
|
|
@@ -17180,7 +17425,8 @@ async function executeParallelCapture(serverUrl, workDir, tasks, captureOptions,
|
|
|
17180
17425
|
kind: representative?.kind ?? "io",
|
|
17181
17426
|
message: `[Parallel] Capture failed: ${errorMessages}`,
|
|
17182
17427
|
cause: representative,
|
|
17183
|
-
workerDiagnostics
|
|
17428
|
+
workerDiagnostics,
|
|
17429
|
+
pageErrorLines: [...new Set(results.flatMap((result) => result.pageErrorLines ?? []))]
|
|
17184
17430
|
});
|
|
17185
17431
|
}
|
|
17186
17432
|
return results;
|
|
@@ -17198,7 +17444,7 @@ async function mergeWorkerFrames(workDir, tasks, outputDir) {
|
|
|
17198
17444
|
const sourcePath = join16(task.outputDir, file);
|
|
17199
17445
|
const targetPath = join16(outputDir, file);
|
|
17200
17446
|
try {
|
|
17201
|
-
await
|
|
17447
|
+
await renameWithRetryAsync(sourcePath, targetPath);
|
|
17202
17448
|
} catch {
|
|
17203
17449
|
await copyFile(sourcePath, targetPath);
|
|
17204
17450
|
}
|
|
@@ -17300,11 +17546,11 @@ function createFileServer(options) {
|
|
|
17300
17546
|
headers: { "Content-Type": contentType }
|
|
17301
17547
|
});
|
|
17302
17548
|
});
|
|
17303
|
-
return new Promise((
|
|
17549
|
+
return new Promise((resolve2) => {
|
|
17304
17550
|
const server = serve({ fetch: app.fetch, port }, (info) => {
|
|
17305
17551
|
const actualPort = info.port;
|
|
17306
17552
|
const url = `http://localhost:${actualPort}`;
|
|
17307
|
-
|
|
17553
|
+
resolve2({
|
|
17308
17554
|
url,
|
|
17309
17555
|
port: actualPort,
|
|
17310
17556
|
close: () => server.close()
|
|
@@ -17607,7 +17853,7 @@ async function launchHdrBrowser(width, height) {
|
|
|
17607
17853
|
...sigintLaunchOptions(),
|
|
17608
17854
|
headless: false,
|
|
17609
17855
|
executablePath: chromePath,
|
|
17610
|
-
args: buildHdrChromeArgs(width, height)
|
|
17856
|
+
args: withHyperframesBrowserMarker(buildHdrChromeArgs(width, height))
|
|
17611
17857
|
});
|
|
17612
17858
|
const page = await browser.newPage();
|
|
17613
17859
|
await page.setViewport({ width, height });
|
|
@@ -17747,6 +17993,10 @@ export {
|
|
|
17747
17993
|
describeFfmpegFailure,
|
|
17748
17994
|
runFfmpeg,
|
|
17749
17995
|
declareContentAddressedUrl,
|
|
17996
|
+
declareProbeFactsUrl,
|
|
17997
|
+
PROBE_FACTS_VERSION,
|
|
17998
|
+
buildProbeFactsText,
|
|
17999
|
+
resolvePlayableVideoDuration,
|
|
17750
18000
|
probeMediaProfile,
|
|
17751
18001
|
extractMediaMetadata,
|
|
17752
18002
|
extractFinalVideoFrameTimestamp,
|
|
@@ -17785,6 +18035,8 @@ export {
|
|
|
17785
18035
|
fetchPublicHttpsText,
|
|
17786
18036
|
downloadToTemp,
|
|
17787
18037
|
isHttpUrl,
|
|
18038
|
+
renameWithRetry,
|
|
18039
|
+
renameWithRetryAsync,
|
|
17788
18040
|
directorySizeBytes,
|
|
17789
18041
|
gcExtractionCache,
|
|
17790
18042
|
VIDEO_FRAME_FORMATS,
|
|
@@ -17799,7 +18051,6 @@ export {
|
|
|
17799
18051
|
parseVideoElements,
|
|
17800
18052
|
parseImageElements,
|
|
17801
18053
|
extractVideoFramesRange,
|
|
17802
|
-
resolvePlayableVideoDuration,
|
|
17803
18054
|
isVideoPastTimelineEnd,
|
|
17804
18055
|
rebaseVideoToWindow,
|
|
17805
18056
|
resolveTimelineExtractionWindow,
|
|
@@ -17828,6 +18079,7 @@ export {
|
|
|
17828
18079
|
audioFailureDiagnostics,
|
|
17829
18080
|
MIXED_AUDIO_FILENAME,
|
|
17830
18081
|
parseMasterFxChain,
|
|
18082
|
+
videoAudioId,
|
|
17831
18083
|
parseAudioElements,
|
|
17832
18084
|
processCompositionAudio,
|
|
17833
18085
|
psnrDb,
|