Initial OSS scaffold from Songs2VID (pre-strip)
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
import path from "path";
|
||||
import type { Plan } from "@prisma/client";
|
||||
import { hasProFeatures } from "./edition";
|
||||
import {
|
||||
DEFAULT_WATERMARK,
|
||||
normalizeWatermarkSettings,
|
||||
type WatermarkSettings,
|
||||
} from "./watermark";
|
||||
|
||||
/** Free users get this many lifetime watermark-free successful videos. */
|
||||
export const FREE_UNWATERMARKED_VIDEO_LIMIT = 2;
|
||||
|
||||
export type SubscriptionStatusLabel = "free" | "pro";
|
||||
|
||||
export function subscriptionStatusFromPlan(plan: Plan): SubscriptionStatusLabel {
|
||||
return hasProFeatures(plan) ? "pro" : "free";
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the Songs2VID brand watermark must be applied for this render slot.
|
||||
* Pro / self-hosted: never forced. Free: forced after FREE_UNWATERMARKED_VIDEO_LIMIT.
|
||||
*/
|
||||
export function shouldApplyBrandWatermark(options: {
|
||||
plan: Plan;
|
||||
createdVideoCount: number;
|
||||
/** 0-based index within the current batch (accounts for multi-file jobs). */
|
||||
itemIndex?: number;
|
||||
}): boolean {
|
||||
if (hasProFeatures(options.plan)) return false;
|
||||
const slot = options.createdVideoCount + (options.itemIndex ?? 0);
|
||||
return slot >= FREE_UNWATERMARKED_VIDEO_LIMIT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply free/pro brand-watermark policy to normalized settings.
|
||||
* - Pro: strip default brand watermark (custom text/logo kept).
|
||||
* - Free under limit: force mode `none`.
|
||||
* - Free at/over limit: force default brand overlay (bottom-right).
|
||||
*/
|
||||
export function applyBrandWatermarkPolicy(
|
||||
input: Partial<WatermarkSettings> | null | undefined,
|
||||
includeWatermarkFallback: boolean,
|
||||
options: {
|
||||
plan: Plan;
|
||||
createdVideoCount: number;
|
||||
itemIndex?: number;
|
||||
},
|
||||
): WatermarkSettings {
|
||||
const base = normalizeWatermarkSettings(input, includeWatermarkFallback);
|
||||
|
||||
if (hasProFeatures(options.plan)) {
|
||||
if (base.mode === "default") {
|
||||
return { ...base, mode: "none" };
|
||||
}
|
||||
return base;
|
||||
}
|
||||
|
||||
if (shouldApplyBrandWatermark(options)) {
|
||||
return {
|
||||
...DEFAULT_WATERMARK,
|
||||
mode: "default",
|
||||
position: "bottom-right",
|
||||
offsetX: 20,
|
||||
offsetY: 20,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...base,
|
||||
mode: "none",
|
||||
};
|
||||
}
|
||||
|
||||
export function watermarkFreeRendersRemaining(createdVideoCount: number): number {
|
||||
return Math.max(0, FREE_UNWATERMARKED_VIDEO_LIMIT - createdVideoCount);
|
||||
}
|
||||
|
||||
/** Absolute path to the Songs2VID brand watermark asset (PNG). */
|
||||
export const WATERMARK_FILE_PATH = path.join(process.cwd(), "assets", "watermark.png");
|
||||
Reference in New Issue
Block a user