Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
# OpenAI Configuration
# Anthropic / Claude (pipeline brain: feature detection + script writing)
# When set, the pipeline runs the "smart" path; unset falls back to heuristics.
ANTHROPIC_API_KEY=your_anthropic_api_key_here
ANTHROPIC_MODEL=claude-opus-4-8

# OpenAI Configuration (legacy CLI path)
OPENAI_API_KEY=your_openai_api_key_here
OPENAI_MODEL=gpt-4-turbo-preview

# ElevenLabs Configuration
# ElevenLabs Configuration (voiceover synthesis)
ELEVENLABS_API_KEY=your_elevenlabs_api_key_here
ELEVENLABS_VOICE_ID=your_preferred_voice_id_here

# Motion graphics: set to 1 to use the Remotion backend (requires the
# optional @remotion/* deps + graphics/ project). Default uses the ffmpeg backend.
MKDEMO_REMOTION=0

# Puppeteer Configuration
PUPPETEER_HEADLESS=true
PUPPETEER_VIEWPORT_WIDTH=1920
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"start": "node apps/web/server.js",
"cli": "node src/index.js",
"setup": "node scripts/setup.js",
"pipeline": "node scripts/run-pipeline.js",
"test": "NODE_OPTIONS='--loader=./node_modules/mocha/lib/nodejs/esm-utils.js' mocha test/**/*.test.js --recursive",
"test:pipeline": "NODE_OPTIONS='--loader=./node_modules/mocha/lib/nodejs/esm-utils.js' mocha test/pipeline/**/*.test.js --recursive",
"test:watch": "NODE_OPTIONS='--loader=./node_modules/mocha/lib/nodejs/esm-utils.js' mocha test/**/*.test.js --recursive --watch",
Expand Down
55 changes: 55 additions & 0 deletions scripts/run-pipeline.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/usr/bin/env node
import 'dotenv/config';
import { randomUUID } from 'node:crypto';
import { runPipeline } from '../packages/core/index.js';

/**
* Local CLI runner for the makedemo pipeline brain — useful for testing the
* full crawl -> Claude features -> record -> script -> voiceover -> assemble
* flow without the web shell. The web app drives runPipeline(job, emit) the
* same way.
*
* node scripts/run-pipeline.js --url https://example.com \
* --clips ./a.mp4,./b.mp4 --song ./suno.mp3 --max-features 5
*/
function parseArgs(argv) {
const out = {};
for (let i = 0; i < argv.length; i++) {
const a = argv[i];
if (a.startsWith('--')) {
const key = a.slice(2);
const val = argv[i + 1] && !argv[i + 1].startsWith('--') ? argv[++i] : 'true';
out[key] = val;
}
}
return out;
}

const args = parseArgs(process.argv.slice(2));
if (!args.url) {
console.error('Usage: node scripts/run-pipeline.js --url <url> [--user <e> --password <p>] [--clips a.mp4,b.mp4] [--song suno.mp3] [--max-features 5] [--voice <id>]');
process.exit(1);
}

const job = {
id: randomUUID().slice(0, 8),
url: args.url,
credentials: args.user && args.password ? { user: args.user, password: args.password } : null,
maxFeatures: args['max-features'] ? Number(args['max-features']) : 5,
voice: args.voice || null,
clips: args.clips ? args.clips.split(',').map((s) => s.trim()).filter(Boolean) : [],
song: args.song || null,
};

const emit = (type, data) => {
if (type === 'log') console.log(` ${data.msg}`);
else if (type === 'stage') console.log(`[${data.stage}] ${data.status}${data.step ? ` ${data.step}/${data.total}` : ''}`);
else if (type === 'done') console.log(`\n✅ Done: output/${job.id}/${data.video}`);
else if (type === 'error') console.error(`❌ ${data.message}`);
};

console.log(`Job ${job.id} → ${job.url}`);
runPipeline(job, emit).catch((err) => {
console.error('Pipeline failed:', err);
process.exit(1);
});