Files
songs2vid/lib/fonts.ts
T
Atakan Doğan Özban 848607f9e0 Add lower-corner layouts, custom blur backgrounds, and classic blur fill.
Ship composition families, optional background images for lower-corner templates, and an optional blurred cover fill for classic letterbox.
2026-08-07 00:51:37 +02:00

90 lines
2.5 KiB
TypeScript

/** Shared font catalog safe for client and server bundles (no Node APIs). */
/** Max custom font upload size (10 MB). */
export const FONT_UPLOAD_MAX_BYTES = 10 * 1024 * 1024;
/** Bundled default font for preview + FFmpeg parity (Apache 2.0, Google Arimo). */
export const SYSTEM_FONT = {
key: "system",
label: "Arimo",
file: "Arimo-Regular.ttf",
boldFile: "Arimo-Bold.ttf",
previewFamily: "S2VIDPreview-system",
} as const;
export const CURATED_FONTS = [
{
key: "inter",
label: "Inter",
cssFamily: "Inter",
googleCss: "Inter:wght@400;600",
file: "Inter-Regular.ttf",
boldFile: null as string | null,
},
{
key: "montserrat",
label: "Montserrat",
cssFamily: "Montserrat",
googleCss: "Montserrat:wght@400;600",
file: "Montserrat-Regular.ttf",
boldFile: null as string | null,
},
{
key: "roboto",
label: "Roboto",
cssFamily: "Roboto",
googleCss: "Roboto:wght@400;500",
file: "Roboto-Regular.ttf",
boldFile: null as string | null,
},
{
key: "oswald",
label: "Oswald",
cssFamily: "Oswald",
googleCss: "Oswald:wght@400;500",
file: "Oswald-Regular.ttf",
boldFile: null as string | null,
},
{
key: "playfair",
label: "Playfair Display",
cssFamily: "Playfair Display",
googleCss: "Playfair+Display:wght@400;600",
file: "PlayfairDisplay-Regular.ttf",
boldFile: null as string | null,
},
] as const;
export type CuratedFontKey = (typeof CURATED_FONTS)[number]["key"];
export type WatermarkFontKey = CuratedFontKey | "custom" | "system";
const CURATED_KEYS = new Set<string>(CURATED_FONTS.map((f) => f.key));
export function isCuratedFontKey(v: unknown): v is CuratedFontKey {
return typeof v === "string" && CURATED_KEYS.has(v);
}
export function isWatermarkFontKey(v: unknown): v is WatermarkFontKey {
return v === "custom" || v === "system" || isCuratedFontKey(v);
}
/**
* Escape an absolute font path for use inside an FFmpeg filtergraph `fontfile=` value.
* Paths are never passed through a shell; this only escapes filter special chars.
*/
export function sanitizeFontfileForFilter(absPath: string): string {
return absPath
.replace(/\\/g, "/")
.replace(/:/g, "\\:")
.replace(/'/g, "\\'")
.replace(/\[/g, "\\[")
.replace(/\]/g, "\\]");
}
export function googleFontsStylesheetUrl(keys: CuratedFontKey[]): string {
const families = CURATED_FONTS.filter((f) => keys.includes(f.key))
.map((f) => `family=${f.googleCss}`)
.join("&");
return `https://fonts.googleapis.com/css2?${families}&display=swap`;
}