mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-01 19:42:03 +00:00
fix(cli): keep render filename timestamp local (#2470)
* fix(cli): keep render filename date and time local * fix(render): share local output timestamps
This commit is contained in:
@@ -76,6 +76,7 @@ import { VERSION } from "../version.js";
|
||||
import { isDevMode } from "../utils/env.js";
|
||||
import { buildDockerRunArgs, resolveDockerPlatform } from "../utils/dockerRunArgs.js";
|
||||
import { normalizeErrorMessage } from "../utils/errorMessage.js";
|
||||
import { formatRenderOutputTimestamp } from "@hyperframes/core";
|
||||
import { runEnvironmentChecks } from "../browser/preflight.js";
|
||||
import { detectH264EncoderMode } from "../browser/ffmpeg.js";
|
||||
import { chromeLaunchRemediation } from "../browser/linuxDeps.js";
|
||||
@@ -610,16 +611,14 @@ export default defineCommand({
|
||||
// ── Resolve output path ───────────────────────────────────────────────
|
||||
const rendersDir = resolve("renders");
|
||||
const ext = FORMAT_EXT[format] ?? ".mp4";
|
||||
// fallow-ignore-next-line code-duplication
|
||||
const now = new Date();
|
||||
const datePart = now.toISOString().slice(0, 10);
|
||||
const timePart = now.toTimeString().slice(0, 8).replace(/:/g, "-");
|
||||
const timestamp = formatRenderOutputTimestamp(now);
|
||||
const batchOutputTemplate = args.output
|
||||
? args.output
|
||||
: join(rendersDir, `${project.name}_${datePart}_${timePart}_{index}${ext}`);
|
||||
: join(rendersDir, `${project.name}_${timestamp}_{index}${ext}`);
|
||||
const outputPath = args.output
|
||||
? resolve(args.output)
|
||||
: join(rendersDir, `${project.name}_${datePart}_${timePart}${ext}`);
|
||||
: join(rendersDir, `${project.name}_${timestamp}${ext}`);
|
||||
|
||||
// Ensure output directory exists
|
||||
if (!batchPath) mkdirSync(dirname(outputPath), { recursive: true });
|
||||
|
||||
@@ -231,6 +231,7 @@ export { createGSAPFrameAdapter } from "./adapters/gsap";
|
||||
// Text measurement
|
||||
export { fitTextFontSize } from "./text/index.js";
|
||||
export type { FitTextOptions, FitTextResult } from "./text/index.js";
|
||||
export { formatRenderOutputTimestamp } from "./utils/renderOutputTimestamp.js";
|
||||
|
||||
// Runtime helpers (composition-side)
|
||||
export { getVariables } from "./runtime/getVariables.js";
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { formatRenderOutputTimestamp } from "./renderOutputTimestamp.js";
|
||||
|
||||
describe("formatRenderOutputTimestamp", () => {
|
||||
it.each([
|
||||
["late local evening", "2026-07-14T22:55:06-07:00", "2026-07-14_22-55-06"],
|
||||
["single-digit calendar and clock fields", "2026-01-05T04:07:03-08:00", "2026-01-05_04-07-03"],
|
||||
])("uses one padded local calendar for %s", (_name, input, expected) => {
|
||||
const previousTimezone = process.env.TZ;
|
||||
process.env.TZ = "America/Los_Angeles";
|
||||
|
||||
try {
|
||||
expect(formatRenderOutputTimestamp(new Date(input))).toBe(expected);
|
||||
} finally {
|
||||
if (previousTimezone === undefined) delete process.env.TZ;
|
||||
else process.env.TZ = previousTimezone;
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,7 @@
|
||||
/** Format a render/job timestamp from one local calendar and clock. */
|
||||
export function formatRenderOutputTimestamp(now: Date): string {
|
||||
const pad = (value: number): string => String(value).padStart(2, "0");
|
||||
const datePart = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}`;
|
||||
const timePart = `${pad(now.getHours())}-${pad(now.getMinutes())}-${pad(now.getSeconds())}`;
|
||||
return `${datePart}_${timePart}`;
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import { existsSync, readFileSync, mkdirSync, unlinkSync, readdirSync, statSync
|
||||
import { join } from "node:path";
|
||||
import type { StudioApiAdapter, RenderJobState } from "../types.js";
|
||||
import { VALID_CANVAS_RESOLUTIONS, type CanvasResolution } from "@hyperframes/parsers";
|
||||
import { parseFps } from "@hyperframes/core";
|
||||
import { formatRenderOutputTimestamp, parseFps } from "@hyperframes/core";
|
||||
import { resolveWithinProject } from "../helpers/safePath.js";
|
||||
import { isVariablesPayload, VARIABLES_PAYLOAD_ERROR } from "../helpers/variablesPayload.js";
|
||||
|
||||
@@ -107,11 +107,8 @@ export function registerRenderRoutes(api: Hono, adapter: StudioApiAdapter): void
|
||||
variables = body.variables;
|
||||
}
|
||||
|
||||
// fallow-ignore-next-line code-duplication
|
||||
const now = new Date();
|
||||
const datePart = now.toISOString().slice(0, 10);
|
||||
const timePart = now.toTimeString().slice(0, 8).replace(/:/g, "-");
|
||||
const jobId = `${project.id}_${datePart}_${timePart}`;
|
||||
const jobId = `${project.id}_${formatRenderOutputTimestamp(now)}`;
|
||||
const rendersDir = adapter.rendersDir(project);
|
||||
if (!existsSync(rendersDir)) mkdirSync(rendersDir, { recursive: true });
|
||||
const ext = FORMAT_EXT[format] ?? ".mp4";
|
||||
|
||||
Reference in New Issue
Block a user