vidjutsu 1.2.0 → 1.3.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 +21 -19
- package/dist/cli/index.mjs +554 -8
- package/dist/client.d.ts +3 -1
- package/dist/client.js +5 -1
- package/dist/distribution.d.ts +23 -0
- package/dist/distribution.js +56 -0
- package/dist/index.d.ts +2 -0
- package/dist/jobs.d.ts +14 -0
- package/dist/jobs.js +50 -0
- package/dist/methods.d.ts +64 -0
- package/dist/methods.js +96 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -26,14 +26,14 @@ import { createClient } from "vidjutsu";
|
|
|
26
26
|
|
|
27
27
|
const vj = createClient();
|
|
28
28
|
|
|
29
|
-
// Watch — AI analyzes a video and answers your prompt (
|
|
29
|
+
// Watch — AI analyzes a video and answers your prompt (50/day)
|
|
30
30
|
const { data: watch } = await vj.watchMedia({
|
|
31
31
|
mediaUrl: "https://cdn.example.com/video.mp4",
|
|
32
32
|
prompt: "Is the hook strong enough for fitness TikTok?",
|
|
33
33
|
});
|
|
34
34
|
console.log(watch.response);
|
|
35
35
|
|
|
36
|
-
// Extract — pull frames, audio, and metadata (
|
|
36
|
+
// Extract — pull frames, audio, and metadata (100/day)
|
|
37
37
|
const { data: extract } = await vj.extractMedia({
|
|
38
38
|
mediaUrl: "https://cdn.example.com/video.mp4",
|
|
39
39
|
frames: "auto",
|
|
@@ -41,13 +41,13 @@ const { data: extract } = await vj.extractMedia({
|
|
|
41
41
|
});
|
|
42
42
|
console.log(extract.frames, extract.metadata);
|
|
43
43
|
|
|
44
|
-
// Transcribe — speech-to-text with word-level timing (
|
|
44
|
+
// Transcribe — speech-to-text with word-level timing (30/day)
|
|
45
45
|
const { data: transcript } = await vj.transcribeMedia({
|
|
46
46
|
mediaUrl: "https://cdn.example.com/video.mp4",
|
|
47
47
|
});
|
|
48
48
|
console.log(transcript.transcript, transcript.words);
|
|
49
49
|
|
|
50
|
-
// Overlay — burn text onto video (
|
|
50
|
+
// Overlay — burn text onto video (50/day)
|
|
51
51
|
const { data: overlay } = await vj.createOverlay({
|
|
52
52
|
videoUrl: "https://cdn.example.com/video.mp4",
|
|
53
53
|
text: "Follow for more tips",
|
|
@@ -77,17 +77,19 @@ const vj = createClient({ baseUrl: "https://staging.api.vidjutsu.ai" });
|
|
|
77
77
|
|
|
78
78
|
## All methods
|
|
79
79
|
|
|
80
|
-
### Video intelligence (
|
|
80
|
+
### Video intelligence (metered)
|
|
81
81
|
|
|
82
|
-
|
|
83
|
-
|--------|---------|-------------|
|
|
84
|
-
| `watchMedia(body)` | 10 | AI watches a video/image and answers your prompt |
|
|
85
|
-
| `extractMedia(body)` | 5 | Extract frames, audio, and metadata from video |
|
|
86
|
-
| `transcribeMedia(body)` | 10 | Speech-to-text with word-level timing |
|
|
87
|
-
| `checkSpec(body)` | 5 | Validate a VidLang spec against rules |
|
|
88
|
-
| `createOverlay(body)` | 5 | Burn text overlay onto video |
|
|
82
|
+
Requires an active subscription. Each endpoint has its own daily rate limit (fixed window, resets 00:00 UTC). Hitting a limit returns HTTP 429 with a `retryAfter` hint.
|
|
89
83
|
|
|
90
|
-
|
|
84
|
+
| Method | Daily limit | Description |
|
|
85
|
+
|--------|-------------|-------------|
|
|
86
|
+
| `watchMedia(body)` | 50 / day | AI watches a video/image and answers your prompt |
|
|
87
|
+
| `extractMedia(body)` | 100 / day | Extract frames, audio, and metadata from video |
|
|
88
|
+
| `transcribeMedia(body)` | 30 / day | Speech-to-text with word-level timing |
|
|
89
|
+
| `checkSpec(body)` | 100 / day | Validate a VidLang spec against rules |
|
|
90
|
+
| `createOverlay(body)` | 50 / day | Burn text overlay onto video |
|
|
91
|
+
|
|
92
|
+
### Resources (unmetered)
|
|
91
93
|
|
|
92
94
|
| Method | Description |
|
|
93
95
|
|--------|-------------|
|
|
@@ -96,7 +98,6 @@ const vj = createClient({ baseUrl: "https://staging.api.vidjutsu.ai" });
|
|
|
96
98
|
| `createAsset(body)` / `updateAsset(body, query)` / `listOrGetAssets(query)` / `deleteAsset(query)` | Manage assets |
|
|
97
99
|
| `createReference(body)` / `updateReference(body, query)` / `listOrGetReferences(query)` / `deleteReference(query)` | Manage references |
|
|
98
100
|
| `uploadFile(body)` / `uploadFromUrl(body)` | Upload media to CDN |
|
|
99
|
-
| `getBalance()` | Check credit balance |
|
|
100
101
|
|
|
101
102
|
### Utilities (free)
|
|
102
103
|
|
|
@@ -115,17 +116,18 @@ const vj = createClient({ baseUrl: "https://staging.api.vidjutsu.ai" });
|
|
|
115
116
|
Every method returns the `openapi-fetch` response shape: `{ data, error, response }`. For endpoints not covered by convenience methods, use the raw client:
|
|
116
117
|
|
|
117
118
|
```ts
|
|
118
|
-
const { data, error } = await vj.api.GET("/v1/
|
|
119
|
+
const { data, error } = await vj.api.GET("/v1/usage");
|
|
119
120
|
const { data, error } = await vj.api.POST("/v1/watch", {
|
|
120
121
|
body: { mediaUrl: "...", prompt: "..." },
|
|
121
122
|
});
|
|
122
123
|
```
|
|
123
124
|
|
|
124
|
-
##
|
|
125
|
+
## Pricing & billing
|
|
125
126
|
|
|
126
|
-
- **$99/month** —
|
|
127
|
-
- **
|
|
128
|
-
-
|
|
127
|
+
- **$99/month flat** — full API access via Stripe, billed monthly, cancel anytime.
|
|
128
|
+
- **No credits, no metered billing, no top-ups** — usage is governed by per-endpoint daily rate limits (reset 00:00 UTC), not a credit balance.
|
|
129
|
+
- Hitting a daily limit returns **HTTP 429** with a `retryAfter` hint. Check remaining capacity with `getUsage()` or `GET /v1/usage`.
|
|
130
|
+
- `GET /v1/pricing` is the single source of truth for current price and limits.
|
|
129
131
|
|
|
130
132
|
## Links
|
|
131
133
|
|
package/dist/cli/index.mjs
CHANGED
|
@@ -2197,14 +2197,19 @@ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
|
|
|
2197
2197
|
import { join } from "path";
|
|
2198
2198
|
import { homedir } from "os";
|
|
2199
2199
|
function loadConfig() {
|
|
2200
|
+
const envApiUrl = process.env.VIDJUTSU_API_URL;
|
|
2201
|
+
const envApiKey = process.env.VIDJUTSU_API_KEY;
|
|
2200
2202
|
if (existsSync(CONFIG_FILE)) {
|
|
2201
2203
|
const raw = JSON.parse(readFileSync(CONFIG_FILE, "utf-8"));
|
|
2202
2204
|
if (!raw.apiUrl || raw.apiUrl.includes(".convex.site")) {
|
|
2203
2205
|
raw.apiUrl = DEFAULT_API_URL;
|
|
2204
2206
|
}
|
|
2205
|
-
return
|
|
2207
|
+
return {
|
|
2208
|
+
apiUrl: envApiUrl ?? raw.apiUrl,
|
|
2209
|
+
apiKey: envApiKey ?? raw.apiKey
|
|
2210
|
+
};
|
|
2206
2211
|
}
|
|
2207
|
-
return { apiUrl: DEFAULT_API_URL };
|
|
2212
|
+
return { apiUrl: envApiUrl ?? DEFAULT_API_URL, apiKey: envApiKey };
|
|
2208
2213
|
}
|
|
2209
2214
|
function saveConfig(config) {
|
|
2210
2215
|
if (!existsSync(CONFIG_DIR))
|
|
@@ -2237,7 +2242,7 @@ async function publicRequest(method, path, body) {
|
|
|
2237
2242
|
}
|
|
2238
2243
|
return json;
|
|
2239
2244
|
}
|
|
2240
|
-
async function apiRequest(method, path, body) {
|
|
2245
|
+
async function apiRequest(method, path, body, options = {}) {
|
|
2241
2246
|
const config = loadConfig();
|
|
2242
2247
|
if (!config.apiKey) {
|
|
2243
2248
|
throw new Error('Not authenticated. Run "vidjutsu auth --key <your_api_key>" first.');
|
|
@@ -2245,7 +2250,8 @@ async function apiRequest(method, path, body) {
|
|
|
2245
2250
|
const url = `${config.apiUrl}${path}`;
|
|
2246
2251
|
const headers = {
|
|
2247
2252
|
Authorization: `Bearer ${config.apiKey}`,
|
|
2248
|
-
"Content-Type": "application/json"
|
|
2253
|
+
"Content-Type": "application/json",
|
|
2254
|
+
...options.idempotencyKey ? { "Idempotency-Key": options.idempotencyKey } : {}
|
|
2249
2255
|
};
|
|
2250
2256
|
const res = await fetch(url, {
|
|
2251
2257
|
method,
|
|
@@ -2601,19 +2607,21 @@ var init_status = __esm(() => {
|
|
|
2601
2607
|
status_default = defineCommand({
|
|
2602
2608
|
meta: { name: "status", description: "Check resource status by ID" },
|
|
2603
2609
|
args: {
|
|
2604
|
-
id: { type: "positional", description: "Resource ID (acc_xxx, post_xxx, ref_xxx)", required: true }
|
|
2610
|
+
id: { type: "positional", description: "Resource ID (job_xxx, acc_xxx, post_xxx, ref_xxx)", required: true }
|
|
2605
2611
|
},
|
|
2606
2612
|
async run({ args }) {
|
|
2607
2613
|
const id = args.id;
|
|
2608
2614
|
let path;
|
|
2609
|
-
if (id.startsWith("
|
|
2615
|
+
if (id.startsWith("job_"))
|
|
2616
|
+
path = `/v1/distribution/jobs?id=${id}`;
|
|
2617
|
+
else if (id.startsWith("acc_"))
|
|
2610
2618
|
path = `/v1/accounts?id=${id}`;
|
|
2611
2619
|
else if (id.startsWith("post_"))
|
|
2612
2620
|
path = `/v1/posts?id=${id}`;
|
|
2613
2621
|
else if (id.startsWith("ref_"))
|
|
2614
2622
|
path = `/v1/references?id=${id}`;
|
|
2615
2623
|
else {
|
|
2616
|
-
console.error("Unknown ID prefix. Expected acc_, post_, or ref_");
|
|
2624
|
+
console.error("Unknown ID prefix. Expected job_, acc_, post_, or ref_");
|
|
2617
2625
|
process.exit(1);
|
|
2618
2626
|
}
|
|
2619
2627
|
const result = await apiRequest("GET", path);
|
|
@@ -2622,6 +2630,148 @@ var init_status = __esm(() => {
|
|
|
2622
2630
|
});
|
|
2623
2631
|
});
|
|
2624
2632
|
|
|
2633
|
+
// src/cli/commands/balance.ts
|
|
2634
|
+
var exports_balance = {};
|
|
2635
|
+
__export(exports_balance, {
|
|
2636
|
+
default: () => balance_default
|
|
2637
|
+
});
|
|
2638
|
+
function fmtTs(ms) {
|
|
2639
|
+
const d2 = new Date(ms);
|
|
2640
|
+
const pad = (n2) => String(n2).padStart(2, "0");
|
|
2641
|
+
return `${d2.getUTCFullYear()}-${pad(d2.getUTCMonth() + 1)}-${pad(d2.getUTCDate())} ${pad(d2.getUTCHours())}:${pad(d2.getUTCMinutes())} UTC`;
|
|
2642
|
+
}
|
|
2643
|
+
function fmtDelta(n2) {
|
|
2644
|
+
const s2 = n2 >= 0 ? `+${n2}` : String(n2);
|
|
2645
|
+
return s2.padStart(6);
|
|
2646
|
+
}
|
|
2647
|
+
var balance_default;
|
|
2648
|
+
var init_balance = __esm(() => {
|
|
2649
|
+
init_dist2();
|
|
2650
|
+
init_client();
|
|
2651
|
+
balance_default = defineCommand({
|
|
2652
|
+
meta: {
|
|
2653
|
+
name: "balance",
|
|
2654
|
+
description: "Show credit balance and recent ledger entries"
|
|
2655
|
+
},
|
|
2656
|
+
args: {
|
|
2657
|
+
json: {
|
|
2658
|
+
type: "boolean",
|
|
2659
|
+
description: "Emit raw JSON instead of a table",
|
|
2660
|
+
default: false
|
|
2661
|
+
}
|
|
2662
|
+
},
|
|
2663
|
+
async run({ args }) {
|
|
2664
|
+
const res = await apiRequest("GET", "/v1/balance");
|
|
2665
|
+
if (args.json) {
|
|
2666
|
+
console.log(JSON.stringify(res, null, 2));
|
|
2667
|
+
return;
|
|
2668
|
+
}
|
|
2669
|
+
console.log(`Balance: ${res.balance} credits`);
|
|
2670
|
+
if (!res.ledger || res.ledger.length === 0) {
|
|
2671
|
+
console.log(`
|
|
2672
|
+
No ledger entries yet.`);
|
|
2673
|
+
return;
|
|
2674
|
+
}
|
|
2675
|
+
console.log(`
|
|
2676
|
+
Recent ledger (newest first):`);
|
|
2677
|
+
for (const e2 of res.ledger) {
|
|
2678
|
+
const detail = e2.operationId ?? e2.note ?? "";
|
|
2679
|
+
console.log(` ${fmtDelta(e2.delta)} ${e2.reason.padEnd(7)} ${fmtTs(e2.createdAt)} ${detail}`);
|
|
2680
|
+
}
|
|
2681
|
+
}
|
|
2682
|
+
});
|
|
2683
|
+
});
|
|
2684
|
+
|
|
2685
|
+
// src/cli/commands/admin.ts
|
|
2686
|
+
var exports_admin = {};
|
|
2687
|
+
__export(exports_admin, {
|
|
2688
|
+
default: () => admin_default
|
|
2689
|
+
});
|
|
2690
|
+
import { spawnSync } from "node:child_process";
|
|
2691
|
+
var grant, admin_default;
|
|
2692
|
+
var init_admin = __esm(() => {
|
|
2693
|
+
init_dist2();
|
|
2694
|
+
grant = defineCommand({
|
|
2695
|
+
meta: {
|
|
2696
|
+
name: "grant",
|
|
2697
|
+
description: "Grant credits to a client (looked up by email or clientId). Runs the Convex mutation directly via 'npx convex run'."
|
|
2698
|
+
},
|
|
2699
|
+
args: {
|
|
2700
|
+
email: {
|
|
2701
|
+
type: "string",
|
|
2702
|
+
description: "Email of the client to grant credits to"
|
|
2703
|
+
},
|
|
2704
|
+
client: {
|
|
2705
|
+
type: "string",
|
|
2706
|
+
description: "clientId of the client to grant credits to"
|
|
2707
|
+
},
|
|
2708
|
+
amount: {
|
|
2709
|
+
type: "string",
|
|
2710
|
+
description: "Number of credits to grant (positive integer)",
|
|
2711
|
+
required: true
|
|
2712
|
+
},
|
|
2713
|
+
note: {
|
|
2714
|
+
type: "string",
|
|
2715
|
+
description: "Optional admin note recorded on the ledger row"
|
|
2716
|
+
},
|
|
2717
|
+
repo: {
|
|
2718
|
+
type: "string",
|
|
2719
|
+
description: "Path to the vidjutsu Convex repo where 'npx convex run' executes (defaults to cwd)"
|
|
2720
|
+
}
|
|
2721
|
+
},
|
|
2722
|
+
async run({ args }) {
|
|
2723
|
+
if (!args.email && !args.client) {
|
|
2724
|
+
console.error("Error: provide --email <e> or --client <clientId>");
|
|
2725
|
+
process.exit(1);
|
|
2726
|
+
}
|
|
2727
|
+
const amount = Number(args.amount);
|
|
2728
|
+
if (!Number.isInteger(amount) || amount <= 0) {
|
|
2729
|
+
console.error("Error: --amount must be a positive integer");
|
|
2730
|
+
process.exit(1);
|
|
2731
|
+
}
|
|
2732
|
+
const payload = { amount };
|
|
2733
|
+
if (args.email)
|
|
2734
|
+
payload.email = args.email;
|
|
2735
|
+
if (args.client)
|
|
2736
|
+
payload.clientId = args.client;
|
|
2737
|
+
if (args.note)
|
|
2738
|
+
payload.note = args.note;
|
|
2739
|
+
const cwd = args.repo ?? process.cwd();
|
|
2740
|
+
const cmdArgs = [
|
|
2741
|
+
"convex",
|
|
2742
|
+
"run",
|
|
2743
|
+
"services/machineClients:grantCreditsByLookup",
|
|
2744
|
+
JSON.stringify(payload)
|
|
2745
|
+
];
|
|
2746
|
+
const result = spawnSync("npx", cmdArgs, {
|
|
2747
|
+
cwd,
|
|
2748
|
+
encoding: "utf-8",
|
|
2749
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
2750
|
+
});
|
|
2751
|
+
if (result.error) {
|
|
2752
|
+
console.error("Error invoking npx convex:", result.error.message);
|
|
2753
|
+
process.exit(1);
|
|
2754
|
+
}
|
|
2755
|
+
if (result.stdout)
|
|
2756
|
+
process.stdout.write(result.stdout);
|
|
2757
|
+
if (result.stderr)
|
|
2758
|
+
process.stderr.write(result.stderr);
|
|
2759
|
+
if (result.status !== 0) {
|
|
2760
|
+
process.exit(result.status ?? 1);
|
|
2761
|
+
}
|
|
2762
|
+
}
|
|
2763
|
+
});
|
|
2764
|
+
admin_default = defineCommand({
|
|
2765
|
+
meta: {
|
|
2766
|
+
name: "admin",
|
|
2767
|
+
description: "Admin operations (credit grants, etc.)"
|
|
2768
|
+
},
|
|
2769
|
+
subCommands: {
|
|
2770
|
+
grant: () => grant
|
|
2771
|
+
}
|
|
2772
|
+
});
|
|
2773
|
+
});
|
|
2774
|
+
|
|
2625
2775
|
// src/cli/commands/version.ts
|
|
2626
2776
|
var exports_version = {};
|
|
2627
2777
|
__export(exports_version, {
|
|
@@ -2716,6 +2866,293 @@ var init_update = __esm(() => {
|
|
|
2716
2866
|
});
|
|
2717
2867
|
});
|
|
2718
2868
|
|
|
2869
|
+
// src/cli/commands/jobs.ts
|
|
2870
|
+
var exports_jobs = {};
|
|
2871
|
+
__export(exports_jobs, {
|
|
2872
|
+
default: () => jobs_default
|
|
2873
|
+
});
|
|
2874
|
+
async function getJob(jobId) {
|
|
2875
|
+
return await apiRequest("GET", `/v1/jobs?id=${encodeURIComponent(jobId)}`);
|
|
2876
|
+
}
|
|
2877
|
+
var jobs_default;
|
|
2878
|
+
var init_jobs = __esm(() => {
|
|
2879
|
+
init_dist2();
|
|
2880
|
+
init_client();
|
|
2881
|
+
jobs_default = defineCommand({
|
|
2882
|
+
meta: { name: "jobs", description: "Inspect durable VidJutsu media jobs" },
|
|
2883
|
+
subCommands: {
|
|
2884
|
+
get: defineCommand({
|
|
2885
|
+
meta: { name: "get", description: "Get a job" },
|
|
2886
|
+
args: {
|
|
2887
|
+
id: { type: "positional", description: "Job ID", required: true }
|
|
2888
|
+
},
|
|
2889
|
+
async run({ args }) {
|
|
2890
|
+
console.log(JSON.stringify(await getJob(args.id), null, 2));
|
|
2891
|
+
}
|
|
2892
|
+
}),
|
|
2893
|
+
wait: defineCommand({
|
|
2894
|
+
meta: { name: "wait", description: "Wait for a job to complete" },
|
|
2895
|
+
args: {
|
|
2896
|
+
id: { type: "positional", description: "Job ID", required: true },
|
|
2897
|
+
timeout: { type: "string", description: "Timeout in seconds", default: "600" },
|
|
2898
|
+
interval: { type: "string", description: "Poll interval in milliseconds", default: "1000" }
|
|
2899
|
+
},
|
|
2900
|
+
async run({ args }) {
|
|
2901
|
+
const deadline = Date.now() + Number(args.timeout) * 1000;
|
|
2902
|
+
while (true) {
|
|
2903
|
+
const job = await getJob(args.id);
|
|
2904
|
+
if (job?.status === "completed") {
|
|
2905
|
+
console.log(JSON.stringify(job, null, 2));
|
|
2906
|
+
return;
|
|
2907
|
+
}
|
|
2908
|
+
if (job?.status === "failed" || job?.status === "cancelled") {
|
|
2909
|
+
throw new Error(job.error?.message ?? `Job ${job.status}`);
|
|
2910
|
+
}
|
|
2911
|
+
if (Date.now() >= deadline)
|
|
2912
|
+
throw new Error(`Timed out waiting for ${args.id}`);
|
|
2913
|
+
await new Promise((resolve) => setTimeout(resolve, Number(args.interval)));
|
|
2914
|
+
}
|
|
2915
|
+
}
|
|
2916
|
+
})
|
|
2917
|
+
}
|
|
2918
|
+
});
|
|
2919
|
+
});
|
|
2920
|
+
|
|
2921
|
+
// src/cli/commands/clone.ts
|
|
2922
|
+
var exports_clone = {};
|
|
2923
|
+
__export(exports_clone, {
|
|
2924
|
+
default: () => clone_default
|
|
2925
|
+
});
|
|
2926
|
+
function validateModel(model) {
|
|
2927
|
+
if (model === undefined)
|
|
2928
|
+
return;
|
|
2929
|
+
if (!VALID_MODELS.includes(model)) {
|
|
2930
|
+
throw new Error(`--model must be one of: ${VALID_MODELS.join(", ")}`);
|
|
2931
|
+
}
|
|
2932
|
+
return model;
|
|
2933
|
+
}
|
|
2934
|
+
function isCharacterId(value) {
|
|
2935
|
+
return value.startsWith("char_");
|
|
2936
|
+
}
|
|
2937
|
+
function characterRef(value) {
|
|
2938
|
+
return isCharacterId(value) ? { characterId: value } : { characterImageUrl: value };
|
|
2939
|
+
}
|
|
2940
|
+
async function pollCloneVideo(id, { intervalMs = 3000, timeoutMs = 600000 } = {}) {
|
|
2941
|
+
const deadline = Date.now() + timeoutMs;
|
|
2942
|
+
while (true) {
|
|
2943
|
+
const status = await apiRequest("GET", `/v1/clones/video/${encodeURIComponent(id)}`);
|
|
2944
|
+
if (status.status === "completed")
|
|
2945
|
+
return status;
|
|
2946
|
+
if (status.status === "failed")
|
|
2947
|
+
throw new Error(status.error ?? `Clone video ${id} failed`);
|
|
2948
|
+
if (Date.now() >= deadline)
|
|
2949
|
+
throw new Error(`Timed out waiting for clone video ${id}`);
|
|
2950
|
+
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
2951
|
+
}
|
|
2952
|
+
}
|
|
2953
|
+
var VALID_MODELS, clone_default;
|
|
2954
|
+
var init_clone = __esm(() => {
|
|
2955
|
+
init_dist2();
|
|
2956
|
+
init_client();
|
|
2957
|
+
VALID_MODELS = ["kling", "seedance"];
|
|
2958
|
+
clone_default = defineCommand({
|
|
2959
|
+
meta: {
|
|
2960
|
+
name: "clone",
|
|
2961
|
+
description: "Clone a source video's motion onto a new character. About 5 minutes end to end for the full chain. " + "Kling motion control is the default model; output is 480p 9:16. Source clips are capped at 15 seconds. " + "Each step below is metered per call."
|
|
2962
|
+
},
|
|
2963
|
+
subCommands: {
|
|
2964
|
+
check: defineCommand({
|
|
2965
|
+
meta: {
|
|
2966
|
+
name: "check",
|
|
2967
|
+
description: "Evaluate whether a source video can be cloned reliably. Metered per call. " + "Exits nonzero when the verdict is weak."
|
|
2968
|
+
},
|
|
2969
|
+
args: {
|
|
2970
|
+
videoUrl: { type: "positional", description: "Public HTTPS URL of the source video", required: true },
|
|
2971
|
+
context: { type: "string", description: "Optional context about the intended clone" }
|
|
2972
|
+
},
|
|
2973
|
+
async run({ args }) {
|
|
2974
|
+
const result = await apiRequest("POST", "/v1/clones/check", {
|
|
2975
|
+
videoUrl: args.videoUrl,
|
|
2976
|
+
context: args.context
|
|
2977
|
+
});
|
|
2978
|
+
console.log(`Verdict: ${result.verdict}`);
|
|
2979
|
+
console.log(`Score: ${result.score}/100`);
|
|
2980
|
+
console.log("Evidence:");
|
|
2981
|
+
for (const item of result.evidence ?? []) {
|
|
2982
|
+
console.log(` - ${item}`);
|
|
2983
|
+
}
|
|
2984
|
+
if (result.verdict === "weak") {
|
|
2985
|
+
process.exit(1);
|
|
2986
|
+
}
|
|
2987
|
+
}
|
|
2988
|
+
}),
|
|
2989
|
+
character: defineCommand({
|
|
2990
|
+
meta: {
|
|
2991
|
+
name: "character",
|
|
2992
|
+
description: "Create a reusable, persisted character. Create it once, then reuse the printed id for every " + "clone (see `vidjutsu clone starting-image --character <id>` and `clone run --character <id>`). " + "Metered per call."
|
|
2993
|
+
},
|
|
2994
|
+
subCommands: {
|
|
2995
|
+
list: defineCommand({
|
|
2996
|
+
meta: {
|
|
2997
|
+
name: "list",
|
|
2998
|
+
description: "List your persisted characters. Reads are not billed."
|
|
2999
|
+
},
|
|
3000
|
+
async run() {
|
|
3001
|
+
const result = await apiRequest("GET", "/v1/characters");
|
|
3002
|
+
const characters = Array.isArray(result) ? result : result.characters ?? [];
|
|
3003
|
+
if (characters.length === 0) {
|
|
3004
|
+
console.log("No characters yet. Create one with: vidjutsu clone character --prompt ...");
|
|
3005
|
+
return;
|
|
3006
|
+
}
|
|
3007
|
+
for (const c3 of characters) {
|
|
3008
|
+
console.log(`${c3.id} ${c3.model} ${c3.createdAt}`);
|
|
3009
|
+
}
|
|
3010
|
+
}
|
|
3011
|
+
})
|
|
3012
|
+
},
|
|
3013
|
+
args: {
|
|
3014
|
+
prompt: { type: "string", description: "Text description of the character to generate" },
|
|
3015
|
+
reference: { type: "string", description: "Optional public HTTPS reference image URL to guide identity" }
|
|
3016
|
+
},
|
|
3017
|
+
async run({ args, rawArgs }) {
|
|
3018
|
+
if (rawArgs[0] === "list")
|
|
3019
|
+
return;
|
|
3020
|
+
if (!args.prompt) {
|
|
3021
|
+
throw new Error("--prompt is required to create a character (or run `vidjutsu clone character list`).");
|
|
3022
|
+
}
|
|
3023
|
+
const result = await apiRequest("POST", "/v1/characters", {
|
|
3024
|
+
prompt: args.prompt,
|
|
3025
|
+
referenceImageUrl: args.reference
|
|
3026
|
+
});
|
|
3027
|
+
console.log(`Character created: ${result.id}`);
|
|
3028
|
+
console.log(`Image: ${result.imageUrl}`);
|
|
3029
|
+
console.log(`Model: ${result.model}`);
|
|
3030
|
+
console.log("");
|
|
3031
|
+
console.log(`Reuse this character with: --character ${result.id}`);
|
|
3032
|
+
}
|
|
3033
|
+
}),
|
|
3034
|
+
"starting-image": defineCommand({
|
|
3035
|
+
meta: {
|
|
3036
|
+
name: "starting-image",
|
|
3037
|
+
description: "Create a character-swapped starting frame, with no overlays. --character accepts either a stored " + "character id (char_...) or a public HTTPS character image URL. Metered per call."
|
|
3038
|
+
},
|
|
3039
|
+
args: {
|
|
3040
|
+
character: {
|
|
3041
|
+
type: "string",
|
|
3042
|
+
description: "Stored character id (char_...) from `clone character`, or a public HTTPS character image URL",
|
|
3043
|
+
required: true
|
|
3044
|
+
},
|
|
3045
|
+
prompt: { type: "string", description: "Instructions for composing the starting frame", required: true },
|
|
3046
|
+
source: { type: "string", description: "Optional public HTTPS source video URL to ground the composition" }
|
|
3047
|
+
},
|
|
3048
|
+
async run({ args }) {
|
|
3049
|
+
const result = await apiRequest("POST", "/v1/clones/starting-image", {
|
|
3050
|
+
...characterRef(args.character),
|
|
3051
|
+
prompt: args.prompt,
|
|
3052
|
+
sourceVideoUrl: args.source
|
|
3053
|
+
});
|
|
3054
|
+
console.log(result.imageUrl);
|
|
3055
|
+
}
|
|
3056
|
+
}),
|
|
3057
|
+
video: defineCommand({
|
|
3058
|
+
meta: {
|
|
3059
|
+
name: "video",
|
|
3060
|
+
description: "Clone source motion onto a starting image. Kling motion control is the default; seedance is the " + "alternate model, 9:16 at 480p. Metered per call. Returns a task id (HTTP 202); use --wait to poll to completion."
|
|
3061
|
+
},
|
|
3062
|
+
args: {
|
|
3063
|
+
"starting-image": { type: "string", description: "Public HTTPS URL of the starting frame", required: true },
|
|
3064
|
+
source: { type: "string", description: "Public HTTPS URL of the source video whose motion is cloned", required: true },
|
|
3065
|
+
model: { type: "string", description: "kling (default) or seedance" },
|
|
3066
|
+
prompt: { type: "string", description: "Optional override for the default identity-swap prompt (seedance only)" },
|
|
3067
|
+
wait: { type: "boolean", description: "Poll GET status until completed or failed, then print videoUrl" }
|
|
3068
|
+
},
|
|
3069
|
+
async run({ args }) {
|
|
3070
|
+
const model = validateModel(args.model);
|
|
3071
|
+
const accepted = await apiRequest("POST", "/v1/clones/video", {
|
|
3072
|
+
startingImageUrl: args["starting-image"],
|
|
3073
|
+
sourceVideoUrl: args.source,
|
|
3074
|
+
model,
|
|
3075
|
+
prompt: args.prompt
|
|
3076
|
+
});
|
|
3077
|
+
console.log(accepted.id);
|
|
3078
|
+
if (args.wait) {
|
|
3079
|
+
const final = await pollCloneVideo(accepted.id);
|
|
3080
|
+
console.log(final.videoUrl);
|
|
3081
|
+
}
|
|
3082
|
+
}
|
|
3083
|
+
}),
|
|
3084
|
+
status: defineCommand({
|
|
3085
|
+
meta: {
|
|
3086
|
+
name: "status",
|
|
3087
|
+
description: "Poll a clone video task by id. Status reads are not billed."
|
|
3088
|
+
},
|
|
3089
|
+
args: {
|
|
3090
|
+
id: { type: "positional", description: "Clone video task id", required: true }
|
|
3091
|
+
},
|
|
3092
|
+
async run({ args }) {
|
|
3093
|
+
const result = await apiRequest("GET", `/v1/clones/video/${encodeURIComponent(args.id)}`);
|
|
3094
|
+
console.log(JSON.stringify(result, null, 2));
|
|
3095
|
+
}
|
|
3096
|
+
}),
|
|
3097
|
+
run: defineCommand({
|
|
3098
|
+
meta: {
|
|
3099
|
+
name: "run",
|
|
3100
|
+
description: "Run the full clone chain: download the TikTok video, check it, generate a starting image from a " + "reusable stored character, generate the clone video, and wait for it to finish. About 5 minutes end " + "to end. Characters are reusable: create one once with `vidjutsu clone character --prompt ...`, then " + "pass its id here with --character on every run — this command never generates a new random character. " + "--character is required. Kling motion control is the default model; output is 480p 9:16, source clips " + "are capped at 15 seconds. Each step is metered per call. Stops before spending on generation when the " + "check verdict is weak, unless --force is given."
|
|
3101
|
+
},
|
|
3102
|
+
args: {
|
|
3103
|
+
tiktokUrl: { type: "positional", description: "TikTok video URL to clone", required: true },
|
|
3104
|
+
character: {
|
|
3105
|
+
type: "string",
|
|
3106
|
+
description: "Required. Stored character id (char_...) from `vidjutsu clone character --prompt ...`. " + "Characters are reusable across runs — create one once, then pass its id here every time."
|
|
3107
|
+
},
|
|
3108
|
+
"starting-prompt": { type: "string", description: "Prompt for the starting frame composition" },
|
|
3109
|
+
model: { type: "string", description: "kling (default) or seedance" },
|
|
3110
|
+
force: { type: "boolean", description: "Proceed even if the clone check verdict is weak" }
|
|
3111
|
+
},
|
|
3112
|
+
async run({ args }) {
|
|
3113
|
+
const model = validateModel(args.model);
|
|
3114
|
+
if (!args.character) {
|
|
3115
|
+
console.log("Missing --character. Create a reusable character first with: " + 'vidjutsu clone character --prompt "A neutral, camera-ready presenter"');
|
|
3116
|
+
console.log("Then pass its id here: vidjutsu clone run <url> --character char_...");
|
|
3117
|
+
process.exit(1);
|
|
3118
|
+
}
|
|
3119
|
+
console.log(`Downloading ${args.tiktokUrl}...`);
|
|
3120
|
+
const download = await apiRequest("POST", "/v1/videos/download/tiktok", {
|
|
3121
|
+
url: args.tiktokUrl
|
|
3122
|
+
});
|
|
3123
|
+
console.log("Checking cloneability...");
|
|
3124
|
+
const check = await apiRequest("POST", "/v1/clones/check", {
|
|
3125
|
+
videoUrl: download.url
|
|
3126
|
+
});
|
|
3127
|
+
console.log(`Verdict: ${check.verdict} (score ${check.score}/100)`);
|
|
3128
|
+
for (const item of check.evidence ?? []) {
|
|
3129
|
+
console.log(` - ${item}`);
|
|
3130
|
+
}
|
|
3131
|
+
if (check.verdict === "weak" && !args.force) {
|
|
3132
|
+
console.log("Stopping: the source clip is unlikely to clone well. Pass --force to continue anyway.");
|
|
3133
|
+
process.exit(1);
|
|
3134
|
+
}
|
|
3135
|
+
console.log("Generating starting image...");
|
|
3136
|
+
const startingImage = await apiRequest("POST", "/v1/clones/starting-image", {
|
|
3137
|
+
...characterRef(args.character),
|
|
3138
|
+
prompt: args["starting-prompt"] ?? "Match the framing and pose of the source video's opening frame",
|
|
3139
|
+
sourceVideoUrl: download.url
|
|
3140
|
+
});
|
|
3141
|
+
console.log("Generating clone video...");
|
|
3142
|
+
const accepted = await apiRequest("POST", "/v1/clones/video", {
|
|
3143
|
+
startingImageUrl: startingImage.imageUrl,
|
|
3144
|
+
sourceVideoUrl: download.url,
|
|
3145
|
+
model
|
|
3146
|
+
});
|
|
3147
|
+
console.log(`Task ${accepted.id} accepted, polling...`);
|
|
3148
|
+
const final = await pollCloneVideo(accepted.id);
|
|
3149
|
+
console.log(final.videoUrl);
|
|
3150
|
+
}
|
|
3151
|
+
})
|
|
3152
|
+
}
|
|
3153
|
+
});
|
|
3154
|
+
});
|
|
3155
|
+
|
|
2719
3156
|
// src/cli/commands/generated/watch.ts
|
|
2720
3157
|
var exports_watch = {};
|
|
2721
3158
|
__export(exports_watch, {
|
|
@@ -3377,6 +3814,110 @@ var init_info = __esm(() => {
|
|
|
3377
3814
|
});
|
|
3378
3815
|
});
|
|
3379
3816
|
|
|
3817
|
+
// src/cli/commands/generated/project.ts
|
|
3818
|
+
var exports_project = {};
|
|
3819
|
+
__export(exports_project, {
|
|
3820
|
+
default: () => project_default
|
|
3821
|
+
});
|
|
3822
|
+
function parseTags5(raw) {
|
|
3823
|
+
if (!raw)
|
|
3824
|
+
return;
|
|
3825
|
+
return raw.split(",").map((pair) => {
|
|
3826
|
+
const [key, ...rest] = pair.split("=");
|
|
3827
|
+
return { key: key.trim(), value: rest.join("=").trim() };
|
|
3828
|
+
});
|
|
3829
|
+
}
|
|
3830
|
+
var project_default;
|
|
3831
|
+
var init_project = __esm(() => {
|
|
3832
|
+
init_dist2();
|
|
3833
|
+
init_client();
|
|
3834
|
+
project_default = defineCommand({
|
|
3835
|
+
meta: { name: "project", description: "Manage projects" },
|
|
3836
|
+
subCommands: {
|
|
3837
|
+
create: defineCommand({
|
|
3838
|
+
meta: { name: "create", description: "Create an editor project" },
|
|
3839
|
+
args: {
|
|
3840
|
+
name: { type: "string", description: "name", required: true },
|
|
3841
|
+
project: { type: "string", description: "project" },
|
|
3842
|
+
tags: { type: "string", description: "Tags as key=value pairs, comma-separated" },
|
|
3843
|
+
metadata: { type: "string", description: "metadata" }
|
|
3844
|
+
},
|
|
3845
|
+
async run({ args }) {
|
|
3846
|
+
const body = {};
|
|
3847
|
+
if (args["name"] !== undefined)
|
|
3848
|
+
body["name"] = args["name"];
|
|
3849
|
+
if (args["project"] !== undefined)
|
|
3850
|
+
body["project"] = args["project"];
|
|
3851
|
+
const tags = parseTags5(args.tags);
|
|
3852
|
+
if (tags)
|
|
3853
|
+
body.tags = tags;
|
|
3854
|
+
if (args["metadata"] !== undefined)
|
|
3855
|
+
body["metadata"] = args["metadata"];
|
|
3856
|
+
const result = await apiRequest("POST", "/v1/projects", body);
|
|
3857
|
+
console.log(JSON.stringify(result, null, 2));
|
|
3858
|
+
}
|
|
3859
|
+
}),
|
|
3860
|
+
edit: defineCommand({
|
|
3861
|
+
meta: { name: "edit", description: "Edit an editor project" },
|
|
3862
|
+
args: {
|
|
3863
|
+
id: { type: "positional", description: "Project ID", required: true },
|
|
3864
|
+
name: { type: "string", description: "name" },
|
|
3865
|
+
status: { type: "string", description: "status" },
|
|
3866
|
+
project: { type: "string", description: "project" },
|
|
3867
|
+
tags: { type: "string", description: "Tags as key=value pairs, comma-separated" },
|
|
3868
|
+
metadata: { type: "string", description: "metadata" }
|
|
3869
|
+
},
|
|
3870
|
+
async run({ args }) {
|
|
3871
|
+
const body = {};
|
|
3872
|
+
if (args["name"] !== undefined)
|
|
3873
|
+
body["name"] = args["name"];
|
|
3874
|
+
if (args["status"] !== undefined)
|
|
3875
|
+
body["status"] = args["status"];
|
|
3876
|
+
if (args["project"] !== undefined)
|
|
3877
|
+
body["project"] = args["project"];
|
|
3878
|
+
const tags = parseTags5(args.tags);
|
|
3879
|
+
if (tags)
|
|
3880
|
+
body.tags = tags;
|
|
3881
|
+
if (args["metadata"] !== undefined)
|
|
3882
|
+
body["metadata"] = args["metadata"];
|
|
3883
|
+
const result = await apiRequest("PUT", "/v1/projects?id=" + args.id, body);
|
|
3884
|
+
console.log(JSON.stringify(result, null, 2));
|
|
3885
|
+
}
|
|
3886
|
+
}),
|
|
3887
|
+
list: defineCommand({
|
|
3888
|
+
meta: { name: "list", description: "List editor projects" },
|
|
3889
|
+
args: {
|
|
3890
|
+
id: { type: "string", description: "Project ID (omit to list all)" },
|
|
3891
|
+
status: { type: "string", description: "status" }
|
|
3892
|
+
},
|
|
3893
|
+
async run({ args }) {
|
|
3894
|
+
let path = "/v1/projects";
|
|
3895
|
+
const params = new URLSearchParams;
|
|
3896
|
+
if (args["id"])
|
|
3897
|
+
params.set("id", args["id"]);
|
|
3898
|
+
if (args["status"])
|
|
3899
|
+
params.set("status", args["status"]);
|
|
3900
|
+
const qs = params.toString();
|
|
3901
|
+
if (qs)
|
|
3902
|
+
path += "?" + qs;
|
|
3903
|
+
const result = await apiRequest("GET", path);
|
|
3904
|
+
console.log(JSON.stringify(result, null, 2));
|
|
3905
|
+
}
|
|
3906
|
+
}),
|
|
3907
|
+
delete: defineCommand({
|
|
3908
|
+
meta: { name: "delete", description: "Archive an editor project" },
|
|
3909
|
+
args: {
|
|
3910
|
+
id: { type: "positional", description: "Project ID", required: true }
|
|
3911
|
+
},
|
|
3912
|
+
async run({ args }) {
|
|
3913
|
+
const result = await apiRequest("DELETE", "/v1/projects?id=" + args.id);
|
|
3914
|
+
console.log(JSON.stringify(result, null, 2));
|
|
3915
|
+
}
|
|
3916
|
+
})
|
|
3917
|
+
}
|
|
3918
|
+
});
|
|
3919
|
+
});
|
|
3920
|
+
|
|
3380
3921
|
// src/cli/index.ts
|
|
3381
3922
|
init_dist2();
|
|
3382
3923
|
var main = defineCommand({
|
|
@@ -3391,8 +3932,12 @@ var main = defineCommand({
|
|
|
3391
3932
|
upload: () => Promise.resolve().then(() => (init_upload(), exports_upload)).then((m2) => m2.default),
|
|
3392
3933
|
subscribe: () => Promise.resolve().then(() => (init_subscribe(), exports_subscribe)).then((m2) => m2.default),
|
|
3393
3934
|
status: () => Promise.resolve().then(() => (init_status(), exports_status)).then((m2) => m2.default),
|
|
3935
|
+
balance: () => Promise.resolve().then(() => (init_balance(), exports_balance)).then((m2) => m2.default),
|
|
3936
|
+
admin: () => Promise.resolve().then(() => (init_admin(), exports_admin)).then((m2) => m2.default),
|
|
3394
3937
|
version: () => Promise.resolve().then(() => (init_version(), exports_version)).then((m2) => m2.default),
|
|
3395
3938
|
update: () => Promise.resolve().then(() => (init_update(), exports_update)).then((m2) => m2.default),
|
|
3939
|
+
jobs: () => Promise.resolve().then(() => (init_jobs(), exports_jobs)).then((m2) => m2.default),
|
|
3940
|
+
clone: () => Promise.resolve().then(() => (init_clone(), exports_clone)).then((m2) => m2.default),
|
|
3396
3941
|
watch: () => Promise.resolve().then(() => (init_watch(), exports_watch)).then((m2) => m2.default),
|
|
3397
3942
|
extract: () => Promise.resolve().then(() => (init_extract(), exports_extract)).then((m2) => m2.default),
|
|
3398
3943
|
transcribe: () => Promise.resolve().then(() => (init_transcribe(), exports_transcribe)).then((m2) => m2.default),
|
|
@@ -3403,7 +3948,8 @@ var main = defineCommand({
|
|
|
3403
3948
|
asset: () => Promise.resolve().then(() => (init_asset(), exports_asset)).then((m2) => m2.default),
|
|
3404
3949
|
reference: () => Promise.resolve().then(() => (init_reference(), exports_reference)).then((m2) => m2.default),
|
|
3405
3950
|
usage: () => Promise.resolve().then(() => (init_usage(), exports_usage)).then((m2) => m2.default),
|
|
3406
|
-
info: () => Promise.resolve().then(() => (init_info(), exports_info)).then((m2) => m2.default)
|
|
3951
|
+
info: () => Promise.resolve().then(() => (init_info(), exports_info)).then((m2) => m2.default),
|
|
3952
|
+
project: () => Promise.resolve().then(() => (init_project(), exports_project)).then((m2) => m2.default)
|
|
3407
3953
|
}
|
|
3408
3954
|
});
|
|
3409
3955
|
runMain(main);
|
package/dist/client.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import createFetchClient from "openapi-fetch";
|
|
2
2
|
import type { paths } from "./schema.js";
|
|
3
3
|
import { type VidJutsuMethods } from "./methods.js";
|
|
4
|
+
import { type DistributionNamespaces } from "./distribution.js";
|
|
5
|
+
import { type JobsNamespaces } from "./jobs.js";
|
|
4
6
|
export interface VidJutsuConfig {
|
|
5
7
|
/** API key. Falls back to VIDJUTSU_API_KEY env var, then ~/.vidjutsu/config.json. */
|
|
6
8
|
apiKey?: string;
|
|
@@ -10,7 +12,7 @@ export interface VidJutsuConfig {
|
|
|
10
12
|
/** The raw openapi-fetch client with typed GET/POST/PUT/DELETE */
|
|
11
13
|
type FetchClient = ReturnType<typeof createFetchClient<paths>>;
|
|
12
14
|
/** Combined client: typed convenience methods + raw openapi-fetch escape hatch */
|
|
13
|
-
export type VidJutsuClient = VidJutsuMethods & {
|
|
15
|
+
export type VidJutsuClient = VidJutsuMethods & DistributionNamespaces & JobsNamespaces & {
|
|
14
16
|
api: FetchClient;
|
|
15
17
|
};
|
|
16
18
|
/**
|
package/dist/client.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import createFetchClient from "openapi-fetch";
|
|
2
2
|
import { bindMethods } from "./methods.js";
|
|
3
|
+
import { bindDistribution } from "./distribution.js";
|
|
4
|
+
import { bindJobs } from "./jobs.js";
|
|
3
5
|
import { readFileSync, existsSync } from "fs";
|
|
4
6
|
import { join } from "path";
|
|
5
7
|
import { homedir } from "os";
|
|
@@ -50,5 +52,7 @@ export function createClient(config = {}) {
|
|
|
50
52
|
},
|
|
51
53
|
});
|
|
52
54
|
const methods = bindMethods(fetchClient);
|
|
53
|
-
|
|
55
|
+
const distribution = bindDistribution(fetchClient);
|
|
56
|
+
const jobs = bindJobs(fetchClient);
|
|
57
|
+
return { ...methods, ...distribution, ...jobs, api: fetchClient };
|
|
54
58
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type createFetchClient from "openapi-fetch";
|
|
2
|
+
import type { components, paths } from "./schema.js";
|
|
3
|
+
type FetchClient = ReturnType<typeof createFetchClient<paths>>;
|
|
4
|
+
type Job = components["schemas"]["DistributionJob"];
|
|
5
|
+
type AddVideoRequest = components["schemas"]["AddVideoRequest"];
|
|
6
|
+
export interface MutationOptions {
|
|
7
|
+
idempotencyKey?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface WaitOptions {
|
|
10
|
+
timeoutMs?: number;
|
|
11
|
+
pollIntervalMs?: number;
|
|
12
|
+
}
|
|
13
|
+
export interface DistributionNamespaces {
|
|
14
|
+
videos: {
|
|
15
|
+
add(body: AddVideoRequest, options?: MutationOptions): Promise<Job>;
|
|
16
|
+
};
|
|
17
|
+
jobs: {
|
|
18
|
+
get(jobId: string): Promise<Job>;
|
|
19
|
+
waitForResult(jobId: string, options?: WaitOptions): Promise<Job>;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export declare function bindDistribution(client: FetchClient): DistributionNamespaces;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
export function bindDistribution(client) {
|
|
2
|
+
const jobs = {
|
|
3
|
+
async get(jobId) {
|
|
4
|
+
const result = await client.GET("/v1/distribution/jobs", {
|
|
5
|
+
params: { query: { id: jobId } },
|
|
6
|
+
});
|
|
7
|
+
return requireData(result, "get distribution job");
|
|
8
|
+
},
|
|
9
|
+
async waitForResult(jobId, options = {}) {
|
|
10
|
+
const timeoutMs = options.timeoutMs ?? 10 * 60_000;
|
|
11
|
+
const pollIntervalMs = options.pollIntervalMs ?? 1_000;
|
|
12
|
+
const deadline = Date.now() + timeoutMs;
|
|
13
|
+
while (true) {
|
|
14
|
+
const job = await jobs.get(jobId);
|
|
15
|
+
if (job.status === "completed")
|
|
16
|
+
return job;
|
|
17
|
+
if (job.status === "failed" || job.status === "cancelled") {
|
|
18
|
+
throw new Error(job.error?.message ?? `Distribution job ${job.status}`);
|
|
19
|
+
}
|
|
20
|
+
if (Date.now() >= deadline)
|
|
21
|
+
throw new Error(`Timed out waiting for distribution job ${jobId}`);
|
|
22
|
+
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
return {
|
|
27
|
+
videos: {
|
|
28
|
+
async add(body, options) {
|
|
29
|
+
const result = await client.POST("/v1/videos/add", {
|
|
30
|
+
body,
|
|
31
|
+
params: { header: idempotencyHeader(options) },
|
|
32
|
+
});
|
|
33
|
+
return requireData(result, "add video");
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
jobs,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function idempotencyHeader(options) {
|
|
40
|
+
return options?.idempotencyKey ? { "Idempotency-Key": options.idempotencyKey } : {};
|
|
41
|
+
}
|
|
42
|
+
function requireData(result, operation) {
|
|
43
|
+
if (result.data !== undefined)
|
|
44
|
+
return result.data;
|
|
45
|
+
const message = extractErrorMessage(result.error) ?? `Vidjutsu failed to ${operation} (HTTP ${result.response.status})`;
|
|
46
|
+
throw new Error(message);
|
|
47
|
+
}
|
|
48
|
+
function extractErrorMessage(error) {
|
|
49
|
+
if (!error || typeof error !== "object")
|
|
50
|
+
return undefined;
|
|
51
|
+
if ("message" in error && typeof error.message === "string")
|
|
52
|
+
return error.message;
|
|
53
|
+
if ("error" in error && typeof error.error === "string")
|
|
54
|
+
return error.error;
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export { createClient } from "./client.js";
|
|
2
2
|
export type { VidJutsuConfig, VidJutsuClient } from "./client.js";
|
|
3
3
|
export type { VidJutsuMethods } from "./methods.js";
|
|
4
|
+
export type { DistributionNamespaces, MutationOptions, WaitOptions } from "./distribution.js";
|
|
5
|
+
export type { JobsNamespaces } from "./jobs.js";
|
|
4
6
|
export type { paths, components } from "./schema.js";
|
package/dist/jobs.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type createFetchClient from "openapi-fetch";
|
|
2
|
+
import type { components, paths } from "./schema.js";
|
|
3
|
+
import type { WaitOptions } from "./distribution.js";
|
|
4
|
+
type FetchClient = ReturnType<typeof createFetchClient<paths>>;
|
|
5
|
+
type MediaJob = components["schemas"]["MediaJob"];
|
|
6
|
+
export interface JobsNamespaces {
|
|
7
|
+
mediaJobs: {
|
|
8
|
+
get(jobId: string): Promise<MediaJob>;
|
|
9
|
+
awaitJob(jobId: string, options?: WaitOptions): Promise<MediaJob>;
|
|
10
|
+
};
|
|
11
|
+
awaitJob(jobId: string, options?: WaitOptions): Promise<MediaJob>;
|
|
12
|
+
}
|
|
13
|
+
export declare function bindJobs(client: FetchClient): JobsNamespaces;
|
|
14
|
+
export {};
|
package/dist/jobs.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export function bindJobs(client) {
|
|
2
|
+
const mediaJobs = {
|
|
3
|
+
async get(jobId) {
|
|
4
|
+
const result = await client.GET("/v1/jobs", {
|
|
5
|
+
params: { query: { id: jobId } },
|
|
6
|
+
});
|
|
7
|
+
return requireData(result, "get media job");
|
|
8
|
+
},
|
|
9
|
+
async awaitJob(jobId, options = {}) {
|
|
10
|
+
const timeoutMs = options.timeoutMs ?? 10 * 60_000;
|
|
11
|
+
const pollIntervalMs = options.pollIntervalMs ?? 1_000;
|
|
12
|
+
if (timeoutMs <= 0 || pollIntervalMs <= 0) {
|
|
13
|
+
throw new Error("timeoutMs and pollIntervalMs must be positive");
|
|
14
|
+
}
|
|
15
|
+
const deadline = Date.now() + timeoutMs;
|
|
16
|
+
while (true) {
|
|
17
|
+
const job = await mediaJobs.get(jobId);
|
|
18
|
+
if (job.status === "completed")
|
|
19
|
+
return job;
|
|
20
|
+
if (job.status === "failed" || job.status === "cancelled") {
|
|
21
|
+
throw new Error(job.error?.message ?? `Media job ${job.status}`);
|
|
22
|
+
}
|
|
23
|
+
if (Date.now() >= deadline) {
|
|
24
|
+
throw new Error(`Timed out waiting for media job ${jobId}`);
|
|
25
|
+
}
|
|
26
|
+
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
return {
|
|
31
|
+
mediaJobs,
|
|
32
|
+
awaitJob: mediaJobs.awaitJob,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function requireData(result, operation) {
|
|
36
|
+
if (result.data !== undefined)
|
|
37
|
+
return result.data;
|
|
38
|
+
const message = extractErrorMessage(result.error) ??
|
|
39
|
+
`VidJutsu failed to ${operation} (HTTP ${result.response.status})`;
|
|
40
|
+
throw new Error(message);
|
|
41
|
+
}
|
|
42
|
+
function extractErrorMessage(error) {
|
|
43
|
+
if (!error || typeof error !== "object")
|
|
44
|
+
return undefined;
|
|
45
|
+
if ("message" in error && typeof error.message === "string")
|
|
46
|
+
return error.message;
|
|
47
|
+
if ("error" in error && typeof error.error === "string")
|
|
48
|
+
return error.error;
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
package/dist/methods.d.ts
CHANGED
|
@@ -34,16 +34,38 @@ export interface VidJutsuMethods {
|
|
|
34
34
|
listOrGetAssets(query?: QueryParams<"/v1/assets", "get">): ReturnType<Client["GET"]>;
|
|
35
35
|
/** Delete asset (soft) Auth required. */
|
|
36
36
|
deleteAsset(query?: QueryParams<"/v1/assets", "delete">): ReturnType<Client["DELETE"]>;
|
|
37
|
+
/** Agent registration (auth.md) */
|
|
38
|
+
signupAgent(body: ReqBody<"/v1/auth/agent", "post">): ReturnType<Client["POST"]>;
|
|
39
|
+
/** Initiate claim flow */
|
|
40
|
+
agentClaim(body: ReqBody<"/v1/auth/agent/claim", "post">): ReturnType<Client["POST"]>;
|
|
41
|
+
/** Complete claim flow */
|
|
42
|
+
agentClaimComplete(body: ReqBody<"/v1/auth/agent/claim/complete", "post">): ReturnType<Client["POST"]>;
|
|
43
|
+
/** Revoke credential */
|
|
44
|
+
agentRevoke(): ReturnType<Client["POST"]>;
|
|
37
45
|
/** Confirm email verification code Public endpoint. */
|
|
38
46
|
confirmVerification(body: ReqBody<"/v1/auth/verify/confirm", "post">): ReturnType<Client["POST"]>;
|
|
39
47
|
/** Request email verification code Public endpoint. */
|
|
40
48
|
requestVerification(body: ReqBody<"/v1/auth/verify/request", "post">): ReturnType<Client["POST"]>;
|
|
49
|
+
/** Create a reusable, persisted character image */
|
|
50
|
+
createCharacter(body: ReqBody<"/v1/characters", "post">): ReturnType<Client["POST"]>;
|
|
51
|
+
/** List your persisted characters */
|
|
52
|
+
listCharacters(): ReturnType<Client["GET"]>;
|
|
53
|
+
/** Fetch a persisted character by id */
|
|
54
|
+
getCharacter(id: string): ReturnType<Client["GET"]>;
|
|
41
55
|
/** Check spec Auth required. 5 credits. */
|
|
42
56
|
checkSpec(body: ReqBody<"/v1/check", "post">): ReturnType<Client["POST"]>;
|
|
43
57
|
/** Get check rules Auth required. */
|
|
44
58
|
getCheckRules(): ReturnType<Client["GET"]>;
|
|
45
59
|
/** Update check rules Auth required. */
|
|
46
60
|
updateCheckRules(body: ReqBody<"/v1/check/rules", "put">): ReturnType<Client["PUT"]>;
|
|
61
|
+
/** Evaluate whether a source video can be cloned reliably */
|
|
62
|
+
cloneCheck(body: ReqBody<"/v1/clones/check", "post">): ReturnType<Client["POST"]>;
|
|
63
|
+
/** Create a character-swapped starting frame */
|
|
64
|
+
cloneStartingImage(body: ReqBody<"/v1/clones/starting-image", "post">): ReturnType<Client["POST"]>;
|
|
65
|
+
/** Clone source motion with Kling motion control or Seedance */
|
|
66
|
+
cloneVideo(body: ReqBody<"/v1/clones/video", "post">): ReturnType<Client["POST"]>;
|
|
67
|
+
/** Poll a clone video task */
|
|
68
|
+
getCloneVideo(id: string): ReturnType<Client["GET"]>;
|
|
47
69
|
/** Check prompt compliance */
|
|
48
70
|
checkCompliancePrompt(body: ReqBody<"/v1/compliance/prompt", "post">): ReturnType<Client["POST"]>;
|
|
49
71
|
/** Check video compliance */
|
|
@@ -52,10 +74,14 @@ export interface VidJutsuMethods {
|
|
|
52
74
|
getCheckoutStatus(query?: QueryParams<"/v1/credits/status", "get">): ReturnType<Client["GET"]>;
|
|
53
75
|
/** Burn fine-print disclaimer onto video */
|
|
54
76
|
createDisclaimer(body: ReqBody<"/v1/disclaimer", "post">): ReturnType<Client["POST"]>;
|
|
77
|
+
/** Inspect a distribution job Auth required. */
|
|
78
|
+
getDistributionJob(query?: QueryParams<"/v1/distribution/jobs", "get">): ReturnType<Client["GET"]>;
|
|
55
79
|
/** Extract from media Auth required. 5 credits. */
|
|
56
80
|
extractMedia(body: ReqBody<"/v1/extract", "post">): ReturnType<Client["POST"]>;
|
|
57
81
|
/** API info Public endpoint. */
|
|
58
82
|
getInfo(): ReturnType<Client["GET"]>;
|
|
83
|
+
/** Inspect a durable VidJutsu media job Auth required. */
|
|
84
|
+
getJob(query?: QueryParams<"/v1/jobs", "get">): ReturnType<Client["GET"]>;
|
|
59
85
|
/** Burn text overlay onto video Auth required. 5 credits. */
|
|
60
86
|
createOverlay(body: ReqBody<"/v1/overlay", "post">): ReturnType<Client["POST"]>;
|
|
61
87
|
/** Create post Auth required. */
|
|
@@ -68,6 +94,14 @@ export interface VidJutsuMethods {
|
|
|
68
94
|
deletePost(query?: QueryParams<"/v1/posts", "delete">): ReturnType<Client["DELETE"]>;
|
|
69
95
|
/** Get pricing Public endpoint. */
|
|
70
96
|
getPricing(): ReturnType<Client["GET"]>;
|
|
97
|
+
/** Create editor project */
|
|
98
|
+
createEditorProject(body: ReqBody<"/v1/projects", "post">): ReturnType<Client["POST"]>;
|
|
99
|
+
/** Update editor project */
|
|
100
|
+
updateEditorProject(body: ReqBody<"/v1/projects", "put">, query?: QueryParams<"/v1/projects", "put">): ReturnType<Client["PUT"]>;
|
|
101
|
+
/** List projects or get by ID */
|
|
102
|
+
listOrGetEditorProjects(query?: QueryParams<"/v1/projects", "get">): ReturnType<Client["GET"]>;
|
|
103
|
+
/** Archive editor project (soft) */
|
|
104
|
+
deleteEditorProject(query?: QueryParams<"/v1/projects", "delete">): ReturnType<Client["DELETE"]>;
|
|
71
105
|
/** Create reference Auth required. */
|
|
72
106
|
createReference(body: ReqBody<"/v1/references", "post">): ReturnType<Client["POST"]>;
|
|
73
107
|
/** Update reference Auth required. */
|
|
@@ -76,6 +110,30 @@ export interface VidJutsuMethods {
|
|
|
76
110
|
listOrGetReferences(query?: QueryParams<"/v1/references", "get">): ReturnType<Client["GET"]>;
|
|
77
111
|
/** Delete reference Auth required. */
|
|
78
112
|
deleteReference(query?: QueryParams<"/v1/references", "delete">): ReturnType<Client["DELETE"]>;
|
|
113
|
+
/** Scrape Instagram post or reel Auth required. 1 credits. */
|
|
114
|
+
scrapeInstagramPost(body: ReqBody<"/v1/scrape/instagram/post", "post">): ReturnType<Client["POST"]>;
|
|
115
|
+
/** Scrape Instagram post comments Auth required. 1 credits. */
|
|
116
|
+
scrapeInstagramPostComments(body: ReqBody<"/v1/scrape/instagram/post/comments", "post">): ReturnType<Client["POST"]>;
|
|
117
|
+
/** Scrape Instagram profile Auth required. 1 credits. */
|
|
118
|
+
scrapeInstagramProfile(body: ReqBody<"/v1/scrape/instagram/profile", "post">): ReturnType<Client["POST"]>;
|
|
119
|
+
/** Scrape Instagram user posts Auth required. 1 credits. */
|
|
120
|
+
scrapeInstagramUserPosts(body: ReqBody<"/v1/scrape/instagram/user/posts", "post">): ReturnType<Client["POST"]>;
|
|
121
|
+
/** Scrape Instagram user reels Auth required. 1 credits. */
|
|
122
|
+
scrapeInstagramUserReels(body: ReqBody<"/v1/scrape/instagram/user/reels", "post">): ReturnType<Client["POST"]>;
|
|
123
|
+
/** Scrape TikTok profile Auth required. 1 credits. */
|
|
124
|
+
scrapeTikTokProfile(body: ReqBody<"/v1/scrape/tiktok/profile", "post">): ReturnType<Client["POST"]>;
|
|
125
|
+
/** Scrape TikTok profile videos Auth required. 1 credits. */
|
|
126
|
+
scrapeTikTokProfileVideos(body: ReqBody<"/v1/scrape/tiktok/profile/videos", "post">): ReturnType<Client["POST"]>;
|
|
127
|
+
/** Scrape TikTok user search Auth required. 1 credits. */
|
|
128
|
+
scrapeTikTokSearchUsers(body: ReqBody<"/v1/scrape/tiktok/search/users", "post">): ReturnType<Client["POST"]>;
|
|
129
|
+
/** Scrape TikTok trending feed Auth required. 1 credits. */
|
|
130
|
+
scrapeTikTokTrending(body: ReqBody<"/v1/scrape/tiktok/trending", "post">): ReturnType<Client["POST"]>;
|
|
131
|
+
/** Scrape TikTok video Auth required. 1 credits. */
|
|
132
|
+
scrapeTikTokVideo(body: ReqBody<"/v1/scrape/tiktok/video", "post">): ReturnType<Client["POST"]>;
|
|
133
|
+
/** Scrape TikTok video comments Auth required. 1 credits. */
|
|
134
|
+
scrapeTikTokVideoComments(body: ReqBody<"/v1/scrape/tiktok/video/comments", "post">): ReturnType<Client["POST"]>;
|
|
135
|
+
/** Scrape TikTok video transcript Auth required. 1 credits. */
|
|
136
|
+
scrapeTikTokVideoTranscript(body: ReqBody<"/v1/scrape/tiktok/video/transcript", "post">): ReturnType<Client["POST"]>;
|
|
79
137
|
/** Create subscription Public endpoint. */
|
|
80
138
|
createSubscription(body: ReqBody<"/v1/subscribe", "post">): ReturnType<Client["POST"]>;
|
|
81
139
|
/** Transcribe media Auth required. 10 credits. */
|
|
@@ -86,6 +144,12 @@ export interface VidJutsuMethods {
|
|
|
86
144
|
uploadFromUrl(body: ReqBody<"/v1/upload/url", "post">): ReturnType<Client["POST"]>;
|
|
87
145
|
/** Get daily usage */
|
|
88
146
|
getUsage(): ReturnType<Client["GET"]>;
|
|
147
|
+
/** Add a video from an uploaded asset or direct MP4 URL Auth required. */
|
|
148
|
+
addVideo(body: ReqBody<"/v1/videos/add", "post">): ReturnType<Client["POST"]>;
|
|
149
|
+
/** Import an Instagram video into VidJutsu Auth required. 1 credits. */
|
|
150
|
+
downloadInstagramVideo(body: ReqBody<"/v1/videos/download/instagram", "post">): ReturnType<Client["POST"]>;
|
|
151
|
+
/** Import a TikTok video into VidJutsu Auth required. 1 credits. */
|
|
152
|
+
downloadTikTokVideo(body: ReqBody<"/v1/videos/download/tiktok", "post">): ReturnType<Client["POST"]>;
|
|
89
153
|
/** Watch media Auth required. 10 credits. */
|
|
90
154
|
watchMedia(body: ReqBody<"/v1/watch", "post">): ReturnType<Client["POST"]>;
|
|
91
155
|
}
|
package/dist/methods.js
CHANGED
|
@@ -30,12 +30,33 @@ export function bindMethods(client) {
|
|
|
30
30
|
deleteAsset(query) {
|
|
31
31
|
return client.DELETE("/v1/assets", { params: { query } });
|
|
32
32
|
},
|
|
33
|
+
signupAgent(body) {
|
|
34
|
+
return client.POST("/v1/auth/agent", { body });
|
|
35
|
+
},
|
|
36
|
+
agentClaim(body) {
|
|
37
|
+
return client.POST("/v1/auth/agent/claim", { body });
|
|
38
|
+
},
|
|
39
|
+
agentClaimComplete(body) {
|
|
40
|
+
return client.POST("/v1/auth/agent/claim/complete", { body });
|
|
41
|
+
},
|
|
42
|
+
agentRevoke() {
|
|
43
|
+
return client.POST("/v1/auth/agent/revoke", {});
|
|
44
|
+
},
|
|
33
45
|
confirmVerification(body) {
|
|
34
46
|
return client.POST("/v1/auth/verify/confirm", { body });
|
|
35
47
|
},
|
|
36
48
|
requestVerification(body) {
|
|
37
49
|
return client.POST("/v1/auth/verify/request", { body });
|
|
38
50
|
},
|
|
51
|
+
createCharacter(body) {
|
|
52
|
+
return client.POST("/v1/characters", { body });
|
|
53
|
+
},
|
|
54
|
+
listCharacters() {
|
|
55
|
+
return client.GET("/v1/characters", {});
|
|
56
|
+
},
|
|
57
|
+
getCharacter(id) {
|
|
58
|
+
return client.GET("/v1/characters/{id}", { params: { path: { id } } });
|
|
59
|
+
},
|
|
39
60
|
checkSpec(body) {
|
|
40
61
|
return client.POST("/v1/check", { body });
|
|
41
62
|
},
|
|
@@ -45,6 +66,18 @@ export function bindMethods(client) {
|
|
|
45
66
|
updateCheckRules(body) {
|
|
46
67
|
return client.PUT("/v1/check/rules", { body });
|
|
47
68
|
},
|
|
69
|
+
cloneCheck(body) {
|
|
70
|
+
return client.POST("/v1/clones/check", { body });
|
|
71
|
+
},
|
|
72
|
+
cloneStartingImage(body) {
|
|
73
|
+
return client.POST("/v1/clones/starting-image", { body });
|
|
74
|
+
},
|
|
75
|
+
cloneVideo(body) {
|
|
76
|
+
return client.POST("/v1/clones/video", { body });
|
|
77
|
+
},
|
|
78
|
+
getCloneVideo(id) {
|
|
79
|
+
return client.GET("/v1/clones/video/{id}", { params: { path: { id } } });
|
|
80
|
+
},
|
|
48
81
|
checkCompliancePrompt(body) {
|
|
49
82
|
return client.POST("/v1/compliance/prompt", { body });
|
|
50
83
|
},
|
|
@@ -57,12 +90,18 @@ export function bindMethods(client) {
|
|
|
57
90
|
createDisclaimer(body) {
|
|
58
91
|
return client.POST("/v1/disclaimer", { body });
|
|
59
92
|
},
|
|
93
|
+
getDistributionJob(query) {
|
|
94
|
+
return client.GET("/v1/distribution/jobs", { params: { query } });
|
|
95
|
+
},
|
|
60
96
|
extractMedia(body) {
|
|
61
97
|
return client.POST("/v1/extract", { body });
|
|
62
98
|
},
|
|
63
99
|
getInfo() {
|
|
64
100
|
return client.GET("/v1/info", {});
|
|
65
101
|
},
|
|
102
|
+
getJob(query) {
|
|
103
|
+
return client.GET("/v1/jobs", { params: { query } });
|
|
104
|
+
},
|
|
66
105
|
createOverlay(body) {
|
|
67
106
|
return client.POST("/v1/overlay", { body });
|
|
68
107
|
},
|
|
@@ -81,6 +120,18 @@ export function bindMethods(client) {
|
|
|
81
120
|
getPricing() {
|
|
82
121
|
return client.GET("/v1/pricing", {});
|
|
83
122
|
},
|
|
123
|
+
createEditorProject(body) {
|
|
124
|
+
return client.POST("/v1/projects", { body });
|
|
125
|
+
},
|
|
126
|
+
updateEditorProject(body, query) {
|
|
127
|
+
return client.PUT("/v1/projects", { body, params: { query } });
|
|
128
|
+
},
|
|
129
|
+
listOrGetEditorProjects(query) {
|
|
130
|
+
return client.GET("/v1/projects", { params: { query } });
|
|
131
|
+
},
|
|
132
|
+
deleteEditorProject(query) {
|
|
133
|
+
return client.DELETE("/v1/projects", { params: { query } });
|
|
134
|
+
},
|
|
84
135
|
createReference(body) {
|
|
85
136
|
return client.POST("/v1/references", { body });
|
|
86
137
|
},
|
|
@@ -93,6 +144,42 @@ export function bindMethods(client) {
|
|
|
93
144
|
deleteReference(query) {
|
|
94
145
|
return client.DELETE("/v1/references", { params: { query } });
|
|
95
146
|
},
|
|
147
|
+
scrapeInstagramPost(body) {
|
|
148
|
+
return client.POST("/v1/scrape/instagram/post", { body });
|
|
149
|
+
},
|
|
150
|
+
scrapeInstagramPostComments(body) {
|
|
151
|
+
return client.POST("/v1/scrape/instagram/post/comments", { body });
|
|
152
|
+
},
|
|
153
|
+
scrapeInstagramProfile(body) {
|
|
154
|
+
return client.POST("/v1/scrape/instagram/profile", { body });
|
|
155
|
+
},
|
|
156
|
+
scrapeInstagramUserPosts(body) {
|
|
157
|
+
return client.POST("/v1/scrape/instagram/user/posts", { body });
|
|
158
|
+
},
|
|
159
|
+
scrapeInstagramUserReels(body) {
|
|
160
|
+
return client.POST("/v1/scrape/instagram/user/reels", { body });
|
|
161
|
+
},
|
|
162
|
+
scrapeTikTokProfile(body) {
|
|
163
|
+
return client.POST("/v1/scrape/tiktok/profile", { body });
|
|
164
|
+
},
|
|
165
|
+
scrapeTikTokProfileVideos(body) {
|
|
166
|
+
return client.POST("/v1/scrape/tiktok/profile/videos", { body });
|
|
167
|
+
},
|
|
168
|
+
scrapeTikTokSearchUsers(body) {
|
|
169
|
+
return client.POST("/v1/scrape/tiktok/search/users", { body });
|
|
170
|
+
},
|
|
171
|
+
scrapeTikTokTrending(body) {
|
|
172
|
+
return client.POST("/v1/scrape/tiktok/trending", { body });
|
|
173
|
+
},
|
|
174
|
+
scrapeTikTokVideo(body) {
|
|
175
|
+
return client.POST("/v1/scrape/tiktok/video", { body });
|
|
176
|
+
},
|
|
177
|
+
scrapeTikTokVideoComments(body) {
|
|
178
|
+
return client.POST("/v1/scrape/tiktok/video/comments", { body });
|
|
179
|
+
},
|
|
180
|
+
scrapeTikTokVideoTranscript(body) {
|
|
181
|
+
return client.POST("/v1/scrape/tiktok/video/transcript", { body });
|
|
182
|
+
},
|
|
96
183
|
createSubscription(body) {
|
|
97
184
|
return client.POST("/v1/subscribe", { body });
|
|
98
185
|
},
|
|
@@ -108,6 +195,15 @@ export function bindMethods(client) {
|
|
|
108
195
|
getUsage() {
|
|
109
196
|
return client.GET("/v1/usage", {});
|
|
110
197
|
},
|
|
198
|
+
addVideo(body) {
|
|
199
|
+
return client.POST("/v1/videos/add", { body });
|
|
200
|
+
},
|
|
201
|
+
downloadInstagramVideo(body) {
|
|
202
|
+
return client.POST("/v1/videos/download/instagram", { body });
|
|
203
|
+
},
|
|
204
|
+
downloadTikTokVideo(body) {
|
|
205
|
+
return client.POST("/v1/videos/download/tiktok", { body });
|
|
206
|
+
},
|
|
111
207
|
watchMedia(body) {
|
|
112
208
|
return client.POST("/v1/watch", { body });
|
|
113
209
|
},
|