clipbait 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/README.md +24 -0
- package/index.js +101 -0
- package/package.json +10 -0
package/README.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# clipbait
|
|
2
|
+
|
|
3
|
+
Turn any video into short viral clips — and auto-clip live streams — from your terminal or an AI agent. Wraps the [Clipbait](https://clipbait.ai) API.
|
|
4
|
+
|
|
5
|
+
## Install / use
|
|
6
|
+
```bash
|
|
7
|
+
npx clipbait login <your_api_key> # get it at clipbait.ai → Me → Developers / API
|
|
8
|
+
npx clipbait generate "https://youtube.com/watch?v=..." --aspect 9:16 --max 9
|
|
9
|
+
npx clipbait status <jobId> # get finished clip URLs
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Commands
|
|
13
|
+
| Command | Description |
|
|
14
|
+
|---|---|
|
|
15
|
+
| `clipbait login <apiKey>` | Save your API key (`~/.clipbait.json`) |
|
|
16
|
+
| `clipbait generate <url> [--aspect 9:16] [--type talking_head] [--max 9]` | Generate clips |
|
|
17
|
+
| `clipbait status <jobId>` | Check a job + get clip URLs |
|
|
18
|
+
| `clipbait jobs` | List recent jobs |
|
|
19
|
+
| `clipbait live <twitchUrl> [--cadence 7]` | Start live auto-clipping (Pro) |
|
|
20
|
+
| `clipbait probe <url>` | Get a video's duration |
|
|
21
|
+
|
|
22
|
+
Auth via `CLIPBAIT_API_KEY` env var or `~/.clipbait.json`. Requires Node 18+.
|
|
23
|
+
|
|
24
|
+
Prefer MCP? Point your agent at `https://app.clipbait.ai/api/mcp/<your_api_key>`.
|
package/index.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// clipbait — CLI + agent tool. Generate viral clips from any video, from your
|
|
3
|
+
// terminal or an AI agent. Zero dependencies (Node 18+ built-in fetch).
|
|
4
|
+
//
|
|
5
|
+
// Auth: `clipbait login <cbk_live_...>` (saved to ~/.clipbait.json) or the
|
|
6
|
+
// CLIPBAIT_API_KEY env var. Get your key at clipbait.ai → Me → API key.
|
|
7
|
+
|
|
8
|
+
const fs = require("fs");
|
|
9
|
+
const os = require("os");
|
|
10
|
+
const path = require("path");
|
|
11
|
+
|
|
12
|
+
const CFG = path.join(os.homedir(), ".clipbait.json");
|
|
13
|
+
const BASE = (process.env.CLIPBAIT_API_URL || "https://app.clipbait.ai/api").replace(/\/$/, "");
|
|
14
|
+
|
|
15
|
+
function loadKey() {
|
|
16
|
+
if (process.env.CLIPBAIT_API_KEY) return process.env.CLIPBAIT_API_KEY;
|
|
17
|
+
try { return JSON.parse(fs.readFileSync(CFG, "utf8")).apiKey || null; } catch { return null; }
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async function api(method, pathname, body) {
|
|
21
|
+
const res = await fetch(BASE + pathname, {
|
|
22
|
+
method,
|
|
23
|
+
headers: { "X-API-Key": loadKey(), "Content-Type": "application/json" },
|
|
24
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
25
|
+
});
|
|
26
|
+
const text = await res.text();
|
|
27
|
+
let data; try { data = JSON.parse(text); } catch { data = text; }
|
|
28
|
+
if (!res.ok) throw new Error((data && (data.error || data.message)) || `HTTP ${res.status}`);
|
|
29
|
+
return data;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function parseFlags(args) {
|
|
33
|
+
const o = {}, rest = [];
|
|
34
|
+
for (let i = 0; i < args.length; i++) {
|
|
35
|
+
if (args[i].startsWith("--")) { o[args[i].slice(2)] = args[i + 1]; i++; }
|
|
36
|
+
else rest.push(args[i]);
|
|
37
|
+
}
|
|
38
|
+
return { o, rest };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const HELP = `clipbait — AI clip generation
|
|
42
|
+
|
|
43
|
+
clipbait login <apiKey> save your API key
|
|
44
|
+
clipbait generate <url> [--aspect 9:16] [--type talking_head] [--max 9]
|
|
45
|
+
clipbait status <jobId> check a job + get clip URLs
|
|
46
|
+
clipbait jobs list recent jobs
|
|
47
|
+
clipbait live <twitchUrl> [--cadence 7] start live auto-clipping (Pro)
|
|
48
|
+
clipbait probe <url> get a video's duration
|
|
49
|
+
|
|
50
|
+
Auth: CLIPBAIT_API_KEY env var or ~/.clipbait.json (via 'clipbait login').`;
|
|
51
|
+
|
|
52
|
+
(async () => {
|
|
53
|
+
const [cmd, ...args] = process.argv.slice(2);
|
|
54
|
+
try {
|
|
55
|
+
if (cmd === "login") {
|
|
56
|
+
const key = args[0];
|
|
57
|
+
if (!key) { console.error("Usage: clipbait login <cbk_live_...>"); process.exit(1); }
|
|
58
|
+
fs.writeFileSync(CFG, JSON.stringify({ apiKey: key }, null, 2));
|
|
59
|
+
console.log("✓ Saved API key to " + CFG);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
if (!cmd || cmd === "help" || cmd === "--help" || cmd === "-h") { console.log(HELP); return; }
|
|
63
|
+
if (!loadKey()) {
|
|
64
|
+
console.error("No API key. Run: clipbait login <key> (get it at clipbait.ai → Me → API key)");
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
67
|
+
const { o, rest } = parseFlags(args);
|
|
68
|
+
|
|
69
|
+
if (cmd === "generate") {
|
|
70
|
+
if (!rest[0]) { console.error("Usage: clipbait generate <videoUrl> [--aspect 9:16] [--type talking_head] [--max 9]"); process.exit(1); }
|
|
71
|
+
const d = await api("POST", "/clips/generate", {
|
|
72
|
+
videoUrl: rest[0], aspectRatio: o.aspect || "9:16",
|
|
73
|
+
contentType: o.type || "talking_head", maxClips: Number(o.max) || 9,
|
|
74
|
+
});
|
|
75
|
+
console.log("✓ Job started:", d.jobId, "\n clipbait status " + d.jobId);
|
|
76
|
+
} else if (cmd === "status") {
|
|
77
|
+
if (!rest[0]) { console.error("Usage: clipbait status <jobId>"); process.exit(1); }
|
|
78
|
+
const d = await api("GET", "/clips/status/" + rest[0]);
|
|
79
|
+
console.log(`Status: ${d.status} (${d.progress ?? 0}%)`);
|
|
80
|
+
(d.clips || []).forEach((c, i) => console.log(` #${i + 1} ${c.hook || ""} — ${c.url || "(rendering)"}`));
|
|
81
|
+
} else if (cmd === "jobs") {
|
|
82
|
+
const d = await api("GET", "/clips/jobs");
|
|
83
|
+
(d.jobs || d || []).slice(0, 15).forEach((j) =>
|
|
84
|
+
console.log(`${j._id} ${j.status} ${(j.clips || []).length} clips ${j.videoTitle || j.streamerName || ""}`));
|
|
85
|
+
} else if (cmd === "live") {
|
|
86
|
+
if (!rest[0]) { console.error("Usage: clipbait live <twitchUrl> [--cadence 7]"); process.exit(1); }
|
|
87
|
+
const d = await api("POST", "/live/start", { videoUrl: rest[0], cadenceMin: Number(o.cadence) || 7 });
|
|
88
|
+
console.log("✓ Live auto-clipping started:", d.liveSessionId || d.session?._id || "");
|
|
89
|
+
} else if (cmd === "probe") {
|
|
90
|
+
if (!rest[0]) { console.error("Usage: clipbait probe <url>"); process.exit(1); }
|
|
91
|
+
const d = await api("POST", "/clips/probe-url", { url: rest[0] });
|
|
92
|
+
console.log(d.durationSeconds != null ? `Duration: ${d.durationSeconds}s (~${Math.round(d.durationSeconds / 60)} min)` : "Duration unknown for this platform.");
|
|
93
|
+
} else {
|
|
94
|
+
console.error(`Unknown command: ${cmd}\n\n` + HELP);
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
} catch (e) {
|
|
98
|
+
console.error("Error:", e.message);
|
|
99
|
+
process.exit(1);
|
|
100
|
+
}
|
|
101
|
+
})();
|
package/package.json
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "clipbait",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Clipbait CLI — turn any video into viral clips, and auto-clip live streams, from your terminal or AI agent.",
|
|
5
|
+
"bin": { "clipbait": "index.js" },
|
|
6
|
+
"type": "commonjs",
|
|
7
|
+
"engines": { "node": ">=18" },
|
|
8
|
+
"keywords": ["clipbait", "clips", "video", "ai", "agent", "cli", "twitch", "shorts"],
|
|
9
|
+
"license": "MIT"
|
|
10
|
+
}
|