mulmocast 2.4.9 → 2.5.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/assets/html/js/animation_runtime.js +371 -0
- package/assets/html/js/auto_render.js +64 -0
- package/assets/html/js/data_attribute_registration.js +178 -0
- package/assets/html/tailwind_animated.html +37 -290
- package/lib/actions/image_references.js +1 -1
- package/lib/types/schema.d.ts +36 -0
- package/lib/types/schema.js +1 -0
- package/lib/utils/context.d.ts +12 -0
- package/lib/utils/file.d.ts +1 -0
- package/lib/utils/file.js +4 -0
- package/lib/utils/image_plugins/html_tailwind.js +4 -1
- package/package.json +7 -6
- package/scripts/test/images/qa_landscape.jpg +0 -0
- package/scripts/test/images/qa_portrait.png +0 -0
- package/scripts/test/test_animated.json +592 -0
- package/scripts/test/test_data_animation.json +149 -0
- package/scripts/test/test_html_cover_pan_zoom_landscape_canvas.json +245 -0
- package/scripts/test/test_html_cover_pan_zoom_portrait_canvas.json +207 -0
- package/scripts/test/test_reference_canvas_size.json +83 -0
|
@@ -1,293 +1,40 @@
|
|
|
1
|
-
<!
|
|
1
|
+
<!doctype html>
|
|
2
2
|
<html lang="en" class="h-full">
|
|
3
|
-
<head>
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
${custom_style}
|
|
14
|
-
</style>
|
|
15
|
-
</head>
|
|
16
|
-
<body class="bg-white text-gray-800 h-full flex flex-col">
|
|
17
|
-
${html_body}
|
|
18
|
-
|
|
19
|
-
<script>
|
|
20
|
-
// === MulmoCast Animation Helpers ===
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Easing functions for non-linear interpolation.
|
|
24
|
-
*/
|
|
25
|
-
const Easing = {
|
|
26
|
-
linear: (t) => t,
|
|
27
|
-
easeIn: (t) => t * t,
|
|
28
|
-
easeOut: (t) => 1 - (1 - t) * (1 - t),
|
|
29
|
-
easeInOut: (t) => t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2,
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Interpolation with clamping and optional easing.
|
|
34
|
-
*
|
|
35
|
-
* @param {number} value - Current value (typically frame number)
|
|
36
|
-
* @param {Object} opts - { input: { inMin, inMax }, output: { outMin, outMax }, easing?: string | function }
|
|
37
|
-
* @returns {number} Interpolated and clamped value
|
|
38
|
-
*
|
|
39
|
-
* @example
|
|
40
|
-
* interpolate(frame, { input: { inMin: 0, inMax: 30 }, output: { outMin: 0, outMax: 1 } })
|
|
41
|
-
* interpolate(frame, { input: { inMin: 0, inMax: 30 }, output: { outMin: 0, outMax: 1 }, easing: 'easeOut' })
|
|
42
|
-
*/
|
|
43
|
-
function interpolate(value, opts) {
|
|
44
|
-
const { inMin, inMax } = opts.input;
|
|
45
|
-
const { outMin, outMax } = opts.output;
|
|
46
|
-
if (inMax === inMin) {
|
|
47
|
-
return outMin;
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<script src="https://cdn.tailwindcss.com"></script>
|
|
7
|
+
<style>
|
|
8
|
+
/* Disable all CSS animations/transitions for deterministic frame-based rendering */
|
|
9
|
+
*, *::before, *::after {
|
|
10
|
+
animation-play-state: paused !important;
|
|
11
|
+
transition: none !important;
|
|
48
12
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Stagger animation across numbered elements.
|
|
79
|
-
* Selector must contain {i} placeholder (e.g. '#item{i}').
|
|
80
|
-
* @param {string} selector - e.g. '#item{i}'
|
|
81
|
-
* @param {number} count - number of elements (0-indexed)
|
|
82
|
-
* @param {Object} props - same as animate()
|
|
83
|
-
* @param {Object} opts - { start, stagger, duration, easing }
|
|
84
|
-
*/
|
|
85
|
-
MulmoAnimation.prototype.stagger = function(selector, count, props, opts) {
|
|
86
|
-
this._entries.push({ kind: 'stagger', selector, count, props, opts: opts || {} });
|
|
87
|
-
return this;
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Typewriter effect — reveal text character by character.
|
|
92
|
-
* @param {string} selector - target element selector
|
|
93
|
-
* @param {string} text - full text to reveal
|
|
94
|
-
* @param {Object} opts - { start, end }
|
|
95
|
-
*/
|
|
96
|
-
MulmoAnimation.prototype.typewriter = function(selector, text, opts) {
|
|
97
|
-
this._entries.push({ kind: 'typewriter', selector, text, opts: opts || {} });
|
|
98
|
-
return this;
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Animated counter — interpolate a number and display with optional prefix/suffix.
|
|
103
|
-
* @param {string} selector - target element selector
|
|
104
|
-
* @param {[number, number]} range - [from, to]
|
|
105
|
-
* @param {Object} opts - { start, end, prefix, suffix, decimals }
|
|
106
|
-
*/
|
|
107
|
-
MulmoAnimation.prototype.counter = function(selector, range, opts) {
|
|
108
|
-
this._entries.push({ kind: 'counter', selector, range, opts: opts || {} });
|
|
109
|
-
return this;
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Code reveal — show lines of code one by one (line-level typewriter).
|
|
114
|
-
* @param {string} selector - target element selector
|
|
115
|
-
* @param {string[]} lines - array of code lines
|
|
116
|
-
* @param {Object} opts - { start, end }
|
|
117
|
-
*/
|
|
118
|
-
MulmoAnimation.prototype.codeReveal = function(selector, lines, opts) {
|
|
119
|
-
this._entries.push({ kind: 'codeReveal', selector, lines, opts: opts || {} });
|
|
120
|
-
return this;
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Blink — periodic show/hide toggle (e.g. cursor blinking).
|
|
125
|
-
* @param {string} selector - target element selector
|
|
126
|
-
* @param {Object} opts - { interval } (half-cycle seconds, default 0.5)
|
|
127
|
-
*/
|
|
128
|
-
MulmoAnimation.prototype.blink = function(selector, opts) {
|
|
129
|
-
this._entries.push({ kind: 'blink', selector, opts: opts || {} });
|
|
130
|
-
return this;
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
/** Resolve easing name string or function to an easing function */
|
|
134
|
-
MulmoAnimation.prototype._resolveEasing = function(e) {
|
|
135
|
-
if (!e) return Easing.linear;
|
|
136
|
-
if (typeof e === 'function') return e;
|
|
137
|
-
return Easing[e] || Easing.linear;
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
/** Apply props to element at a given progress (0-1) with easing */
|
|
141
|
-
MulmoAnimation.prototype._applyProps = function(el, props, progress, easingFn) {
|
|
142
|
-
if (!el) return;
|
|
143
|
-
const transforms = [];
|
|
144
|
-
Object.keys(props).forEach((prop) => {
|
|
145
|
-
const spec = props[prop];
|
|
146
|
-
const from = spec[0], to = spec[1];
|
|
147
|
-
const unit = (spec.length > 2) ? spec[2] : null;
|
|
148
|
-
const val = from + easingFn(progress) * (to - from);
|
|
149
|
-
|
|
150
|
-
if (TRANSFORM_PROPS.hasOwnProperty(prop)) {
|
|
151
|
-
const tUnit = unit || TRANSFORM_PROPS[prop];
|
|
152
|
-
transforms.push(prop === 'scale' ? 'scale(' + val + ')' : prop + '(' + val + tUnit + ')');
|
|
153
|
-
} else if (el instanceof SVGElement && SVG_PROPS.indexOf(prop) !== -1) {
|
|
154
|
-
el.setAttribute(prop, val);
|
|
155
|
-
} else if (prop === 'opacity') {
|
|
156
|
-
el.style.opacity = val;
|
|
157
|
-
} else {
|
|
158
|
-
const cssUnit = unit || 'px';
|
|
159
|
-
el.style[prop] = val + cssUnit;
|
|
160
|
-
}
|
|
161
|
-
});
|
|
162
|
-
if (transforms.length > 0) {
|
|
163
|
-
el.style.transform = transforms.join(' ');
|
|
164
|
-
}
|
|
165
|
-
};
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* Update all registered animations for the given frame.
|
|
169
|
-
* @param {number} frame - current frame number
|
|
170
|
-
* @param {number} fps - frames per second
|
|
171
|
-
*/
|
|
172
|
-
MulmoAnimation.prototype.update = function(frame, fps) {
|
|
173
|
-
this._entries.forEach((entry) => {
|
|
174
|
-
const opts = entry.opts;
|
|
175
|
-
const easingFn = this._resolveEasing(opts.easing);
|
|
176
|
-
|
|
177
|
-
if (entry.kind === 'animate') {
|
|
178
|
-
const startFrame = (opts.start || 0) * fps;
|
|
179
|
-
const endFrame = (opts.end === 'auto' ? window.__MULMO.totalFrames / fps : (opts.end || 0)) * fps;
|
|
180
|
-
const progress = Math.max(0, Math.min(1, endFrame === startFrame ? 1 : (frame - startFrame) / (endFrame - startFrame)));
|
|
181
|
-
const el = document.querySelector(entry.selector);
|
|
182
|
-
this._applyProps(el, entry.props, progress, easingFn);
|
|
183
|
-
|
|
184
|
-
} else if (entry.kind === 'stagger') {
|
|
185
|
-
const baseStart = (opts.start || 0) * fps;
|
|
186
|
-
const staggerDelay = (opts.stagger || 0.2) * fps;
|
|
187
|
-
const dur = (opts.duration || 0.5) * fps;
|
|
188
|
-
for (let j = 0; j < entry.count; j++) {
|
|
189
|
-
const sel = entry.selector.replace(/\{i\}/g, j);
|
|
190
|
-
const sEl = document.querySelector(sel);
|
|
191
|
-
const sStart = baseStart + j * staggerDelay;
|
|
192
|
-
const sEnd = sStart + dur;
|
|
193
|
-
const sProgress = Math.max(0, Math.min(1, sEnd === sStart ? 1 : (frame - sStart) / (sEnd - sStart)));
|
|
194
|
-
this._applyProps(sEl, entry.props, sProgress, easingFn);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
} else if (entry.kind === 'typewriter') {
|
|
198
|
-
const twStart = (opts.start || 0) * fps;
|
|
199
|
-
const twEnd = (opts.end === 'auto' ? window.__MULMO.totalFrames / fps : (opts.end || 0)) * fps;
|
|
200
|
-
const twProgress = Math.max(0, Math.min(1, twEnd === twStart ? 1 : (frame - twStart) / (twEnd - twStart)));
|
|
201
|
-
const charCount = Math.floor(twProgress * entry.text.length);
|
|
202
|
-
const twEl = document.querySelector(entry.selector);
|
|
203
|
-
if (twEl) twEl.textContent = entry.text.substring(0, charCount);
|
|
204
|
-
|
|
205
|
-
} else if (entry.kind === 'counter') {
|
|
206
|
-
const cStart = (opts.start || 0) * fps;
|
|
207
|
-
const cEnd = (opts.end === 'auto' ? window.__MULMO.totalFrames / fps : (opts.end || 0)) * fps;
|
|
208
|
-
const cProgress = Math.max(0, Math.min(1, cEnd === cStart ? 1 : (frame - cStart) / (cEnd - cStart)));
|
|
209
|
-
const cVal = entry.range[0] + easingFn(cProgress) * (entry.range[1] - entry.range[0]);
|
|
210
|
-
const decimals = opts.decimals || 0;
|
|
211
|
-
const display = (opts.prefix || '') + cVal.toFixed(decimals) + (opts.suffix || '');
|
|
212
|
-
const cEl = document.querySelector(entry.selector);
|
|
213
|
-
if (cEl) cEl.textContent = display;
|
|
214
|
-
|
|
215
|
-
} else if (entry.kind === 'codeReveal') {
|
|
216
|
-
const crStart = (opts.start || 0) * fps;
|
|
217
|
-
const crEnd = (opts.end === 'auto' ? window.__MULMO.totalFrames / fps : (opts.end || 0)) * fps;
|
|
218
|
-
const crProgress = Math.max(0, Math.min(1, crEnd === crStart ? 1 : (frame - crStart) / (crEnd - crStart)));
|
|
219
|
-
const lineCount = Math.floor(crProgress * entry.lines.length);
|
|
220
|
-
const crEl = document.querySelector(entry.selector);
|
|
221
|
-
if (crEl) crEl.textContent = entry.lines.slice(0, lineCount).join('\n');
|
|
222
|
-
|
|
223
|
-
} else if (entry.kind === 'blink') {
|
|
224
|
-
const interval_s = opts.interval || 0.5;
|
|
225
|
-
const blinkEl = document.querySelector(entry.selector);
|
|
226
|
-
if (blinkEl) {
|
|
227
|
-
const cycle = (frame / fps) / interval_s;
|
|
228
|
-
blinkEl.style.opacity = (Math.floor(cycle) % 2 === 0) ? 1 : 0;
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
});
|
|
232
|
-
};
|
|
233
|
-
|
|
234
|
-
// === MulmoCast Frame State (updated by Puppeteer per frame) ===
|
|
235
|
-
window.__MULMO = {
|
|
236
|
-
frame: 0,
|
|
237
|
-
totalFrames: ${totalFrames},
|
|
238
|
-
fps: ${fps},
|
|
239
|
-
};
|
|
240
|
-
</script>
|
|
241
|
-
|
|
242
|
-
${user_script}
|
|
243
|
-
|
|
244
|
-
<script>
|
|
245
|
-
// Auto-render: if MulmoAnimation is used but render() is not defined, generate it
|
|
246
|
-
if (typeof render !== 'function' && typeof animation !== 'undefined' && animation instanceof MulmoAnimation) {
|
|
247
|
-
window.render = function(frame, totalFrames, fps) { animation.update(frame, fps); };
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
// Initial render (frame 0)
|
|
251
|
-
if (typeof render === 'function') {
|
|
252
|
-
const result = render(0, window.__MULMO.totalFrames, window.__MULMO.fps);
|
|
253
|
-
if (result && typeof result.then === 'function') {
|
|
254
|
-
result.catch(console.error);
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
/**
|
|
259
|
-
* Play animation in real-time using requestAnimationFrame.
|
|
260
|
-
* Returns a Promise that resolves when all frames have been rendered.
|
|
261
|
-
* Called by Puppeteer's page.evaluate() during screencast recording.
|
|
262
|
-
*/
|
|
263
|
-
window.playAnimation = function() {
|
|
264
|
-
return new Promise(function(resolve) {
|
|
265
|
-
var mulmo = window.__MULMO;
|
|
266
|
-
var fps = mulmo.fps;
|
|
267
|
-
var totalFrames = mulmo.totalFrames;
|
|
268
|
-
var frameDuration = 1000 / fps;
|
|
269
|
-
var startTime = null;
|
|
270
|
-
|
|
271
|
-
function tick(timestamp) {
|
|
272
|
-
if (startTime === null) startTime = timestamp;
|
|
273
|
-
var elapsed = timestamp - startTime;
|
|
274
|
-
var frame = Math.min(Math.floor(elapsed / frameDuration), totalFrames - 1);
|
|
275
|
-
|
|
276
|
-
mulmo.frame = frame;
|
|
277
|
-
if (typeof render === 'function') {
|
|
278
|
-
render(frame, totalFrames, fps);
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
if (frame < totalFrames - 1) {
|
|
282
|
-
requestAnimationFrame(tick);
|
|
283
|
-
} else {
|
|
284
|
-
resolve();
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
requestAnimationFrame(tick);
|
|
289
|
-
});
|
|
290
|
-
};
|
|
291
|
-
</script>
|
|
292
|
-
</body>
|
|
13
|
+
${custom_style}
|
|
14
|
+
</style>
|
|
15
|
+
</head>
|
|
16
|
+
<body class="bg-white text-gray-800 h-full flex flex-col">
|
|
17
|
+
${html_body}
|
|
18
|
+
|
|
19
|
+
<script>
|
|
20
|
+
${animation_runtime}
|
|
21
|
+
|
|
22
|
+
// === MulmoCast Frame State (updated by Puppeteer per frame) ===
|
|
23
|
+
window.__MULMO = {
|
|
24
|
+
frame: 0,
|
|
25
|
+
totalFrames: ${totalFrames},
|
|
26
|
+
fps: ${fps},
|
|
27
|
+
};
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
${user_script}
|
|
31
|
+
|
|
32
|
+
<script>
|
|
33
|
+
${data_attribute_registration}
|
|
34
|
+
</script>
|
|
35
|
+
|
|
36
|
+
<script>
|
|
37
|
+
${auto_render}
|
|
38
|
+
</script>
|
|
39
|
+
</body>
|
|
293
40
|
</html>
|
|
@@ -33,7 +33,7 @@ export const generateReferenceImage = async (inputs) => {
|
|
|
33
33
|
},
|
|
34
34
|
params: {
|
|
35
35
|
model: imageAgentInfo.imageParams.model,
|
|
36
|
-
canvasSize: context.presentationStyle.canvasSize,
|
|
36
|
+
canvasSize: image.canvasSize ?? context.presentationStyle.canvasSize,
|
|
37
37
|
},
|
|
38
38
|
},
|
|
39
39
|
},
|
package/lib/types/schema.d.ts
CHANGED
|
@@ -2957,6 +2957,10 @@ export declare const mulmoAudioAssetSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
2957
2957
|
export declare const mulmoImagePromptMediaSchema: z.ZodObject<{
|
|
2958
2958
|
type: z.ZodLiteral<"imagePrompt">;
|
|
2959
2959
|
prompt: z.ZodString;
|
|
2960
|
+
canvasSize: z.ZodOptional<z.ZodObject<{
|
|
2961
|
+
width: z.ZodNumber;
|
|
2962
|
+
height: z.ZodNumber;
|
|
2963
|
+
}, z.core.$strict>>;
|
|
2960
2964
|
}, z.core.$strict>;
|
|
2961
2965
|
export declare const mulmoImageParamsImagesValueSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
2962
2966
|
type: z.ZodLiteral<"image">;
|
|
@@ -2973,6 +2977,10 @@ export declare const mulmoImageParamsImagesValueSchema: z.ZodUnion<readonly [z.Z
|
|
|
2973
2977
|
}, z.core.$strict>, z.ZodObject<{
|
|
2974
2978
|
type: z.ZodLiteral<"imagePrompt">;
|
|
2975
2979
|
prompt: z.ZodString;
|
|
2980
|
+
canvasSize: z.ZodOptional<z.ZodObject<{
|
|
2981
|
+
width: z.ZodNumber;
|
|
2982
|
+
height: z.ZodNumber;
|
|
2983
|
+
}, z.core.$strict>>;
|
|
2976
2984
|
}, z.core.$strict>]>;
|
|
2977
2985
|
export declare const mulmoImageParamsImagesSchema: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodObject<{
|
|
2978
2986
|
type: z.ZodLiteral<"image">;
|
|
@@ -2989,6 +2997,10 @@ export declare const mulmoImageParamsImagesSchema: z.ZodRecord<z.ZodString, z.Zo
|
|
|
2989
2997
|
}, z.core.$strict>, z.ZodObject<{
|
|
2990
2998
|
type: z.ZodLiteral<"imagePrompt">;
|
|
2991
2999
|
prompt: z.ZodString;
|
|
3000
|
+
canvasSize: z.ZodOptional<z.ZodObject<{
|
|
3001
|
+
width: z.ZodNumber;
|
|
3002
|
+
height: z.ZodNumber;
|
|
3003
|
+
}, z.core.$strict>>;
|
|
2992
3004
|
}, z.core.$strict>]>>;
|
|
2993
3005
|
export declare const mulmoFillOptionSchema: z.ZodObject<{
|
|
2994
3006
|
style: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
@@ -3057,6 +3069,10 @@ export declare const mulmoImageParamsSchema: z.ZodObject<{
|
|
|
3057
3069
|
}, z.core.$strict>, z.ZodObject<{
|
|
3058
3070
|
type: z.ZodLiteral<"imagePrompt">;
|
|
3059
3071
|
prompt: z.ZodString;
|
|
3072
|
+
canvasSize: z.ZodOptional<z.ZodObject<{
|
|
3073
|
+
width: z.ZodNumber;
|
|
3074
|
+
height: z.ZodNumber;
|
|
3075
|
+
}, z.core.$strict>>;
|
|
3060
3076
|
}, z.core.$strict>]>>>;
|
|
3061
3077
|
backgroundImage: z.ZodOptional<z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
3062
3078
|
source: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
@@ -6405,6 +6421,10 @@ export declare const mulmoPresentationStyleSchema: z.ZodObject<{
|
|
|
6405
6421
|
}, z.core.$strict>, z.ZodObject<{
|
|
6406
6422
|
type: z.ZodLiteral<"imagePrompt">;
|
|
6407
6423
|
prompt: z.ZodString;
|
|
6424
|
+
canvasSize: z.ZodOptional<z.ZodObject<{
|
|
6425
|
+
width: z.ZodNumber;
|
|
6426
|
+
height: z.ZodNumber;
|
|
6427
|
+
}, z.core.$strict>>;
|
|
6408
6428
|
}, z.core.$strict>]>>>;
|
|
6409
6429
|
backgroundImage: z.ZodOptional<z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
6410
6430
|
source: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
@@ -6861,6 +6881,10 @@ export declare const mulmoScriptSchema: z.ZodObject<{
|
|
|
6861
6881
|
}, z.core.$strict>, z.ZodObject<{
|
|
6862
6882
|
type: z.ZodLiteral<"imagePrompt">;
|
|
6863
6883
|
prompt: z.ZodString;
|
|
6884
|
+
canvasSize: z.ZodOptional<z.ZodObject<{
|
|
6885
|
+
width: z.ZodNumber;
|
|
6886
|
+
height: z.ZodNumber;
|
|
6887
|
+
}, z.core.$strict>>;
|
|
6864
6888
|
}, z.core.$strict>]>>>;
|
|
6865
6889
|
backgroundImage: z.ZodOptional<z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
6866
6890
|
source: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
@@ -10279,6 +10303,10 @@ export declare const mulmoStudioSchema: z.ZodObject<{
|
|
|
10279
10303
|
}, z.core.$strict>, z.ZodObject<{
|
|
10280
10304
|
type: z.ZodLiteral<"imagePrompt">;
|
|
10281
10305
|
prompt: z.ZodString;
|
|
10306
|
+
canvasSize: z.ZodOptional<z.ZodObject<{
|
|
10307
|
+
width: z.ZodNumber;
|
|
10308
|
+
height: z.ZodNumber;
|
|
10309
|
+
}, z.core.$strict>>;
|
|
10282
10310
|
}, z.core.$strict>]>>>;
|
|
10283
10311
|
backgroundImage: z.ZodOptional<z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
10284
10312
|
source: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
@@ -13633,6 +13661,10 @@ export declare const mulmoPromptTemplateSchema: z.ZodObject<{
|
|
|
13633
13661
|
}, z.core.$strict>, z.ZodObject<{
|
|
13634
13662
|
type: z.ZodLiteral<"imagePrompt">;
|
|
13635
13663
|
prompt: z.ZodString;
|
|
13664
|
+
canvasSize: z.ZodOptional<z.ZodObject<{
|
|
13665
|
+
width: z.ZodNumber;
|
|
13666
|
+
height: z.ZodNumber;
|
|
13667
|
+
}, z.core.$strict>>;
|
|
13636
13668
|
}, z.core.$strict>]>>>;
|
|
13637
13669
|
backgroundImage: z.ZodOptional<z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
13638
13670
|
source: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
@@ -14083,6 +14115,10 @@ export declare const mulmoPromptTemplateFileSchema: z.ZodObject<{
|
|
|
14083
14115
|
}, z.core.$strict>, z.ZodObject<{
|
|
14084
14116
|
type: z.ZodLiteral<"imagePrompt">;
|
|
14085
14117
|
prompt: z.ZodString;
|
|
14118
|
+
canvasSize: z.ZodOptional<z.ZodObject<{
|
|
14119
|
+
width: z.ZodNumber;
|
|
14120
|
+
height: z.ZodNumber;
|
|
14121
|
+
}, z.core.$strict>>;
|
|
14086
14122
|
}, z.core.$strict>]>>>;
|
|
14087
14123
|
backgroundImage: z.ZodOptional<z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
14088
14124
|
source: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
package/lib/types/schema.js
CHANGED
|
@@ -264,6 +264,7 @@ export const mulmoImagePromptMediaSchema = z
|
|
|
264
264
|
.object({
|
|
265
265
|
type: z.literal("imagePrompt"),
|
|
266
266
|
prompt: z.string().min(1),
|
|
267
|
+
canvasSize: z.object({ width: z.number(), height: z.number() }).strict().optional(),
|
|
267
268
|
})
|
|
268
269
|
.strict();
|
|
269
270
|
export const mulmoImageParamsImagesValueSchema = z.union([mulmoImageMediaSchema, mulmoImagePromptMediaSchema]);
|
package/lib/utils/context.d.ts
CHANGED
|
@@ -69,6 +69,10 @@ export declare const createStudioData: (_mulmoScript: MulmoScript, fileName: str
|
|
|
69
69
|
} | {
|
|
70
70
|
type: "imagePrompt";
|
|
71
71
|
prompt: string;
|
|
72
|
+
canvasSize?: {
|
|
73
|
+
width: number;
|
|
74
|
+
height: number;
|
|
75
|
+
} | undefined;
|
|
72
76
|
}> | undefined;
|
|
73
77
|
backgroundImage?: string | {
|
|
74
78
|
source: {
|
|
@@ -2164,6 +2168,10 @@ export declare const initializeContextFromFiles: (files: FileObject, raiseError:
|
|
|
2164
2168
|
} | {
|
|
2165
2169
|
type: "imagePrompt";
|
|
2166
2170
|
prompt: string;
|
|
2171
|
+
canvasSize?: {
|
|
2172
|
+
width: number;
|
|
2173
|
+
height: number;
|
|
2174
|
+
} | undefined;
|
|
2167
2175
|
}> | undefined;
|
|
2168
2176
|
backgroundImage?: string | {
|
|
2169
2177
|
source: {
|
|
@@ -4266,6 +4274,10 @@ export declare const initializeContextFromFiles: (files: FileObject, raiseError:
|
|
|
4266
4274
|
} | {
|
|
4267
4275
|
type: "imagePrompt";
|
|
4268
4276
|
prompt: string;
|
|
4277
|
+
canvasSize?: {
|
|
4278
|
+
width: number;
|
|
4279
|
+
height: number;
|
|
4280
|
+
} | undefined;
|
|
4269
4281
|
}> | undefined;
|
|
4270
4282
|
backgroundImage?: string | {
|
|
4271
4283
|
source: {
|
package/lib/utils/file.d.ts
CHANGED
|
@@ -49,6 +49,7 @@ export declare const blankImagePath: () => string;
|
|
|
49
49
|
export declare const blankVerticalImagePath: () => string;
|
|
50
50
|
export declare const blankSquareImagePath: () => string;
|
|
51
51
|
export declare const getHTMLFile: (filename: string) => string;
|
|
52
|
+
export declare const getJSFile: (filename: string) => string;
|
|
52
53
|
export declare const getBaseDirPath: (basedir?: string) => string;
|
|
53
54
|
export declare const getFullPath: (baseDirPath: string | undefined, file: string) => string;
|
|
54
55
|
export declare const readScriptTemplateFile: (scriptTemplateFileName: string) => MulmoScript;
|
package/lib/utils/file.js
CHANGED
|
@@ -158,6 +158,10 @@ export const getHTMLFile = (filename) => {
|
|
|
158
158
|
const htmlPath = resolveAssetFile(`./assets/html/${filename}.html`, npmRoot);
|
|
159
159
|
return fs.readFileSync(htmlPath, "utf-8");
|
|
160
160
|
};
|
|
161
|
+
export const getJSFile = (filename) => {
|
|
162
|
+
const jsPath = resolveAssetFile(`./assets/html/js/${filename}.js`, npmRoot);
|
|
163
|
+
return fs.readFileSync(jsPath, "utf-8");
|
|
164
|
+
};
|
|
161
165
|
// for cli
|
|
162
166
|
export const getBaseDirPath = (basedir) => {
|
|
163
167
|
if (!basedir) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import nodePath from "node:path";
|
|
3
3
|
import { MulmoBeatMethods } from "../../methods/mulmo_beat.js";
|
|
4
|
-
import { getHTMLFile } from "../file.js";
|
|
4
|
+
import { getHTMLFile, getJSFile } from "../file.js";
|
|
5
5
|
import { renderHTMLToImage, interpolate, renderHTMLToFrames, renderHTMLToVideo } from "../html_render.js";
|
|
6
6
|
import { framesToVideo } from "../ffmpeg_utils.js";
|
|
7
7
|
import { parrotingImagePath } from "./utils.js";
|
|
@@ -72,6 +72,9 @@ const processHtmlTailwindAnimated = async (params) => {
|
|
|
72
72
|
const script = "script" in beat.image ? beat.image.script : undefined;
|
|
73
73
|
const rawHtmlData = interpolate(template, {
|
|
74
74
|
html_body: html,
|
|
75
|
+
animation_runtime: getJSFile("animation_runtime"),
|
|
76
|
+
data_attribute_registration: getJSFile("data_attribute_registration"),
|
|
77
|
+
auto_render: getJSFile("auto_render"),
|
|
75
78
|
user_script: buildUserScript(script),
|
|
76
79
|
totalFrames: String(totalFrames),
|
|
77
80
|
fps: String(fps),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mulmocast",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.node.js",
|
|
@@ -24,7 +24,8 @@
|
|
|
24
24
|
}
|
|
25
25
|
},
|
|
26
26
|
"resolutions": {
|
|
27
|
-
"minimatch": "^10.2.4"
|
|
27
|
+
"minimatch": "^10.2.4",
|
|
28
|
+
"yauzl": "^3.2.1"
|
|
28
29
|
},
|
|
29
30
|
"bin": {
|
|
30
31
|
"mulmo": "lib/cli/bin.js",
|
|
@@ -56,7 +57,7 @@
|
|
|
56
57
|
"pdf": "npx tsx ./src/cli/bin.ts pdf",
|
|
57
58
|
"test": "rm -f scratchpad/test*.* && npx tsx ./src/audio.ts scripts/test/test.json && npx tsx ./src/images.ts scripts/test/test.json && npx tsx ./src/movie.ts scripts/test/test.json",
|
|
58
59
|
"ci_test": "cross-env NODE_ENV=test tsx --test --experimental-test-coverage ./test/*/test_*.ts",
|
|
59
|
-
"lint": "eslint src test",
|
|
60
|
+
"lint": "eslint src test assets/html/js",
|
|
60
61
|
"build": "tsc",
|
|
61
62
|
"build_test": "tsc && git checkout -- lib/*",
|
|
62
63
|
"cli": "npx tsx ./src/cli/bin.ts",
|
|
@@ -68,7 +69,7 @@
|
|
|
68
69
|
"story_to_script": "npx tsx ./src/cli/bin.ts tool story_to_script",
|
|
69
70
|
"whisper": "npx tsx ./src/cli/bin.ts tool whisper",
|
|
70
71
|
"latest": "yarn upgrade-interactive --latest",
|
|
71
|
-
"format": "prettier --write '{src,scripts,assets/templates,assets/styles,draft,ideason,scripts_mag2,proto,test,batch,graphai,output,docs/scripts}/**/*.{ts,json,yaml}'",
|
|
72
|
+
"format": "prettier --write '{src,scripts,assets/templates,assets/styles,assets/html/js,draft,ideason,scripts_mag2,proto,test,batch,graphai,output,docs/scripts}/**/*.{ts,js,json,yaml}'",
|
|
72
73
|
"deep_research": "npx tsx ./src/tools/deep_research.ts",
|
|
73
74
|
"template": "npx tsx batch/template2tsobject.ts && yarn run format",
|
|
74
75
|
"mcp_server": "npx tsx ./src/mcp/server.ts",
|
|
@@ -109,9 +110,9 @@
|
|
|
109
110
|
"graphai": "^2.0.16",
|
|
110
111
|
"jsdom": "^28.1.0",
|
|
111
112
|
"marked": "^17.0.4",
|
|
112
|
-
"mulmocast-vision": "^1.0.
|
|
113
|
+
"mulmocast-vision": "^1.0.9",
|
|
113
114
|
"ora": "^9.3.0",
|
|
114
|
-
"puppeteer": "^24.39.
|
|
115
|
+
"puppeteer": "^24.39.1",
|
|
115
116
|
"replicate": "^1.4.0",
|
|
116
117
|
"yaml": "^2.8.2",
|
|
117
118
|
"yargs": "^18.0.0",
|
|
Binary file
|
|
Binary file
|