@hyperframes/studio-server 0.9.6 → 0.9.8
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/{chunk-CEQWOCYI.js → chunk-BAJ6HKBU.js} +45 -5
- package/dist/{chunk-PN2VGFAA.js → chunk-J4SRRKQU.js} +2 -2
- package/dist/{chunk-FUTDRYQK.js → chunk-NOIHVBIQ.js} +2 -0
- package/dist/helpers/mediaCodecMap.d.ts +2 -1
- package/dist/helpers/mediaCodecMap.js +3 -1
- package/dist/helpers/mediaProxyPreview.js +3 -3
- package/dist/helpers/proxyTranscoder.d.ts +3 -1
- package/dist/helpers/proxyTranscoder.js +4 -2
- package/dist/index.js +44 -9
- package/package.json +3 -3
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
|
+
PROXY_STILL_EXTENSION,
|
|
2
3
|
PROXY_VARIANT_CONFIG,
|
|
3
4
|
ffmpegHasHdrFilters
|
|
4
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-NOIHVBIQ.js";
|
|
5
6
|
import {
|
|
6
7
|
probeFirstFrameColour,
|
|
7
8
|
probeMediaMetadata
|
|
@@ -36,9 +37,10 @@ import { extname, join } from "path";
|
|
|
36
37
|
var DEFAULT_MAX_BYTES = 10 * 1024 * 1024 * 1024;
|
|
37
38
|
var DEFAULT_STALE_TEMP_MS = 60 * 60 * 1e3;
|
|
38
39
|
var DEFAULT_MIN_SWEEP_INTERVAL_MS = 5 * 60 * 1e3;
|
|
39
|
-
var PROXY_EXTENSIONS = new Set(
|
|
40
|
-
Object.values(PROXY_VARIANT_CONFIG).map(({ extension }) => extension)
|
|
41
|
-
|
|
40
|
+
var PROXY_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
41
|
+
...Object.values(PROXY_VARIANT_CONFIG).map(({ extension }) => extension),
|
|
42
|
+
PROXY_STILL_EXTENSION
|
|
43
|
+
]);
|
|
42
44
|
var TRANSCODER_PROXY_NAME = /^[0-9a-f]{64}\.\w+$/;
|
|
43
45
|
var TRANSCODER_TEMP_NAME = /^\.tmp-[0-9a-f-]{36}-(?:\.part-[0-9a-f]{64}-\d+|[0-9a-f]{64})\.\w+$/;
|
|
44
46
|
var TRANSCODER_PIECE_NAME = /^\.part-([0-9a-f]{64})-\d+(\.\w+)$/;
|
|
@@ -1082,6 +1084,43 @@ async function resolveProxies(projectDir, sources, onSettled = () => {
|
|
|
1082
1084
|
await Promise.all(Array.from({ length: workers }, worker));
|
|
1083
1085
|
return results;
|
|
1084
1086
|
}
|
|
1087
|
+
var stillsInFlight = /* @__PURE__ */ new Map();
|
|
1088
|
+
function resolveStill(projectDir, absoluteSourcePath, atSeconds, box) {
|
|
1089
|
+
const source = canonicalizeProxySource(projectDir, absoluteSourcePath);
|
|
1090
|
+
const at = Math.max(0, Math.round(atSeconds * 10) / 10);
|
|
1091
|
+
const key = fastCopyKey(source.sourcePath, PROXY_PARAMS_VERSION, `still@${at}`, box);
|
|
1092
|
+
const cachePath = join4(source.projectDir, CACHE_DIR_NAME, `${key}${PROXY_STILL_EXTENSION}`);
|
|
1093
|
+
if (existsSync4(cachePath)) return Promise.resolve(cachePath);
|
|
1094
|
+
const shared = stillsInFlight.get(cachePath);
|
|
1095
|
+
if (shared) return shared;
|
|
1096
|
+
const made = makeStill(source, at, box, cachePath).finally(
|
|
1097
|
+
() => stillsInFlight.delete(cachePath)
|
|
1098
|
+
);
|
|
1099
|
+
stillsInFlight.set(cachePath, made);
|
|
1100
|
+
return made;
|
|
1101
|
+
}
|
|
1102
|
+
async function makeStill(source, at, box, cachePath) {
|
|
1103
|
+
const ffmpegPath = findFfBinary("ffmpeg", { configuredMustExist: true });
|
|
1104
|
+
if (!ffmpegPath) throw new FfmpegUnavailableError();
|
|
1105
|
+
const filter = await buildVideoFilter(
|
|
1106
|
+
ffmpegPath,
|
|
1107
|
+
source.sourcePath,
|
|
1108
|
+
await probeMediaMetadata(source.sourcePath),
|
|
1109
|
+
false,
|
|
1110
|
+
box
|
|
1111
|
+
);
|
|
1112
|
+
mkdirWithinProject(source.projectDir, dirname3(cachePath));
|
|
1113
|
+
const tempPath = join4(dirname3(cachePath), `.tmp-${randomUUID()}-${basename3(cachePath)}`);
|
|
1114
|
+
try {
|
|
1115
|
+
const args = ["-y", "-ss", String(at), "-i", source.sourcePath, "-map", "0:V:0"];
|
|
1116
|
+
args.push("-frames:v", "1", "-vf", filter, "-pix_fmt", "yuvj420p", "-q:v", "3", tempPath);
|
|
1117
|
+
await spawnFfmpeg(ffmpegPath, args, TRANSCODE_STALL_MS, new AbortController().signal);
|
|
1118
|
+
renameSync(tempPath, cachePath);
|
|
1119
|
+
} finally {
|
|
1120
|
+
rmSync2(tempPath, { force: true });
|
|
1121
|
+
}
|
|
1122
|
+
return cachePath;
|
|
1123
|
+
}
|
|
1085
1124
|
function joinJob(promise, job, signal) {
|
|
1086
1125
|
job.callers++;
|
|
1087
1126
|
if (!signal) return promise;
|
|
@@ -1117,5 +1156,6 @@ export {
|
|
|
1117
1156
|
retryProxyCopy,
|
|
1118
1157
|
proxyActivityMark,
|
|
1119
1158
|
resolveProxy,
|
|
1120
|
-
resolveProxies
|
|
1159
|
+
resolveProxies,
|
|
1160
|
+
resolveStill
|
|
1121
1161
|
};
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
PROXY_PARAMS_VERSION,
|
|
3
3
|
resolveProxy
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-BAJ6HKBU.js";
|
|
5
5
|
import {
|
|
6
6
|
createMediaCodecProbeCache,
|
|
7
7
|
proxyVariantFor,
|
|
8
8
|
recordProxyPrewarm,
|
|
9
9
|
scanProjectMedia,
|
|
10
10
|
shouldPrewarmProxy
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-NOIHVBIQ.js";
|
|
12
12
|
|
|
13
13
|
// src/helpers/mediaProxyPreview.ts
|
|
14
14
|
import { resolve } from "path";
|
|
@@ -98,6 +98,7 @@ var PROXY_VARIANT_CONFIG = {
|
|
|
98
98
|
h264: { extension: ".mp4", contentType: "video/mp4" },
|
|
99
99
|
vp8: { extension: ".webm", contentType: "video/webm" }
|
|
100
100
|
};
|
|
101
|
+
var PROXY_STILL_EXTENSION = ".jpg";
|
|
101
102
|
function isProxyVariant(value) {
|
|
102
103
|
return Object.hasOwn(PROXY_VARIANT_CONFIG, value);
|
|
103
104
|
}
|
|
@@ -252,6 +253,7 @@ export {
|
|
|
252
253
|
recordProxyPrewarm,
|
|
253
254
|
recordProxyRequest,
|
|
254
255
|
PROXY_VARIANT_CONFIG,
|
|
256
|
+
PROXY_STILL_EXTENSION,
|
|
255
257
|
isProxyVariant,
|
|
256
258
|
isProxyVariantRequest,
|
|
257
259
|
proxyVariantFor,
|
|
@@ -89,6 +89,7 @@ declare const PROXY_VARIANT_CONFIG: Record<ProxyVariant, {
|
|
|
89
89
|
extension: ".mp4" | ".webm";
|
|
90
90
|
contentType: "video/mp4" | "video/webm";
|
|
91
91
|
}>;
|
|
92
|
+
declare const PROXY_STILL_EXTENSION = ".jpg";
|
|
92
93
|
declare function isProxyVariant(value: string): value is ProxyVariant;
|
|
93
94
|
declare function isProxyVariantRequest(value: string): value is ProxyVariantRequest;
|
|
94
95
|
declare function proxyVariantFor(facts: AssetCodecFacts): ProxyVariant;
|
|
@@ -144,4 +145,4 @@ declare function scanProjectMedia(projectDir: string, htmlSources: HtmlSourceLik
|
|
|
144
145
|
/** The injection map alone: root-relative URL pathname -> codec facts of the hostile videos. */
|
|
145
146
|
declare function scanProjectMediaCodecMap(projectDir: string, htmlSources: HtmlSourceLike[], options?: ScanProjectMediaCodecMapOptions): Promise<MediaCodecMap>;
|
|
146
147
|
|
|
147
|
-
export { type AssetCodecFacts, BROWSER_HOSTILE_CODECS, type BrowserHostileCodec, type HtmlSourceLike, type MediaCodecMap, type MediaCodecProbeCache, type MediaProxyEligibility, type MediaProxyIneligibilityReason, PROXY_VARIANT_CONFIG, type ProjectMediaScan, type ProxyVariant, type ProxyVariantRequest, type ScanProjectMediaCodecMapOptions, createMediaCodecProbeCache, decideMediaProxyEligibility, isProxyVariant, isProxyVariantRequest, mediaProxyDemand, probeAssetCodec, proxyVariantFor, recordProxyPrewarm, recordProxyRequest, resolveProxyVariantRequest, scanProjectMedia, scanProjectMediaCodecMap, shouldPrewarmProxy };
|
|
148
|
+
export { type AssetCodecFacts, BROWSER_HOSTILE_CODECS, type BrowserHostileCodec, type HtmlSourceLike, type MediaCodecMap, type MediaCodecProbeCache, type MediaProxyEligibility, type MediaProxyIneligibilityReason, PROXY_STILL_EXTENSION, PROXY_VARIANT_CONFIG, type ProjectMediaScan, type ProxyVariant, type ProxyVariantRequest, type ScanProjectMediaCodecMapOptions, createMediaCodecProbeCache, decideMediaProxyEligibility, isProxyVariant, isProxyVariantRequest, mediaProxyDemand, probeAssetCodec, proxyVariantFor, recordProxyPrewarm, recordProxyRequest, resolveProxyVariantRequest, scanProjectMedia, scanProjectMediaCodecMap, shouldPrewarmProxy };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
BROWSER_HOSTILE_CODECS,
|
|
3
|
+
PROXY_STILL_EXTENSION,
|
|
3
4
|
PROXY_VARIANT_CONFIG,
|
|
4
5
|
createMediaCodecProbeCache,
|
|
5
6
|
decideMediaProxyEligibility,
|
|
@@ -14,13 +15,14 @@ import {
|
|
|
14
15
|
scanProjectMedia,
|
|
15
16
|
scanProjectMediaCodecMap,
|
|
16
17
|
shouldPrewarmProxy
|
|
17
|
-
} from "../chunk-
|
|
18
|
+
} from "../chunk-NOIHVBIQ.js";
|
|
18
19
|
import "../chunk-X73QTST2.js";
|
|
19
20
|
import "../chunk-QF7MFJJU.js";
|
|
20
21
|
import "../chunk-SVQFE44C.js";
|
|
21
22
|
import "../chunk-L3HJVTQE.js";
|
|
22
23
|
export {
|
|
23
24
|
BROWSER_HOSTILE_CODECS,
|
|
25
|
+
PROXY_STILL_EXTENSION,
|
|
24
26
|
PROXY_VARIANT_CONFIG,
|
|
25
27
|
createMediaCodecProbeCache,
|
|
26
28
|
decideMediaProxyEligibility,
|
|
@@ -4,9 +4,9 @@ import {
|
|
|
4
4
|
isAutoProxyEnabled,
|
|
5
5
|
proxyEtagSalt,
|
|
6
6
|
resolvePreviewMediaCodecProbeCache
|
|
7
|
-
} from "../chunk-
|
|
8
|
-
import "../chunk-
|
|
9
|
-
import "../chunk-
|
|
7
|
+
} from "../chunk-J4SRRKQU.js";
|
|
8
|
+
import "../chunk-BAJ6HKBU.js";
|
|
9
|
+
import "../chunk-NOIHVBIQ.js";
|
|
10
10
|
import "../chunk-X73QTST2.js";
|
|
11
11
|
import "../chunk-QF7MFJJU.js";
|
|
12
12
|
import "../chunk-SVQFE44C.js";
|
|
@@ -87,6 +87,8 @@ declare function resolveProxies(projectDir: string, sources: ReadonlyArray<{
|
|
|
87
87
|
variant: ProxyVariant;
|
|
88
88
|
box?: PreviewProxyBox;
|
|
89
89
|
}>, onSettled?: (index: number) => void, onProgress?: (index: number, progress: ProxyProgress) => void, signal?: AbortSignal): Promise<PromiseSettledResult<string>[]>;
|
|
90
|
+
/** One JPEG of the source at a time (to a tenth of a second), sized like the copy's box. */
|
|
91
|
+
declare function resolveStill(projectDir: string, absoluteSourcePath: string, atSeconds: number, box?: PreviewProxyBox): Promise<string>;
|
|
90
92
|
interface ResolveProxyOptions {
|
|
91
93
|
priority?: boolean;
|
|
92
94
|
background?: boolean;
|
|
@@ -95,4 +97,4 @@ interface ResolveProxyOptions {
|
|
|
95
97
|
onProgress?: (progress: ProxyProgress) => void;
|
|
96
98
|
}
|
|
97
99
|
|
|
98
|
-
export { CACHE_DIR_NAME, DEFAULT_PROXY_WAIT_TIMEOUT_MS, FfmpegMissingFilterError, FfmpegUnavailableError, PROXY_CHUNK_SECONDS, PROXY_PARAMS_VERSION, PROXY_PENDING_RETRY_AFTER_SECONDS, ProxyCapacityError, type ProxyProgress, ProxySourceOutsideProjectError, ProxyTranscodeError, ProxyWaitTimeoutError, type ResolveProxyOptions, type SourceFolderKind, TRANSCODE_STALL_MS, clearFailedTranscodesForTest, getProxyCachePath, proxyActivityMark, proxyCopyProgress, resolveProxies, resolveProxy, retryProxyCopy, sourceFolderKind, waitForProxy };
|
|
100
|
+
export { CACHE_DIR_NAME, DEFAULT_PROXY_WAIT_TIMEOUT_MS, FfmpegMissingFilterError, FfmpegUnavailableError, PROXY_CHUNK_SECONDS, PROXY_PARAMS_VERSION, PROXY_PENDING_RETRY_AFTER_SECONDS, ProxyCapacityError, type ProxyProgress, ProxySourceOutsideProjectError, ProxyTranscodeError, ProxyWaitTimeoutError, type ResolveProxyOptions, type SourceFolderKind, TRANSCODE_STALL_MS, clearFailedTranscodesForTest, getProxyCachePath, proxyActivityMark, proxyCopyProgress, resolveProxies, resolveProxy, resolveStill, retryProxyCopy, sourceFolderKind, waitForProxy };
|
|
@@ -17,11 +17,12 @@ import {
|
|
|
17
17
|
proxyCopyProgress,
|
|
18
18
|
resolveProxies,
|
|
19
19
|
resolveProxy,
|
|
20
|
+
resolveStill,
|
|
20
21
|
retryProxyCopy,
|
|
21
22
|
sourceFolderKind,
|
|
22
23
|
waitForProxy
|
|
23
|
-
} from "../chunk-
|
|
24
|
-
import "../chunk-
|
|
24
|
+
} from "../chunk-BAJ6HKBU.js";
|
|
25
|
+
import "../chunk-NOIHVBIQ.js";
|
|
25
26
|
import "../chunk-X73QTST2.js";
|
|
26
27
|
import "../chunk-QF7MFJJU.js";
|
|
27
28
|
import "../chunk-SVQFE44C.js";
|
|
@@ -45,6 +46,7 @@ export {
|
|
|
45
46
|
proxyCopyProgress,
|
|
46
47
|
resolveProxies,
|
|
47
48
|
resolveProxy,
|
|
49
|
+
resolveStill,
|
|
48
50
|
retryProxyCopy,
|
|
49
51
|
sourceFolderKind,
|
|
50
52
|
waitForProxy
|
package/dist/index.js
CHANGED
|
@@ -91,7 +91,7 @@ import {
|
|
|
91
91
|
isAutoProxyEnabled,
|
|
92
92
|
proxyEtagSalt,
|
|
93
93
|
resolvePreviewMediaCodecProbeCache
|
|
94
|
-
} from "./chunk-
|
|
94
|
+
} from "./chunk-J4SRRKQU.js";
|
|
95
95
|
import {
|
|
96
96
|
CACHE_DIR_NAME,
|
|
97
97
|
PROXY_PENDING_RETRY_AFTER_SECONDS,
|
|
@@ -102,9 +102,10 @@ import {
|
|
|
102
102
|
proxyActivityMark,
|
|
103
103
|
proxyCopyProgress,
|
|
104
104
|
resolveProxy,
|
|
105
|
+
resolveStill,
|
|
105
106
|
retryProxyCopy,
|
|
106
107
|
waitForProxy
|
|
107
|
-
} from "./chunk-
|
|
108
|
+
} from "./chunk-BAJ6HKBU.js";
|
|
108
109
|
import {
|
|
109
110
|
PROXY_VARIANT_CONFIG,
|
|
110
111
|
decideMediaProxyEligibility,
|
|
@@ -112,7 +113,7 @@ import {
|
|
|
112
113
|
probeAssetCodec,
|
|
113
114
|
recordProxyRequest,
|
|
114
115
|
resolveProxyVariantRequest
|
|
115
|
-
} from "./chunk-
|
|
116
|
+
} from "./chunk-NOIHVBIQ.js";
|
|
116
117
|
import {
|
|
117
118
|
probeAudioTrack,
|
|
118
119
|
probeMediaMetadata
|
|
@@ -3932,6 +3933,7 @@ import {
|
|
|
3932
3933
|
import {
|
|
3933
3934
|
STUDIO_PREVIEW_CAPTURE_MODE,
|
|
3934
3935
|
STUDIO_PREVIEW_MARK_META,
|
|
3936
|
+
STUDIO_PREVIEW_ERROR_KINDS,
|
|
3935
3937
|
STUDIO_PREVIEW_ERRORS
|
|
3936
3938
|
} from "@hyperframes/core/studio-preview-mark";
|
|
3937
3939
|
import {
|
|
@@ -3940,6 +3942,7 @@ import {
|
|
|
3940
3942
|
PREVIEW_PROXY_PRIORITY_HEADER,
|
|
3941
3943
|
PREVIEW_PROXY_PROGRESS_HEADER,
|
|
3942
3944
|
PREVIEW_PROXY_RETRY_PARAM,
|
|
3945
|
+
PREVIEW_PROXY_STILL_PARAM,
|
|
3943
3946
|
parsePreviewProxyBox
|
|
3944
3947
|
} from "@hyperframes/core";
|
|
3945
3948
|
import {
|
|
@@ -4278,7 +4281,7 @@ var GSAP_FALLBACK_ATTR = "data-hf-gsap-fallback";
|
|
|
4278
4281
|
function gsapCdnFallbackScript(baseUrl) {
|
|
4279
4282
|
return `<script ${GSAP_FALLBACK_ATTR}>
|
|
4280
4283
|
(function(){
|
|
4281
|
-
var cdnBase=${
|
|
4284
|
+
var cdnBase=${scriptJson(gsapCdnDist2(void 0, baseUrl))};
|
|
4282
4285
|
var loaded={};
|
|
4283
4286
|
function loadFallback(file){
|
|
4284
4287
|
if(loaded[file])return loaded[file];
|
|
@@ -4328,15 +4331,21 @@ function previewVariablesFromRequest(rawVariables) {
|
|
|
4328
4331
|
return { raw: rawVariables, values: parse2.values };
|
|
4329
4332
|
}
|
|
4330
4333
|
var PREVIEW_CAPTURE_PARAM = "hf-capture";
|
|
4331
|
-
|
|
4332
|
-
|
|
4334
|
+
function scriptJson(value) {
|
|
4335
|
+
return JSON.stringify(value).replace(/</g, "\\u003c").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
4336
|
+
}
|
|
4337
|
+
var earlyErrorsScript = (runtimeUrl) => `<script>(function(){var seen=window.${STUDIO_PREVIEW_ERRORS}=[],kinds=window.${STUDIO_PREVIEW_ERROR_KINDS}=[],known={SyntaxError:1,TypeError:1,ReferenceError:1,RangeError:1},runtime=${scriptJson(new URL(runtimeUrl, "http://x").pathname)};
|
|
4338
|
+
addEventListener("error",function(e){seen.push(e.message||String(e));
|
|
4339
|
+
var name=e.error&&e.error.constructor&&e.error.constructor.name,path="";
|
|
4340
|
+
try{var url=e.filename&&new URL(e.filename,window.location.href);if(url&&url.origin===window.location.origin)path=url.pathname}catch(_){}
|
|
4341
|
+
kinds.push({name:known[name]===1?name:"other",origin:!path?"unknown":path===runtime?"runtime":path.indexOf("/api/projects/")===0?"project":"studio"})});})();</script>`;
|
|
4333
4342
|
function injectStudioPreviewAugmentations(html, adapter, projectDir, activeCompositionPath, options) {
|
|
4334
4343
|
const marked = options.capture ? injectTagsAtHeadStart2(
|
|
4335
4344
|
html,
|
|
4336
4345
|
`<meta name="${STUDIO_PREVIEW_MARK_META}" content="${STUDIO_PREVIEW_CAPTURE_MODE}">`
|
|
4337
4346
|
) : injectTagsAtHeadStart2(
|
|
4338
4347
|
lazyPreviewImages(html),
|
|
4339
|
-
`<meta name="${STUDIO_PREVIEW_MARK_META}">${
|
|
4348
|
+
`<meta name="${STUDIO_PREVIEW_MARK_META}">${earlyErrorsScript(adapter.runtimeUrl)}`
|
|
4340
4349
|
);
|
|
4341
4350
|
const withFallback = injectGsapCdnFallback(
|
|
4342
4351
|
injectProjectSignature(
|
|
@@ -4624,6 +4633,22 @@ ${etag}`;
|
|
|
4624
4633
|
return c.text("media proxy variant does not match asset", 422);
|
|
4625
4634
|
}
|
|
4626
4635
|
}
|
|
4636
|
+
const stillParam = c.req.query(PREVIEW_PROXY_STILL_PARAM);
|
|
4637
|
+
if (stillParam !== void 0) {
|
|
4638
|
+
const at = Number(stillParam);
|
|
4639
|
+
if (stillParam === "" || !Number.isFinite(at) || at < 0 || !proxyVariant) {
|
|
4640
|
+
return c.text("not found", 404);
|
|
4641
|
+
}
|
|
4642
|
+
try {
|
|
4643
|
+
const still = await resolveStill(project.dir, file, at, proxyBox);
|
|
4644
|
+
return new Response(readFileSync6(still), {
|
|
4645
|
+
headers: { "Content-Type": "image/jpeg", "Cache-Control": "private, max-age=3600" }
|
|
4646
|
+
});
|
|
4647
|
+
} catch (err) {
|
|
4648
|
+
if (isProjectRootMissing(err)) throw err;
|
|
4649
|
+
return c.text("media still failed", 502);
|
|
4650
|
+
}
|
|
4651
|
+
}
|
|
4627
4652
|
const tag = settledFileTag(stat2);
|
|
4628
4653
|
const etag = tag && `"${tag}${proxyEtagSalt(proxyVariant, proxyBox)}"`;
|
|
4629
4654
|
const cacheHeaders = isText ? { "Cache-Control": "no-store" } : { "Cache-Control": "private, no-cache", ...etag && { ETag: etag } };
|
|
@@ -4806,6 +4831,13 @@ function contentDispositionHeader(disposition, filename) {
|
|
|
4806
4831
|
}
|
|
4807
4832
|
function registerRenderRoutes(api, adapter) {
|
|
4808
4833
|
const renderJobs = /* @__PURE__ */ new Map();
|
|
4834
|
+
const nextFreeRenderJobId = (baseId, ext, rendersDir) => {
|
|
4835
|
+
let jobId = baseId;
|
|
4836
|
+
for (let n = 2; renderJobs.has(jobId) || existsSync6(join10(rendersDir, `${jobId}${ext}`)); n++) {
|
|
4837
|
+
jobId = `${baseId}-${n}`;
|
|
4838
|
+
}
|
|
4839
|
+
return jobId;
|
|
4840
|
+
};
|
|
4809
4841
|
const TTL_MS = 3e5;
|
|
4810
4842
|
const CLEANUP_INTERVAL_MS = 6e4;
|
|
4811
4843
|
let cleanupTimer = null;
|
|
@@ -4869,11 +4901,14 @@ function registerRenderRoutes(api, adapter) {
|
|
|
4869
4901
|
return c.json({ error: "pageMotionBlur must be off when supplied" }, 400);
|
|
4870
4902
|
}
|
|
4871
4903
|
const pageMotionBlur = requestedPageMotionBlur === void 0 && body.previewMotionBlur === false ? "off" : requestedPageMotionBlur;
|
|
4872
|
-
const now = /* @__PURE__ */ new Date();
|
|
4873
|
-
const jobId = `${project.id}_${formatRenderOutputTimestamp(now)}`;
|
|
4874
4904
|
const rendersDir = adapter.rendersDir(project);
|
|
4875
4905
|
mkdirWithinProject(project.dir, rendersDir);
|
|
4876
4906
|
const ext = FORMAT_EXT[format] ?? ".mp4";
|
|
4907
|
+
const jobId = nextFreeRenderJobId(
|
|
4908
|
+
`${project.id}_${formatRenderOutputTimestamp(/* @__PURE__ */ new Date())}`,
|
|
4909
|
+
ext,
|
|
4910
|
+
rendersDir
|
|
4911
|
+
);
|
|
4877
4912
|
const outputPath = join10(rendersDir, `${jobId}${ext}`);
|
|
4878
4913
|
const jobState = adapter.startRender({
|
|
4879
4914
|
project,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyperframes/studio-server",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.8",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/heygen-com/hyperframes",
|
|
@@ -88,8 +88,8 @@
|
|
|
88
88
|
"linkedom": "^0.18.12",
|
|
89
89
|
"postcss": "^8.5.8",
|
|
90
90
|
"postcss-selector-parser": "^7.1.2",
|
|
91
|
-
"@hyperframes/
|
|
92
|
-
"@hyperframes/
|
|
91
|
+
"@hyperframes/core": "0.9.8",
|
|
92
|
+
"@hyperframes/parsers": "0.9.8"
|
|
93
93
|
},
|
|
94
94
|
"devDependencies": {
|
|
95
95
|
"@types/node": "^25.0.10",
|