@studiomeyer/mcp-video 1.0.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/.github/ISSUE_TEMPLATE/bug_report.md +31 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +19 -0
- package/.github/workflows/ci.yml +34 -0
- package/CHANGELOG.md +24 -0
- package/CONTRIBUTING.md +75 -0
- package/LICENSE +21 -0
- package/README.md +198 -0
- package/USAGE.md +144 -0
- package/dist/handlers/capcut.d.ts +6 -0
- package/dist/handlers/capcut.js +229 -0
- package/dist/handlers/capcut.js.map +1 -0
- package/dist/handlers/editing.d.ts +6 -0
- package/dist/handlers/editing.js +242 -0
- package/dist/handlers/editing.js.map +1 -0
- package/dist/handlers/index.d.ts +2 -0
- package/dist/handlers/index.js +33 -0
- package/dist/handlers/index.js.map +1 -0
- package/dist/handlers/post-production.d.ts +5 -0
- package/dist/handlers/post-production.js +109 -0
- package/dist/handlers/post-production.js.map +1 -0
- package/dist/handlers/smart-screenshot.d.ts +5 -0
- package/dist/handlers/smart-screenshot.js +83 -0
- package/dist/handlers/smart-screenshot.js.map +1 -0
- package/dist/handlers/tts.d.ts +5 -0
- package/dist/handlers/tts.js +83 -0
- package/dist/handlers/tts.js.map +1 -0
- package/dist/handlers/video.d.ts +5 -0
- package/dist/handlers/video.js +127 -0
- package/dist/handlers/video.js.map +1 -0
- package/dist/lib/dual-transport.d.ts +42 -0
- package/dist/lib/dual-transport.js +208 -0
- package/dist/lib/dual-transport.js.map +1 -0
- package/dist/lib/logger.d.ts +12 -0
- package/dist/lib/logger.js +42 -0
- package/dist/lib/logger.js.map +1 -0
- package/dist/lib/types.d.ts +16 -0
- package/dist/lib/types.js +15 -0
- package/dist/lib/types.js.map +1 -0
- package/dist/schemas/capcut.d.ts +608 -0
- package/dist/schemas/capcut.js +411 -0
- package/dist/schemas/capcut.js.map +1 -0
- package/dist/schemas/editing.d.ts +822 -0
- package/dist/schemas/editing.js +466 -0
- package/dist/schemas/editing.js.map +1 -0
- package/dist/schemas/index.d.ts +2366 -0
- package/dist/schemas/index.js +15 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/schemas/post-production.d.ts +379 -0
- package/dist/schemas/post-production.js +268 -0
- package/dist/schemas/post-production.js.map +1 -0
- package/dist/schemas/smart-screenshot.d.ts +127 -0
- package/dist/schemas/smart-screenshot.js +122 -0
- package/dist/schemas/smart-screenshot.js.map +1 -0
- package/dist/schemas/tts.d.ts +220 -0
- package/dist/schemas/tts.js +194 -0
- package/dist/schemas/tts.js.map +1 -0
- package/dist/schemas/video.d.ts +236 -0
- package/dist/schemas/video.js +210 -0
- package/dist/schemas/video.js.map +1 -0
- package/dist/server.d.ts +11 -0
- package/dist/server.js +239 -0
- package/dist/server.js.map +1 -0
- package/dist/server.test.d.ts +1 -0
- package/dist/server.test.js +87 -0
- package/dist/server.test.js.map +1 -0
- package/dist/tools/engine/audio-mixer.d.ts +40 -0
- package/dist/tools/engine/audio-mixer.js +169 -0
- package/dist/tools/engine/audio-mixer.js.map +1 -0
- package/dist/tools/engine/audio.d.ts +22 -0
- package/dist/tools/engine/audio.js +73 -0
- package/dist/tools/engine/audio.js.map +1 -0
- package/dist/tools/engine/beat-sync.d.ts +31 -0
- package/dist/tools/engine/beat-sync.js +270 -0
- package/dist/tools/engine/beat-sync.js.map +1 -0
- package/dist/tools/engine/capture.d.ts +12 -0
- package/dist/tools/engine/capture.js +290 -0
- package/dist/tools/engine/capture.js.map +1 -0
- package/dist/tools/engine/chroma-key.d.ts +27 -0
- package/dist/tools/engine/chroma-key.js +154 -0
- package/dist/tools/engine/chroma-key.js.map +1 -0
- package/dist/tools/engine/concat.d.ts +49 -0
- package/dist/tools/engine/concat.js +149 -0
- package/dist/tools/engine/concat.js.map +1 -0
- package/dist/tools/engine/cursor.d.ts +26 -0
- package/dist/tools/engine/cursor.js +185 -0
- package/dist/tools/engine/cursor.js.map +1 -0
- package/dist/tools/engine/easing.d.ts +15 -0
- package/dist/tools/engine/easing.js +100 -0
- package/dist/tools/engine/easing.js.map +1 -0
- package/dist/tools/engine/editing.d.ts +158 -0
- package/dist/tools/engine/editing.js +541 -0
- package/dist/tools/engine/editing.js.map +1 -0
- package/dist/tools/engine/encoder.d.ts +31 -0
- package/dist/tools/engine/encoder.js +154 -0
- package/dist/tools/engine/encoder.js.map +1 -0
- package/dist/tools/engine/index.d.ts +30 -0
- package/dist/tools/engine/index.js +23 -0
- package/dist/tools/engine/index.js.map +1 -0
- package/dist/tools/engine/lut-presets.d.ts +25 -0
- package/dist/tools/engine/lut-presets.js +141 -0
- package/dist/tools/engine/lut-presets.js.map +1 -0
- package/dist/tools/engine/narrated-video.d.ts +63 -0
- package/dist/tools/engine/narrated-video.js +163 -0
- package/dist/tools/engine/narrated-video.js.map +1 -0
- package/dist/tools/engine/scenes.d.ts +17 -0
- package/dist/tools/engine/scenes.js +223 -0
- package/dist/tools/engine/scenes.js.map +1 -0
- package/dist/tools/engine/smart-screenshot.d.ts +80 -0
- package/dist/tools/engine/smart-screenshot.js +744 -0
- package/dist/tools/engine/smart-screenshot.js.map +1 -0
- package/dist/tools/engine/social-format.d.ts +66 -0
- package/dist/tools/engine/social-format.js +107 -0
- package/dist/tools/engine/social-format.js.map +1 -0
- package/dist/tools/engine/template-renderer.d.ts +45 -0
- package/dist/tools/engine/template-renderer.js +233 -0
- package/dist/tools/engine/template-renderer.js.map +1 -0
- package/dist/tools/engine/templates.d.ts +87 -0
- package/dist/tools/engine/templates.js +272 -0
- package/dist/tools/engine/templates.js.map +1 -0
- package/dist/tools/engine/text-animations.d.ts +33 -0
- package/dist/tools/engine/text-animations.js +192 -0
- package/dist/tools/engine/text-animations.js.map +1 -0
- package/dist/tools/engine/text-overlay.d.ts +27 -0
- package/dist/tools/engine/text-overlay.js +84 -0
- package/dist/tools/engine/text-overlay.js.map +1 -0
- package/dist/tools/engine/tts.d.ts +54 -0
- package/dist/tools/engine/tts.js +186 -0
- package/dist/tools/engine/tts.js.map +1 -0
- package/dist/tools/engine/types.d.ts +166 -0
- package/dist/tools/engine/types.js +13 -0
- package/dist/tools/engine/types.js.map +1 -0
- package/dist/tools/engine/voice-effects.d.ts +18 -0
- package/dist/tools/engine/voice-effects.js +215 -0
- package/dist/tools/engine/voice-effects.js.map +1 -0
- package/dist/tools/index.d.ts +32 -0
- package/dist/tools/index.js +23 -0
- package/dist/tools/index.js.map +1 -0
- package/package.json +56 -0
- package/scripts/check-deps.js +39 -0
- package/src/handlers/capcut.ts +245 -0
- package/src/handlers/editing.ts +260 -0
- package/src/handlers/index.ts +34 -0
- package/src/handlers/post-production.ts +136 -0
- package/src/handlers/smart-screenshot.ts +86 -0
- package/src/handlers/tts.ts +103 -0
- package/src/handlers/video.ts +137 -0
- package/src/lib/dual-transport.ts +272 -0
- package/src/lib/logger.ts +59 -0
- package/src/lib/types.ts +25 -0
- package/src/schemas/capcut.ts +418 -0
- package/src/schemas/editing.ts +476 -0
- package/src/schemas/index.ts +15 -0
- package/src/schemas/post-production.ts +273 -0
- package/src/schemas/smart-screenshot.ts +122 -0
- package/src/schemas/tts.ts +197 -0
- package/src/schemas/video.ts +211 -0
- package/src/server.test.ts +99 -0
- package/src/server.ts +289 -0
- package/src/tools/engine/audio-mixer.ts +244 -0
- package/src/tools/engine/audio.ts +115 -0
- package/src/tools/engine/beat-sync.ts +356 -0
- package/src/tools/engine/capture.ts +360 -0
- package/src/tools/engine/chroma-key.ts +202 -0
- package/src/tools/engine/concat.ts +242 -0
- package/src/tools/engine/cursor.ts +222 -0
- package/src/tools/engine/easing.ts +120 -0
- package/src/tools/engine/editing.ts +809 -0
- package/src/tools/engine/encoder.ts +208 -0
- package/src/tools/engine/index.ts +33 -0
- package/src/tools/engine/lut-presets.ts +235 -0
- package/src/tools/engine/narrated-video.ts +267 -0
- package/src/tools/engine/scenes.ts +309 -0
- package/src/tools/engine/smart-screenshot.ts +923 -0
- package/src/tools/engine/social-format.ts +146 -0
- package/src/tools/engine/template-renderer.ts +294 -0
- package/src/tools/engine/templates.ts +370 -0
- package/src/tools/engine/text-animations.ts +282 -0
- package/src/tools/engine/text-overlay.ts +143 -0
- package/src/tools/engine/tts.ts +284 -0
- package/src/tools/engine/types.ts +191 -0
- package/src/tools/engine/voice-effects.ts +258 -0
- package/src/tools/index.ts +67 -0
- package/tsconfig.json +19 -0
- package/vitest.config.ts +7 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Video concatenation engine — merge multiple clips with cinematic transitions
|
|
3
|
+
*/
|
|
4
|
+
import { execFile } from 'child_process';
|
|
5
|
+
import * as fs from 'fs';
|
|
6
|
+
import * as path from 'path';
|
|
7
|
+
import { logger } from '../../lib/logger.js';
|
|
8
|
+
import { getMediaDuration } from './audio.js';
|
|
9
|
+
// ─── Available Transitions ──────────────────────────────────────────
|
|
10
|
+
export const TRANSITIONS = [
|
|
11
|
+
'fade', 'fadeblack', 'fadewhite', 'dissolve',
|
|
12
|
+
'wipeleft', 'wiperight', 'wipeup', 'wipedown',
|
|
13
|
+
'slideleft', 'slideright', 'slideup', 'slidedown',
|
|
14
|
+
'smoothleft', 'smoothright', 'smoothup', 'smoothdown',
|
|
15
|
+
'circlecrop', 'circleopen', 'circleclose',
|
|
16
|
+
'rectcrop', 'vertopen', 'vertclose', 'horzopen', 'horzclose',
|
|
17
|
+
'diagtl', 'diagtr', 'diagbl', 'diagbr',
|
|
18
|
+
'hlslice', 'hrslice', 'vuslice', 'vdslice',
|
|
19
|
+
'radial', 'pixelize',
|
|
20
|
+
];
|
|
21
|
+
export async function concatenateVideos(config) {
|
|
22
|
+
const { clips, outputPath, transition = 'fade', transitionDuration = 1, targetWidth = 1920, targetHeight = 1080, targetFps = 60, } = config;
|
|
23
|
+
if (clips.length === 0)
|
|
24
|
+
throw new Error('No clips provided');
|
|
25
|
+
if (clips.length === 1) {
|
|
26
|
+
fs.copyFileSync(clips[0].path, outputPath);
|
|
27
|
+
return outputPath;
|
|
28
|
+
}
|
|
29
|
+
// Verify all clips exist
|
|
30
|
+
for (const clip of clips) {
|
|
31
|
+
if (!fs.existsSync(clip.path))
|
|
32
|
+
throw new Error(`Clip not found: ${clip.path}`);
|
|
33
|
+
}
|
|
34
|
+
// Get durations for each clip
|
|
35
|
+
const durations = [];
|
|
36
|
+
for (const clip of clips) {
|
|
37
|
+
let dur = await getMediaDuration(clip.path);
|
|
38
|
+
if (clip.trimStart)
|
|
39
|
+
dur -= clip.trimStart;
|
|
40
|
+
if (clip.trimEnd)
|
|
41
|
+
dur = Math.min(dur, clip.trimEnd - (clip.trimStart ?? 0));
|
|
42
|
+
durations.push(dur);
|
|
43
|
+
}
|
|
44
|
+
logger.info(`Concatenating ${clips.length} clips (${durations.map(d => d.toFixed(1) + 's').join(' + ')}) with ${transition} transition`);
|
|
45
|
+
const inputs = [];
|
|
46
|
+
const filterParts = [];
|
|
47
|
+
// Add inputs
|
|
48
|
+
for (const clip of clips) {
|
|
49
|
+
if (clip.trimStart !== undefined || clip.trimEnd !== undefined) {
|
|
50
|
+
if (clip.trimStart)
|
|
51
|
+
inputs.push('-ss', String(clip.trimStart));
|
|
52
|
+
if (clip.trimEnd)
|
|
53
|
+
inputs.push('-to', String(clip.trimEnd));
|
|
54
|
+
}
|
|
55
|
+
inputs.push('-i', clip.path);
|
|
56
|
+
}
|
|
57
|
+
// Normalize all inputs to same resolution and fps
|
|
58
|
+
for (let i = 0; i < clips.length; i++) {
|
|
59
|
+
filterParts.push(`[${i}:v]scale=${targetWidth}:${targetHeight}:force_original_aspect_ratio=decrease,` +
|
|
60
|
+
`pad=${targetWidth}:${targetHeight}:(ow-iw)/2:(oh-ih)/2:color=black,` +
|
|
61
|
+
`setsar=1,fps=${targetFps}[v${i}]`);
|
|
62
|
+
}
|
|
63
|
+
// Chain xfade filters with correct offset calculation
|
|
64
|
+
let cumulativeDuration = durations[0];
|
|
65
|
+
let prevLabel = 'v0';
|
|
66
|
+
for (let i = 1; i < clips.length; i++) {
|
|
67
|
+
const offset = Math.max(0, cumulativeDuration - transitionDuration);
|
|
68
|
+
const outLabel = i === clips.length - 1 ? 'vout' : `xf${i}`;
|
|
69
|
+
filterParts.push(`[${prevLabel}][v${i}]xfade=transition=${transition}:duration=${transitionDuration}:offset=${offset.toFixed(3)}[${outLabel}]`);
|
|
70
|
+
cumulativeDuration += durations[i] - transitionDuration;
|
|
71
|
+
prevLabel = outLabel;
|
|
72
|
+
}
|
|
73
|
+
// Ensure output dir exists
|
|
74
|
+
const outDir = path.dirname(outputPath);
|
|
75
|
+
if (!fs.existsSync(outDir))
|
|
76
|
+
fs.mkdirSync(outDir, { recursive: true });
|
|
77
|
+
const args = [
|
|
78
|
+
'-y',
|
|
79
|
+
...inputs,
|
|
80
|
+
'-filter_complex', filterParts.join(';'),
|
|
81
|
+
'-map', '[vout]',
|
|
82
|
+
'-c:v', 'libx264',
|
|
83
|
+
'-crf', '18',
|
|
84
|
+
'-preset', 'medium',
|
|
85
|
+
'-pix_fmt', 'yuv420p',
|
|
86
|
+
'-movflags', '+faststart',
|
|
87
|
+
outputPath,
|
|
88
|
+
];
|
|
89
|
+
await runFfmpeg(args);
|
|
90
|
+
const stats = fs.statSync(outputPath);
|
|
91
|
+
logger.info(`Concatenated: ${outputPath} (${(stats.size / 1024 / 1024).toFixed(2)} MB)`);
|
|
92
|
+
return outputPath;
|
|
93
|
+
}
|
|
94
|
+
export async function generateIntro(config) {
|
|
95
|
+
const { text, subtitle, duration = 3, backgroundColor = '#0a0a0a', textColor = 'white', width = 1920, height = 1080, fps = 60, outputPath, } = config;
|
|
96
|
+
const outDir = path.dirname(outputPath);
|
|
97
|
+
if (!fs.existsSync(outDir))
|
|
98
|
+
fs.mkdirSync(outDir, { recursive: true });
|
|
99
|
+
// Find a usable font
|
|
100
|
+
const fontPath = await findFont();
|
|
101
|
+
// Build drawtext filter with fade animation
|
|
102
|
+
const escapedText = text.replace(/'/g, "\\\\'").replace(/:/g, '\\:');
|
|
103
|
+
let vf = `drawtext=text='${escapedText}':fontfile='${fontPath}':fontsize=72:fontcolor=${textColor}:x=(w-text_w)/2:y=(h-text_h)/2-40:alpha='if(lt(t\\,0.8)\\,t/0.8\\,if(gt(t\\,${duration - 0.8})\\,(${duration}-t)/0.8\\,1))'`;
|
|
104
|
+
if (subtitle) {
|
|
105
|
+
const escapedSub = subtitle.replace(/'/g, "\\\\'").replace(/:/g, '\\:');
|
|
106
|
+
vf += `,drawtext=text='${escapedSub}':fontfile='${fontPath}':fontsize=36:fontcolor=${textColor}@0.7:x=(w-text_w)/2:y=(h-text_h)/2+40:alpha='if(lt(t\\,1.2)\\,0\\,if(lt(t\\,2)\\,(t-1.2)/0.8\\,if(gt(t\\,${duration - 0.8})\\,(${duration}-t)/0.8\\,1)))'`;
|
|
107
|
+
}
|
|
108
|
+
const args = [
|
|
109
|
+
'-y',
|
|
110
|
+
'-f', 'lavfi',
|
|
111
|
+
'-i', `color=c=${backgroundColor}:s=${width}x${height}:d=${duration}:r=${fps}`,
|
|
112
|
+
'-vf', vf,
|
|
113
|
+
'-c:v', 'libx264',
|
|
114
|
+
'-crf', '18',
|
|
115
|
+
'-pix_fmt', 'yuv420p',
|
|
116
|
+
'-movflags', '+faststart',
|
|
117
|
+
outputPath,
|
|
118
|
+
];
|
|
119
|
+
await runFfmpeg(args);
|
|
120
|
+
logger.info(`Intro generated: ${outputPath}`);
|
|
121
|
+
return outputPath;
|
|
122
|
+
}
|
|
123
|
+
// ─── Helpers ────────────────────────────────────────────────────────
|
|
124
|
+
async function findFont() {
|
|
125
|
+
const candidates = [
|
|
126
|
+
'/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf',
|
|
127
|
+
'/usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf',
|
|
128
|
+
'/usr/share/fonts/truetype/ubuntu/Ubuntu-Bold.ttf',
|
|
129
|
+
'/usr/share/fonts/truetype/freefont/FreeSansBold.ttf',
|
|
130
|
+
];
|
|
131
|
+
for (const f of candidates) {
|
|
132
|
+
if (fs.existsSync(f))
|
|
133
|
+
return f;
|
|
134
|
+
}
|
|
135
|
+
return '/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf';
|
|
136
|
+
}
|
|
137
|
+
function runFfmpeg(args) {
|
|
138
|
+
return new Promise((resolve, reject) => {
|
|
139
|
+
execFile('ffmpeg', args, { maxBuffer: 50 * 1024 * 1024 }, (error, stdout, stderr) => {
|
|
140
|
+
if (error) {
|
|
141
|
+
logger.error(`ffmpeg failed: ${stderr}`);
|
|
142
|
+
reject(new Error(`ffmpeg failed: ${stderr || error.message}`));
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
resolve(stdout);
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=concat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"concat.js","sourceRoot":"","sources":["../../../src/tools/engine/concat.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cursor simulation — injects a visible, smooth cursor into the page
|
|
3
|
+
* Uses Bézier curves for natural-looking mouse movement
|
|
4
|
+
*/
|
|
5
|
+
import type { Page } from 'playwright';
|
|
6
|
+
import type { CursorConfig } from './types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Inject a visible cursor overlay into the page
|
|
9
|
+
*/
|
|
10
|
+
export declare function injectCursor(page: Page, config?: Partial<CursorConfig>): Promise<void>;
|
|
11
|
+
/**
|
|
12
|
+
* Move cursor to a specific position with smooth Bézier interpolation
|
|
13
|
+
*/
|
|
14
|
+
export declare function moveCursor(page: Page, targetX: number, targetY: number, duration?: number, fps?: number): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Move cursor to a CSS selector's center
|
|
17
|
+
*/
|
|
18
|
+
export declare function moveCursorToElement(page: Page, selector: string, duration?: number, fps?: number): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* Animate a click effect at current cursor position
|
|
21
|
+
*/
|
|
22
|
+
export declare function animateClick(page: Page): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Hide cursor (move off-screen)
|
|
25
|
+
*/
|
|
26
|
+
export declare function hideCursor(page: Page): Promise<void>;
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cursor simulation — injects a visible, smooth cursor into the page
|
|
3
|
+
* Uses Bézier curves for natural-looking mouse movement
|
|
4
|
+
*/
|
|
5
|
+
const DEFAULT_CURSOR = {
|
|
6
|
+
enabled: true,
|
|
7
|
+
style: 'dot',
|
|
8
|
+
color: 'rgba(255, 255, 255, 0.9)',
|
|
9
|
+
size: 20,
|
|
10
|
+
clickAnimation: true,
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Inject a visible cursor overlay into the page
|
|
14
|
+
*/
|
|
15
|
+
export async function injectCursor(page, config = {}) {
|
|
16
|
+
const opts = { ...DEFAULT_CURSOR, ...config };
|
|
17
|
+
if (!opts.enabled)
|
|
18
|
+
return;
|
|
19
|
+
await page.evaluate(({ style, color, size, clickAnimation }) => {
|
|
20
|
+
// Create cursor element
|
|
21
|
+
const cursor = document.createElement('div');
|
|
22
|
+
cursor.id = '__cinema-cursor';
|
|
23
|
+
const isArrow = style === 'arrow' || style === 'pointer';
|
|
24
|
+
if (isArrow) {
|
|
25
|
+
// SVG arrow cursor
|
|
26
|
+
cursor.innerHTML = `<svg width="${size}" height="${size}" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
27
|
+
<path d="M5 3L19 12L12 13L9 20L5 3Z" fill="${color}" stroke="rgba(0,0,0,0.4)" stroke-width="1.5"/>
|
|
28
|
+
</svg>`;
|
|
29
|
+
Object.assign(cursor.style, {
|
|
30
|
+
position: 'fixed',
|
|
31
|
+
zIndex: '2147483647',
|
|
32
|
+
pointerEvents: 'none',
|
|
33
|
+
left: '-100px',
|
|
34
|
+
top: '-100px',
|
|
35
|
+
transition: 'none',
|
|
36
|
+
filter: 'drop-shadow(0 2px 4px rgba(0,0,0,0.3))',
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
// Dot cursor
|
|
41
|
+
Object.assign(cursor.style, {
|
|
42
|
+
position: 'fixed',
|
|
43
|
+
zIndex: '2147483647',
|
|
44
|
+
pointerEvents: 'none',
|
|
45
|
+
width: `${size}px`,
|
|
46
|
+
height: `${size}px`,
|
|
47
|
+
borderRadius: '50%',
|
|
48
|
+
backgroundColor: color,
|
|
49
|
+
border: '2px solid rgba(0,0,0,0.2)',
|
|
50
|
+
boxShadow: '0 0 12px rgba(0,0,0,0.15), 0 2px 8px rgba(0,0,0,0.1)',
|
|
51
|
+
left: '-100px',
|
|
52
|
+
top: '-100px',
|
|
53
|
+
transform: 'translate(-50%, -50%)',
|
|
54
|
+
transition: 'none',
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
document.body.appendChild(cursor);
|
|
58
|
+
// Click animation ring
|
|
59
|
+
if (clickAnimation) {
|
|
60
|
+
const ring = document.createElement('div');
|
|
61
|
+
ring.id = '__cinema-cursor-ring';
|
|
62
|
+
Object.assign(ring.style, {
|
|
63
|
+
position: 'fixed',
|
|
64
|
+
zIndex: '2147483646',
|
|
65
|
+
pointerEvents: 'none',
|
|
66
|
+
width: `${size * 2.5}px`,
|
|
67
|
+
height: `${size * 2.5}px`,
|
|
68
|
+
borderRadius: '50%',
|
|
69
|
+
border: `2px solid ${color}`,
|
|
70
|
+
left: '-100px',
|
|
71
|
+
top: '-100px',
|
|
72
|
+
transform: 'translate(-50%, -50%) scale(0)',
|
|
73
|
+
opacity: '0',
|
|
74
|
+
transition: 'none',
|
|
75
|
+
});
|
|
76
|
+
document.body.appendChild(ring);
|
|
77
|
+
}
|
|
78
|
+
// Store config on window for later use
|
|
79
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
80
|
+
window.__cinemaCursorConfig = { style, color, size, clickAnimation };
|
|
81
|
+
}, opts);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Move cursor to a specific position with smooth Bézier interpolation
|
|
85
|
+
*/
|
|
86
|
+
export async function moveCursor(page, targetX, targetY, duration = 800, fps = 60) {
|
|
87
|
+
const frames = Math.max(1, Math.ceil((duration / 1000) * fps));
|
|
88
|
+
// Get current cursor position
|
|
89
|
+
const startPos = await page.evaluate(() => {
|
|
90
|
+
const cursor = document.getElementById('__cinema-cursor');
|
|
91
|
+
if (!cursor)
|
|
92
|
+
return { x: 0, y: 0 };
|
|
93
|
+
return {
|
|
94
|
+
x: parseFloat(cursor.style.left) || 0,
|
|
95
|
+
y: parseFloat(cursor.style.top) || 0,
|
|
96
|
+
};
|
|
97
|
+
});
|
|
98
|
+
// Generate Bézier control points for natural movement
|
|
99
|
+
const dx = targetX - startPos.x;
|
|
100
|
+
const dy = targetY - startPos.y;
|
|
101
|
+
const cp1x = startPos.x + dx * 0.3 + (Math.random() - 0.5) * Math.abs(dx) * 0.2;
|
|
102
|
+
const cp1y = startPos.y + dy * 0.1 + (Math.random() - 0.5) * Math.abs(dy) * 0.3;
|
|
103
|
+
const cp2x = startPos.x + dx * 0.7 + (Math.random() - 0.5) * Math.abs(dx) * 0.15;
|
|
104
|
+
const cp2y = startPos.y + dy * 0.9 + (Math.random() - 0.5) * Math.abs(dy) * 0.2;
|
|
105
|
+
// Animate through Bézier curve
|
|
106
|
+
for (let i = 0; i <= frames; i++) {
|
|
107
|
+
const t = i / frames;
|
|
108
|
+
// Ease the t parameter for acceleration/deceleration
|
|
109
|
+
const et = t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
|
|
110
|
+
// Cubic Bézier
|
|
111
|
+
const mt = 1 - et;
|
|
112
|
+
const x = mt * mt * mt * startPos.x +
|
|
113
|
+
3 * mt * mt * et * cp1x +
|
|
114
|
+
3 * mt * et * et * cp2x +
|
|
115
|
+
et * et * et * targetX;
|
|
116
|
+
const y = mt * mt * mt * startPos.y +
|
|
117
|
+
3 * mt * mt * et * cp1y +
|
|
118
|
+
3 * mt * et * et * cp2y +
|
|
119
|
+
et * et * et * targetY;
|
|
120
|
+
await page.evaluate(({ x, y }) => {
|
|
121
|
+
const cursor = document.getElementById('__cinema-cursor');
|
|
122
|
+
if (cursor) {
|
|
123
|
+
cursor.style.left = `${x}px`;
|
|
124
|
+
cursor.style.top = `${y}px`;
|
|
125
|
+
}
|
|
126
|
+
}, { x: Math.round(x), y: Math.round(y) });
|
|
127
|
+
// Also move the actual mouse for hover effects
|
|
128
|
+
await page.mouse.move(Math.round(x), Math.round(y));
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Move cursor to a CSS selector's center
|
|
133
|
+
*/
|
|
134
|
+
export async function moveCursorToElement(page, selector, duration = 800, fps = 60) {
|
|
135
|
+
const pos = await page.evaluate((sel) => {
|
|
136
|
+
const el = document.querySelector(sel);
|
|
137
|
+
if (!el)
|
|
138
|
+
return null;
|
|
139
|
+
const rect = el.getBoundingClientRect();
|
|
140
|
+
return {
|
|
141
|
+
x: rect.left + rect.width / 2,
|
|
142
|
+
y: rect.top + rect.height / 2,
|
|
143
|
+
};
|
|
144
|
+
}, selector);
|
|
145
|
+
if (pos) {
|
|
146
|
+
await moveCursor(page, pos.x, pos.y, duration, fps);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Animate a click effect at current cursor position
|
|
151
|
+
*/
|
|
152
|
+
export async function animateClick(page) {
|
|
153
|
+
await page.evaluate(() => {
|
|
154
|
+
const ring = document.getElementById('__cinema-cursor-ring');
|
|
155
|
+
const cursor = document.getElementById('__cinema-cursor');
|
|
156
|
+
if (!ring || !cursor)
|
|
157
|
+
return;
|
|
158
|
+
ring.style.left = cursor.style.left;
|
|
159
|
+
ring.style.top = cursor.style.top;
|
|
160
|
+
ring.style.transition = 'transform 0.4s ease-out, opacity 0.4s ease-out';
|
|
161
|
+
ring.style.transform = 'translate(-50%, -50%) scale(0)';
|
|
162
|
+
ring.style.opacity = '1';
|
|
163
|
+
// Trigger animation
|
|
164
|
+
requestAnimationFrame(() => {
|
|
165
|
+
ring.style.transform = 'translate(-50%, -50%) scale(1)';
|
|
166
|
+
ring.style.opacity = '0';
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
// Wait for animation
|
|
170
|
+
await new Promise((r) => setTimeout(r, 450));
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Hide cursor (move off-screen)
|
|
174
|
+
*/
|
|
175
|
+
export async function hideCursor(page) {
|
|
176
|
+
await page.evaluate(() => {
|
|
177
|
+
const cursor = document.getElementById('__cinema-cursor');
|
|
178
|
+
const ring = document.getElementById('__cinema-cursor-ring');
|
|
179
|
+
if (cursor)
|
|
180
|
+
cursor.style.left = '-100px';
|
|
181
|
+
if (ring)
|
|
182
|
+
ring.style.left = '-100px';
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
//# sourceMappingURL=cursor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cursor.js","sourceRoot":"","sources":["../../../src/tools/engine/cursor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cinema-grade easing functions for smooth scroll animations
|
|
3
|
+
* All functions: t ∈ [0,1] → output ∈ [0,1]
|
|
4
|
+
*/
|
|
5
|
+
import type { EasingName } from './types.js';
|
|
6
|
+
declare const EASINGS: Record<EasingName, (t: number) => number>;
|
|
7
|
+
/**
|
|
8
|
+
* Get an easing function by name
|
|
9
|
+
*/
|
|
10
|
+
export declare function getEasing(name: EasingName): (t: number) => number;
|
|
11
|
+
/**
|
|
12
|
+
* Apply easing to a progress value and map to a range
|
|
13
|
+
*/
|
|
14
|
+
export declare function applyEasing(progress: number, totalDistance: number, easingName?: EasingName): number;
|
|
15
|
+
export { EASINGS };
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cinema-grade easing functions for smooth scroll animations
|
|
3
|
+
* All functions: t ∈ [0,1] → output ∈ [0,1]
|
|
4
|
+
*/
|
|
5
|
+
// ─── Core Easing Functions ──────────────────────────────────────────
|
|
6
|
+
const linear = (t) => t;
|
|
7
|
+
const easeInQuad = (t) => t * t;
|
|
8
|
+
const easeOutQuad = (t) => t * (2 - t);
|
|
9
|
+
const easeInOutQuad = (t) => t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
|
|
10
|
+
const easeInCubic = (t) => t * t * t;
|
|
11
|
+
const easeOutCubic = (t) => (--t) * t * t + 1;
|
|
12
|
+
const easeInOutCubic = (t) => t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
|
|
13
|
+
const easeInQuart = (t) => t * t * t * t;
|
|
14
|
+
const easeOutQuart = (t) => 1 - (--t) * t * t * t;
|
|
15
|
+
const easeInOutQuart = (t) => t < 0.5 ? 8 * t * t * t * t : 1 - Math.pow(-2 * t + 2, 4) / 2;
|
|
16
|
+
const easeInQuint = (t) => t * t * t * t * t;
|
|
17
|
+
const easeOutQuint = (t) => 1 + (--t) * t * t * t * t;
|
|
18
|
+
const easeInOutQuint = (t) => t < 0.5 ? 16 * t * t * t * t * t : 1 - Math.pow(-2 * t + 2, 5) / 2;
|
|
19
|
+
const easeInOutSine = (t) => -(Math.cos(Math.PI * t) - 1) / 2;
|
|
20
|
+
/**
|
|
21
|
+
* Cinematic easing: slow start (15%), smooth cruise (70%), slow end (15%)
|
|
22
|
+
* Uses quintic in/out for dramatic deceleration at edges
|
|
23
|
+
*/
|
|
24
|
+
const cinematic = (t) => {
|
|
25
|
+
if (t < 0.15) {
|
|
26
|
+
// Slow ease-in (quintic)
|
|
27
|
+
const local = t / 0.15;
|
|
28
|
+
return 0.15 * (local * local * local);
|
|
29
|
+
}
|
|
30
|
+
else if (t > 0.85) {
|
|
31
|
+
// Slow ease-out (quintic)
|
|
32
|
+
const local = (t - 0.85) / 0.15;
|
|
33
|
+
return 0.85 + 0.15 * (1 - Math.pow(1 - local, 3));
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
// Linear cruise in the middle
|
|
37
|
+
const local = (t - 0.15) / 0.70;
|
|
38
|
+
return 0.15 + 0.70 * local;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Showcase easing: dramatic slow start, buttery cruise, elegant deceleration
|
|
43
|
+
* Designed specifically for portfolio showcase videos
|
|
44
|
+
*
|
|
45
|
+
* Distribution: 25% slow start → 50% smooth cruise → 25% slow end
|
|
46
|
+
* The cruise section uses easeInOutSine for a gentle wave-like motion
|
|
47
|
+
* that never feels rushed — perfect for long pages
|
|
48
|
+
*/
|
|
49
|
+
const showcase = (t) => {
|
|
50
|
+
if (t < 0.25) {
|
|
51
|
+
// Very slow ease-in (quintic for dramatic slowness)
|
|
52
|
+
const local = t / 0.25;
|
|
53
|
+
return 0.08 * easeInQuint(local);
|
|
54
|
+
}
|
|
55
|
+
else if (t > 0.75) {
|
|
56
|
+
// Very slow ease-out (quintic for elegant stop)
|
|
57
|
+
const local = (t - 0.75) / 0.25;
|
|
58
|
+
return 0.92 + 0.08 * easeOutQuint(local);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
// Smooth cruise in the middle — easeInOutSine for wave-like feel
|
|
62
|
+
const local = (t - 0.25) / 0.50;
|
|
63
|
+
return 0.08 + 0.84 * easeInOutSine(local);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
// ─── Easing Registry ────────────────────────────────────────────────
|
|
67
|
+
const EASINGS = {
|
|
68
|
+
linear,
|
|
69
|
+
easeInQuad,
|
|
70
|
+
easeOutQuad,
|
|
71
|
+
easeInOutQuad,
|
|
72
|
+
easeInCubic,
|
|
73
|
+
easeOutCubic,
|
|
74
|
+
easeInOutCubic,
|
|
75
|
+
easeInQuart,
|
|
76
|
+
easeOutQuart,
|
|
77
|
+
easeInOutQuart,
|
|
78
|
+
easeInQuint,
|
|
79
|
+
easeOutQuint,
|
|
80
|
+
easeInOutQuint,
|
|
81
|
+
easeInOutSine,
|
|
82
|
+
cinematic,
|
|
83
|
+
showcase,
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* Get an easing function by name
|
|
87
|
+
*/
|
|
88
|
+
export function getEasing(name) {
|
|
89
|
+
return EASINGS[name] ?? EASINGS.easeInOutCubic;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Apply easing to a progress value and map to a range
|
|
93
|
+
*/
|
|
94
|
+
export function applyEasing(progress, totalDistance, easingName = 'easeInOutCubic') {
|
|
95
|
+
const easingFn = getEasing(easingName);
|
|
96
|
+
const clamped = Math.max(0, Math.min(1, progress));
|
|
97
|
+
return Math.round(easingFn(clamped) * totalDistance);
|
|
98
|
+
}
|
|
99
|
+
export { EASINGS };
|
|
100
|
+
//# sourceMappingURL=easing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"easing.js","sourceRoot":"","sources":["../../../src/tools/engine/easing.ts"],"names":[],"mappings":"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"}
|