@adforge-adgeniq/render 0.1.0
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-IU6GCMDG.mjs +23 -0
- package/dist/chunk-NQY73BAM.mjs +68 -0
- package/dist/chunk-PNJ7IKUC.mjs +25 -0
- package/dist/ffmpeg/captions.d.mts +22 -0
- package/dist/ffmpeg/captions.d.ts +22 -0
- package/dist/ffmpeg/captions.js +96 -0
- package/dist/ffmpeg/captions.mjs +9 -0
- package/dist/ffmpeg/dimensions.d.mts +8 -0
- package/dist/ffmpeg/dimensions.d.ts +8 -0
- package/dist/ffmpeg/dimensions.js +50 -0
- package/dist/ffmpeg/dimensions.mjs +8 -0
- package/dist/index.d.mts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +489 -0
- package/dist/index.mjs +360 -0
- package/dist/remotion/index.d.mts +40 -0
- package/dist/remotion/index.d.ts +40 -0
- package/dist/remotion/index.js +373 -0
- package/dist/remotion/index.mjs +348 -0
- package/dist/storyboard/utils.d.mts +16 -0
- package/dist/storyboard/utils.d.ts +16 -0
- package/dist/storyboard/utils.js +49 -0
- package/dist/storyboard/utils.mjs +10 -0
- package/dist/storyboard/validate.d.mts +12 -0
- package/dist/storyboard/validate.d.ts +12 -0
- package/dist/storyboard/validate.js +35 -0
- package/dist/storyboard/validate.mjs +9 -0
- package/dist/types.d.mts +37 -0
- package/dist/types.d.ts +37 -0
- package/dist/types.js +18 -0
- package/dist/types.mjs +0 -0
- package/package.json +77 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// src/storyboard/utils.ts
|
|
2
|
+
function storyboardDurationS(sb) {
|
|
3
|
+
return sb.scenes.reduce((sum, s) => sum + s.duration_s, 0);
|
|
4
|
+
}
|
|
5
|
+
function estimateRenderCredits(sb, aspects) {
|
|
6
|
+
const durationS = storyboardDurationS(sb);
|
|
7
|
+
return Math.ceil(durationS / 30) * 5 * aspects;
|
|
8
|
+
}
|
|
9
|
+
function assignStartTimes(sb) {
|
|
10
|
+
let cursor = 0;
|
|
11
|
+
const scenes = sb.scenes.map((s) => {
|
|
12
|
+
const scene = { ...s, start_s: cursor };
|
|
13
|
+
cursor += s.duration_s;
|
|
14
|
+
return scene;
|
|
15
|
+
});
|
|
16
|
+
return { ...sb, scenes };
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export {
|
|
20
|
+
storyboardDurationS,
|
|
21
|
+
estimateRenderCredits,
|
|
22
|
+
assignStartTimes
|
|
23
|
+
};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import {
|
|
2
|
+
fontScale
|
|
3
|
+
} from "./chunk-PNJ7IKUC.mjs";
|
|
4
|
+
|
|
5
|
+
// src/ffmpeg/captions.ts
|
|
6
|
+
function toAssTime(s) {
|
|
7
|
+
const h = Math.floor(s / 3600);
|
|
8
|
+
const m = Math.floor(s % 3600 / 60);
|
|
9
|
+
const sec = (s % 60).toFixed(2);
|
|
10
|
+
return `${h}:${String(m).padStart(2, "0")}:${String(sec).padStart(5, "0")}`;
|
|
11
|
+
}
|
|
12
|
+
function escapeAss(text) {
|
|
13
|
+
return text.replace(/\\/g, "\\\\").replace(/{/g, "\\{").replace(/}/g, "\\}");
|
|
14
|
+
}
|
|
15
|
+
function buildAssSubtitles(scenes, style, dims) {
|
|
16
|
+
if (style === "NONE") return "";
|
|
17
|
+
const scale = fontScale(dims);
|
|
18
|
+
const fontSize = Math.round(48 * scale);
|
|
19
|
+
const marginV = dims.safeAreaBottom + Math.round(40 * scale);
|
|
20
|
+
const marginH = dims.safeAreaSide + Math.round(20 * scale);
|
|
21
|
+
const header = `[Script Info]
|
|
22
|
+
ScriptType: v4.00+
|
|
23
|
+
PlayResX: ${dims.width}
|
|
24
|
+
PlayResY: ${dims.height}
|
|
25
|
+
ScaledBorderAndShadow: yes
|
|
26
|
+
|
|
27
|
+
[V4+ Styles]
|
|
28
|
+
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
|
|
29
|
+
Style: Default,Arial,${fontSize},&H00FFFFFF,&H000000FF,&H00000000,&H80000000,-1,0,0,0,100,100,0,0,1,2,0,2,${marginH},${marginH},${marginV},1
|
|
30
|
+
|
|
31
|
+
[Events]
|
|
32
|
+
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text`;
|
|
33
|
+
const events = [];
|
|
34
|
+
for (const scene of scenes) {
|
|
35
|
+
if (!scene.captions?.length) continue;
|
|
36
|
+
const offset = scene.start_s;
|
|
37
|
+
if (style === "KARAOKE") {
|
|
38
|
+
for (const cap of scene.captions) {
|
|
39
|
+
const text = escapeAss(cap.text);
|
|
40
|
+
events.push(
|
|
41
|
+
`Dialogue: 0,${toAssTime(offset + cap.start_s)},${toAssTime(offset + cap.end_s)},Default,,0,0,0,,{\\an8\\fad(80,80)}${text}`
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
} else {
|
|
45
|
+
const merged = scene.captions.map((c) => c.text).join(" ");
|
|
46
|
+
const startS = offset + (scene.captions[0]?.start_s ?? 0);
|
|
47
|
+
const endS = offset + (scene.captions[scene.captions.length - 1]?.end_s ?? scene.duration_s);
|
|
48
|
+
events.push(
|
|
49
|
+
`Dialogue: 0,${toAssTime(startS)},${toAssTime(endS)},Default,,0,0,0,,{\\an2\\fad(100,100)}${escapeAss(merged)}`
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return [header, ...events].join("\n");
|
|
54
|
+
}
|
|
55
|
+
function flattenCaptions(scenes) {
|
|
56
|
+
const out = [];
|
|
57
|
+
for (const s of scenes) {
|
|
58
|
+
for (const c of s.captions) {
|
|
59
|
+
out.push({ text: c.text, startS: c.start_s, endS: c.end_s });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return out;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export {
|
|
66
|
+
buildAssSubtitles,
|
|
67
|
+
flattenCaptions
|
|
68
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// src/ffmpeg/dimensions.ts
|
|
2
|
+
var DIMS = {
|
|
3
|
+
"9:16": { "720p": { w: 720, h: 1280 }, "1080p": { w: 1080, h: 1920 } },
|
|
4
|
+
"16:9": { "720p": { w: 1280, h: 720 }, "1080p": { w: 1920, h: 1080 } },
|
|
5
|
+
"1:1": { "720p": { w: 720, h: 720 }, "1080p": { w: 1080, h: 1080 } }
|
|
6
|
+
};
|
|
7
|
+
var SAFE_AREA_PCT = { top: 0.08, bottom: 0.12, side: 0.05 };
|
|
8
|
+
function getDimensions(aspect, resolution) {
|
|
9
|
+
const { w, h } = DIMS[aspect][resolution];
|
|
10
|
+
return {
|
|
11
|
+
width: w,
|
|
12
|
+
height: h,
|
|
13
|
+
safeAreaTop: Math.round(h * SAFE_AREA_PCT.top),
|
|
14
|
+
safeAreaBottom: Math.round(h * SAFE_AREA_PCT.bottom),
|
|
15
|
+
safeAreaSide: Math.round(w * SAFE_AREA_PCT.side)
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function fontScale(dims) {
|
|
19
|
+
return dims.width / 1080;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export {
|
|
23
|
+
getDimensions,
|
|
24
|
+
fontScale
|
|
25
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { StoryboardScene } from '@adforge-adgeniq/shared';
|
|
2
|
+
import { CaptionStyle, AspectDimensions } from '../types.mjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* ASS subtitle generation for FFmpeg subtitle filter.
|
|
6
|
+
* Supports karaoke (word-by-word) and block subtitle styles.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
interface CaptionEntry {
|
|
10
|
+
text: string;
|
|
11
|
+
startS: number;
|
|
12
|
+
endS: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Build an ASS subtitle string for the entire storyboard.
|
|
16
|
+
* Each scene's captions are rendered with proper timing offsets.
|
|
17
|
+
*/
|
|
18
|
+
declare function buildAssSubtitles(scenes: StoryboardScene[], style: CaptionStyle, dims: AspectDimensions): string;
|
|
19
|
+
/** Collect all caption entries from scenes as flat list (for testing) */
|
|
20
|
+
declare function flattenCaptions(scenes: StoryboardScene[]): CaptionEntry[];
|
|
21
|
+
|
|
22
|
+
export { buildAssSubtitles, flattenCaptions };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { StoryboardScene } from '@adforge-adgeniq/shared';
|
|
2
|
+
import { CaptionStyle, AspectDimensions } from '../types.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* ASS subtitle generation for FFmpeg subtitle filter.
|
|
6
|
+
* Supports karaoke (word-by-word) and block subtitle styles.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
interface CaptionEntry {
|
|
10
|
+
text: string;
|
|
11
|
+
startS: number;
|
|
12
|
+
endS: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Build an ASS subtitle string for the entire storyboard.
|
|
16
|
+
* Each scene's captions are rendered with proper timing offsets.
|
|
17
|
+
*/
|
|
18
|
+
declare function buildAssSubtitles(scenes: StoryboardScene[], style: CaptionStyle, dims: AspectDimensions): string;
|
|
19
|
+
/** Collect all caption entries from scenes as flat list (for testing) */
|
|
20
|
+
declare function flattenCaptions(scenes: StoryboardScene[]): CaptionEntry[];
|
|
21
|
+
|
|
22
|
+
export { buildAssSubtitles, flattenCaptions };
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/ffmpeg/captions.ts
|
|
21
|
+
var captions_exports = {};
|
|
22
|
+
__export(captions_exports, {
|
|
23
|
+
buildAssSubtitles: () => buildAssSubtitles,
|
|
24
|
+
flattenCaptions: () => flattenCaptions
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(captions_exports);
|
|
27
|
+
|
|
28
|
+
// src/ffmpeg/dimensions.ts
|
|
29
|
+
function fontScale(dims) {
|
|
30
|
+
return dims.width / 1080;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// src/ffmpeg/captions.ts
|
|
34
|
+
function toAssTime(s) {
|
|
35
|
+
const h = Math.floor(s / 3600);
|
|
36
|
+
const m = Math.floor(s % 3600 / 60);
|
|
37
|
+
const sec = (s % 60).toFixed(2);
|
|
38
|
+
return `${h}:${String(m).padStart(2, "0")}:${String(sec).padStart(5, "0")}`;
|
|
39
|
+
}
|
|
40
|
+
function escapeAss(text) {
|
|
41
|
+
return text.replace(/\\/g, "\\\\").replace(/{/g, "\\{").replace(/}/g, "\\}");
|
|
42
|
+
}
|
|
43
|
+
function buildAssSubtitles(scenes, style, dims) {
|
|
44
|
+
if (style === "NONE") return "";
|
|
45
|
+
const scale = fontScale(dims);
|
|
46
|
+
const fontSize = Math.round(48 * scale);
|
|
47
|
+
const marginV = dims.safeAreaBottom + Math.round(40 * scale);
|
|
48
|
+
const marginH = dims.safeAreaSide + Math.round(20 * scale);
|
|
49
|
+
const header = `[Script Info]
|
|
50
|
+
ScriptType: v4.00+
|
|
51
|
+
PlayResX: ${dims.width}
|
|
52
|
+
PlayResY: ${dims.height}
|
|
53
|
+
ScaledBorderAndShadow: yes
|
|
54
|
+
|
|
55
|
+
[V4+ Styles]
|
|
56
|
+
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
|
|
57
|
+
Style: Default,Arial,${fontSize},&H00FFFFFF,&H000000FF,&H00000000,&H80000000,-1,0,0,0,100,100,0,0,1,2,0,2,${marginH},${marginH},${marginV},1
|
|
58
|
+
|
|
59
|
+
[Events]
|
|
60
|
+
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text`;
|
|
61
|
+
const events = [];
|
|
62
|
+
for (const scene of scenes) {
|
|
63
|
+
if (!scene.captions?.length) continue;
|
|
64
|
+
const offset = scene.start_s;
|
|
65
|
+
if (style === "KARAOKE") {
|
|
66
|
+
for (const cap of scene.captions) {
|
|
67
|
+
const text = escapeAss(cap.text);
|
|
68
|
+
events.push(
|
|
69
|
+
`Dialogue: 0,${toAssTime(offset + cap.start_s)},${toAssTime(offset + cap.end_s)},Default,,0,0,0,,{\\an8\\fad(80,80)}${text}`
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
} else {
|
|
73
|
+
const merged = scene.captions.map((c) => c.text).join(" ");
|
|
74
|
+
const startS = offset + (scene.captions[0]?.start_s ?? 0);
|
|
75
|
+
const endS = offset + (scene.captions[scene.captions.length - 1]?.end_s ?? scene.duration_s);
|
|
76
|
+
events.push(
|
|
77
|
+
`Dialogue: 0,${toAssTime(startS)},${toAssTime(endS)},Default,,0,0,0,,{\\an2\\fad(100,100)}${escapeAss(merged)}`
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return [header, ...events].join("\n");
|
|
82
|
+
}
|
|
83
|
+
function flattenCaptions(scenes) {
|
|
84
|
+
const out = [];
|
|
85
|
+
for (const s of scenes) {
|
|
86
|
+
for (const c of s.captions) {
|
|
87
|
+
out.push({ text: c.text, startS: c.start_s, endS: c.end_s });
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return out;
|
|
91
|
+
}
|
|
92
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
93
|
+
0 && (module.exports = {
|
|
94
|
+
buildAssSubtitles,
|
|
95
|
+
flattenCaptions
|
|
96
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { AspectDimensions, Aspect, Resolution } from '../types.mjs';
|
|
2
|
+
import '@adforge-adgeniq/shared';
|
|
3
|
+
|
|
4
|
+
declare function getDimensions(aspect: Aspect, resolution: Resolution): AspectDimensions;
|
|
5
|
+
/** Font scale relative to 1080p base */
|
|
6
|
+
declare function fontScale(dims: AspectDimensions): number;
|
|
7
|
+
|
|
8
|
+
export { fontScale, getDimensions };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { AspectDimensions, Aspect, Resolution } from '../types.js';
|
|
2
|
+
import '@adforge-adgeniq/shared';
|
|
3
|
+
|
|
4
|
+
declare function getDimensions(aspect: Aspect, resolution: Resolution): AspectDimensions;
|
|
5
|
+
/** Font scale relative to 1080p base */
|
|
6
|
+
declare function fontScale(dims: AspectDimensions): number;
|
|
7
|
+
|
|
8
|
+
export { fontScale, getDimensions };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/ffmpeg/dimensions.ts
|
|
21
|
+
var dimensions_exports = {};
|
|
22
|
+
__export(dimensions_exports, {
|
|
23
|
+
fontScale: () => fontScale,
|
|
24
|
+
getDimensions: () => getDimensions
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(dimensions_exports);
|
|
27
|
+
var DIMS = {
|
|
28
|
+
"9:16": { "720p": { w: 720, h: 1280 }, "1080p": { w: 1080, h: 1920 } },
|
|
29
|
+
"16:9": { "720p": { w: 1280, h: 720 }, "1080p": { w: 1920, h: 1080 } },
|
|
30
|
+
"1:1": { "720p": { w: 720, h: 720 }, "1080p": { w: 1080, h: 1080 } }
|
|
31
|
+
};
|
|
32
|
+
var SAFE_AREA_PCT = { top: 0.08, bottom: 0.12, side: 0.05 };
|
|
33
|
+
function getDimensions(aspect, resolution) {
|
|
34
|
+
const { w, h } = DIMS[aspect][resolution];
|
|
35
|
+
return {
|
|
36
|
+
width: w,
|
|
37
|
+
height: h,
|
|
38
|
+
safeAreaTop: Math.round(h * SAFE_AREA_PCT.top),
|
|
39
|
+
safeAreaBottom: Math.round(h * SAFE_AREA_PCT.bottom),
|
|
40
|
+
safeAreaSide: Math.round(w * SAFE_AREA_PCT.side)
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function fontScale(dims) {
|
|
44
|
+
return dims.width / 1080;
|
|
45
|
+
}
|
|
46
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
47
|
+
0 && (module.exports = {
|
|
48
|
+
fontScale,
|
|
49
|
+
getDimensions
|
|
50
|
+
});
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { RenderJob, RenderResult } from './types.mjs';
|
|
2
|
+
export { buildAssSubtitles, flattenCaptions } from './ffmpeg/captions.mjs';
|
|
3
|
+
export { assignStartTimes, estimateRenderCredits, storyboardDurationS } from './storyboard/utils.mjs';
|
|
4
|
+
import '@adforge-adgeniq/shared';
|
|
5
|
+
|
|
6
|
+
declare function renderVideo(job: RenderJob): Promise<RenderResult>;
|
|
7
|
+
|
|
8
|
+
export { RenderJob, RenderResult, renderVideo };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { RenderJob, RenderResult } from './types.js';
|
|
2
|
+
export { buildAssSubtitles, flattenCaptions } from './ffmpeg/captions.js';
|
|
3
|
+
export { assignStartTimes, estimateRenderCredits, storyboardDurationS } from './storyboard/utils.js';
|
|
4
|
+
import '@adforge-adgeniq/shared';
|
|
5
|
+
|
|
6
|
+
declare function renderVideo(job: RenderJob): Promise<RenderResult>;
|
|
7
|
+
|
|
8
|
+
export { RenderJob, RenderResult, renderVideo };
|