@amg555/frameforge-mcp 2.3.5 → 2.3.7
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/CHANGELOG.md +47 -0
- package/README.md +7 -5
- package/package.json +3 -3
- package/plugins/video-pipeline/skills/video-pipeline/SKILL.md +70 -14
- package/scripts/deep-validate.js +5 -3
- package/src/cli/make.js +6 -0
- package/src/mcp-server/server.js +166 -14
- package/src/video-editor/editor.js +852 -0
- package/src/video-renderer/renderer.js +129 -31
- package/src/video-renderer/scene-animator.js +1033 -251
- package/src/worker/server-render-free.js +5 -0
- package/src/worker/server.js +6 -0
- package/src/workflows/assets.js +25 -3
- package/src/workflows/render.js +26 -3
- package/src/workflows/script.js +2 -0
|
@@ -177,6 +177,11 @@ async function dispatchJob(job) {
|
|
|
177
177
|
case 'shorts': return runShorts(payload);
|
|
178
178
|
case 'package': return runPackaging(payload);
|
|
179
179
|
case 'publish': return runPublishing(payload);
|
|
180
|
+
case 'edit_video': {
|
|
181
|
+
const { VideoEditor } = require('../video-editor/editor');
|
|
182
|
+
const editor = new VideoEditor({ filesDir: FILES_DIR });
|
|
183
|
+
return editor.editAndAssemble(payload);
|
|
184
|
+
}
|
|
180
185
|
case 'full_pipeline': return runFullPipeline(payload, job.id);
|
|
181
186
|
default: throw new Error(`Unknown job type: ${type}`);
|
|
182
187
|
}
|
package/src/worker/server.js
CHANGED
|
@@ -96,6 +96,12 @@ async function executeJob(job) {
|
|
|
96
96
|
case 'shorts': result = await runShorts(job.payload); break;
|
|
97
97
|
case 'package': result = await runPackaging(job.payload); break;
|
|
98
98
|
case 'publish': result = await runPublishing(job.payload); break;
|
|
99
|
+
case 'edit_video': {
|
|
100
|
+
const { VideoEditor } = require('../video-editor/editor');
|
|
101
|
+
const editor = new VideoEditor({ filesDir: FILES_DIR });
|
|
102
|
+
result = await editor.editAndAssemble(job.payload);
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
99
105
|
default: throw new Error(`Unknown job type: ${job.type}`);
|
|
100
106
|
}
|
|
101
107
|
job.status = 'SUCCEEDED';
|
package/src/workflows/assets.js
CHANGED
|
@@ -21,10 +21,21 @@ const VDIR = `${FILES_DIR}/video_tmp`;
|
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* Prepare all scene visuals (user media or code animation) and TTS audio in parallel batches.
|
|
24
|
-
* @param {{ productionId: string, scenes: object[], parallelism?: number, skipTts?: boolean, voice?: string }} opts
|
|
24
|
+
* @param {{ productionId: string, scenes: object[], parallelism?: number, skipTts?: boolean, voice?: string, topic?: string, style?: string, theme?: string, title?: string, language?: string }} opts
|
|
25
25
|
* @returns {Promise<AssetsResult>}
|
|
26
26
|
*/
|
|
27
|
-
async function runAssets({
|
|
27
|
+
async function runAssets({
|
|
28
|
+
productionId,
|
|
29
|
+
scenes,
|
|
30
|
+
parallelism = 1,
|
|
31
|
+
skipTts = false,
|
|
32
|
+
voice = null,
|
|
33
|
+
topic = '',
|
|
34
|
+
style = '',
|
|
35
|
+
theme = '',
|
|
36
|
+
title = '',
|
|
37
|
+
language = '',
|
|
38
|
+
}) {
|
|
28
39
|
const ttsGen = new TTSProvider();
|
|
29
40
|
const sm = new StateMachine({ mode: 'file', stateDir: STATE_DIR });
|
|
30
41
|
const retryPol = new RetryPolicy({ maxAttempts: 3, baseDelayMs: 8000 });
|
|
@@ -90,8 +101,19 @@ async function runAssets({ productionId, scenes, parallelism = 1, skipTts = fals
|
|
|
90
101
|
focalPoint: scene.focal_point || null,
|
|
91
102
|
narration: scene.narration || '',
|
|
92
103
|
visualDescription: scene.visual_description || scene.narration || '',
|
|
104
|
+
topic: scene.topic || topic || '',
|
|
105
|
+
style: scene.style || style || '',
|
|
106
|
+
theme: scene.theme || theme || '',
|
|
107
|
+
title: scene.title || title || '',
|
|
93
108
|
musicMood: scene.music_mood || 'neutral',
|
|
94
|
-
language: scene.language || '',
|
|
109
|
+
language: scene.language || language || '',
|
|
110
|
+
html: scene.html || null,
|
|
111
|
+
code: scene.code || scene.animation_code || null,
|
|
112
|
+
startTime: scene.start_time != null ? scene.start_time : scene.trim_start,
|
|
113
|
+
endTime: scene.end_time != null ? scene.end_time : scene.trim_end,
|
|
114
|
+
speed: scene.speed != null ? scene.speed : 1.0,
|
|
115
|
+
clipVolume: scene.clip_volume != null ? scene.clip_volume : (scene.clipVolume != null ? scene.clipVolume : 0),
|
|
116
|
+
colorGrade: scene.color_grade || scene.colorGrade || null,
|
|
95
117
|
};
|
|
96
118
|
}));
|
|
97
119
|
results.push(...batchResults);
|
package/src/workflows/render.js
CHANGED
|
@@ -21,10 +21,22 @@ const STATE_DIR = `${FILES_DIR}/state`;
|
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* Render all scene assets into a final master video.
|
|
24
|
-
* @param {{ productionId: string, sceneAssets: object[], withMusic?: boolean, musicVolume?: number }} opts
|
|
24
|
+
* @param {{ productionId: string, sceneAssets: object[], withMusic?: boolean, musicVolume?: number, renderWidth?: number, renderHeight?: number, topic?: string, style?: string, theme?: string, title?: string, language?: string }} opts
|
|
25
25
|
* @returns {Promise<RenderResult>}
|
|
26
26
|
*/
|
|
27
|
-
async function runRender({
|
|
27
|
+
async function runRender({
|
|
28
|
+
productionId,
|
|
29
|
+
sceneAssets,
|
|
30
|
+
withMusic = true,
|
|
31
|
+
musicVolume = 0.07,
|
|
32
|
+
renderWidth = 1920,
|
|
33
|
+
renderHeight = 1080,
|
|
34
|
+
topic = '',
|
|
35
|
+
style = '',
|
|
36
|
+
theme = '',
|
|
37
|
+
title = '',
|
|
38
|
+
language = '',
|
|
39
|
+
}) {
|
|
28
40
|
const sm = new StateMachine({ mode: 'file', stateDir: STATE_DIR });
|
|
29
41
|
const retryPol = new RetryPolicy({ maxAttempts: 2, baseDelayMs: 15000 });
|
|
30
42
|
const telemetry = new Telemetry({ mode: 'file', logPath: `${FILES_DIR}/usage.ndjson` });
|
|
@@ -50,10 +62,21 @@ async function runRender({ productionId, sceneAssets, withMusic = true, musicVol
|
|
|
50
62
|
narration: asset.narration || '',
|
|
51
63
|
visualDescription: asset.visualDescription || '',
|
|
52
64
|
visualType: asset.visualType || 'code_animation',
|
|
65
|
+
topic: asset.topic || topic || '',
|
|
66
|
+
style: asset.style || style || '',
|
|
67
|
+
theme: asset.theme || theme || '',
|
|
68
|
+
title: asset.title || title || '',
|
|
53
69
|
musicMood: asset.musicMood || 'neutral',
|
|
54
|
-
language: asset.language || '',
|
|
70
|
+
language: asset.language || language || '',
|
|
55
71
|
camera: asset.camera || 'static',
|
|
56
72
|
focalPoint: asset.focalPoint || null,
|
|
73
|
+
html: asset.html || null,
|
|
74
|
+
code: asset.code || null,
|
|
75
|
+
startTime: asset.startTime,
|
|
76
|
+
endTime: asset.endTime,
|
|
77
|
+
speed: asset.speed,
|
|
78
|
+
clipVolume: asset.clipVolume,
|
|
79
|
+
colorGrade: asset.colorGrade,
|
|
57
80
|
renderWidth,
|
|
58
81
|
renderHeight,
|
|
59
82
|
});
|
package/src/workflows/script.js
CHANGED
|
@@ -67,6 +67,8 @@ function normaliseScene(raw, index) {
|
|
|
67
67
|
image_path: raw.image_path || null,
|
|
68
68
|
video_path: raw.video_path || null,
|
|
69
69
|
audio_path: raw.audio_path || null,
|
|
70
|
+
html: raw.html || null,
|
|
71
|
+
code: raw.code || raw.animation_code || null,
|
|
70
72
|
metadata: {
|
|
71
73
|
importance: meta.importance || 'medium',
|
|
72
74
|
hook_potential: typeof meta.hook_potential === 'number' ? meta.hook_potential : 0.5,
|