faceless-cli 1.0.0 → 1.1.5
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/package.json +35 -35
- package/src/generated/operations.json +110 -1
- package/src/index.mjs +13 -0
package/package.json
CHANGED
|
@@ -1,37 +1,37 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
2
|
+
"name": "faceless-cli",
|
|
3
|
+
"version": "1.1.5",
|
|
4
|
+
"description": "CLI for Faceless.so: create AI faceless videos, run automated series and publish to YouTube, TikTok, Instagram and more.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"faceless": "bin/faceless.js",
|
|
8
|
+
"fcl": "bin/faceless.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"bin",
|
|
12
|
+
"src",
|
|
13
|
+
"README.md",
|
|
14
|
+
"LICENSE"
|
|
15
|
+
],
|
|
16
|
+
"engines": {
|
|
17
|
+
"node": ">=18"
|
|
18
|
+
},
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"homepage": "https://faceless.so",
|
|
21
|
+
"keywords": [
|
|
22
|
+
"faceless",
|
|
23
|
+
"cli",
|
|
24
|
+
"mcp",
|
|
25
|
+
"ai",
|
|
26
|
+
"video",
|
|
27
|
+
"faceless-video",
|
|
28
|
+
"youtube",
|
|
29
|
+
"tiktok",
|
|
30
|
+
"social-media",
|
|
31
|
+
"scheduling"
|
|
32
|
+
],
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
35
|
+
"commander": "^13.0.0"
|
|
36
|
+
}
|
|
37
37
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"generatedFrom": "src/backend/api/v1/spec/registry.mjs",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.5",
|
|
4
4
|
"baseUrl": "https://faceless.so/api/v1",
|
|
5
5
|
"operations": [
|
|
6
6
|
{
|
|
@@ -363,6 +363,24 @@
|
|
|
363
363
|
"voiceId": "EXAVITQu4vr4xnSDxMaL",
|
|
364
364
|
"status": "completed",
|
|
365
365
|
"renderedVideoUrl": "https://exports.faceless.so/renders/665f1b2a9c31a2b3c4d5e801/1722333444555.mp4",
|
|
366
|
+
"thumbnailUrl": "https://exports.faceless.so/thumbnails/665f1b2a9c31a2b3c4d5e801/1/a1b2c3d4.jpg",
|
|
367
|
+
"thumbnails": {
|
|
368
|
+
"status": "ready",
|
|
369
|
+
"generation": 1,
|
|
370
|
+
"aspect": "9:16",
|
|
371
|
+
"selectedVariantId": "a1b2c3d4-0000-4000-8000-000000000001",
|
|
372
|
+
"selectedBy": "ai",
|
|
373
|
+
"variants": [
|
|
374
|
+
{
|
|
375
|
+
"id": "a1b2c3d4-0000-4000-8000-000000000001",
|
|
376
|
+
"url": "https://exports.faceless.so/thumbnails/665f1b2a9c31a2b3c4d5e801/1/a1b2c3d4.jpg",
|
|
377
|
+
"hookText": "OCEAN RIVERS",
|
|
378
|
+
"source": "ai",
|
|
379
|
+
"score": 88,
|
|
380
|
+
"grade": "S"
|
|
381
|
+
}
|
|
382
|
+
]
|
|
383
|
+
},
|
|
366
384
|
"createdAt": "2026-07-30T10:00:00.000Z"
|
|
367
385
|
}
|
|
368
386
|
}
|
|
@@ -535,6 +553,65 @@
|
|
|
535
553
|
"name": "Ocean facts",
|
|
536
554
|
"youtubePost": {
|
|
537
555
|
"title": "The ocean has rivers underwater"
|
|
556
|
+
},
|
|
557
|
+
"thumbnailUrl": "https://exports.faceless.so/thumbnails/665f1b2a9c31a2b3c4d5e801/1/a1b2c3d4.jpg",
|
|
558
|
+
"thumbnails": {
|
|
559
|
+
"status": "ready",
|
|
560
|
+
"selectedBy": "ai",
|
|
561
|
+
"variants": []
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
},
|
|
566
|
+
{
|
|
567
|
+
"operationId": "selectVideoThumbnail",
|
|
568
|
+
"method": "post",
|
|
569
|
+
"path": "/videos/{id}/thumbnail",
|
|
570
|
+
"resource": "videos",
|
|
571
|
+
"summary": "Choose which thumbnail a video uses",
|
|
572
|
+
"description": "Selects one of the video's thumbnail variants as the effective thumbnail. Read the available variants from GET /videos/{id} (the thumbnails object). The choice is marked as a user pick, so later automatic regenerations will not overwrite it, and it is what gets pushed to YouTube and used as the Instagram Reels cover at post time. Thumbnails are free and generated automatically after a video completes.",
|
|
573
|
+
"scopes": [
|
|
574
|
+
"videos:write"
|
|
575
|
+
],
|
|
576
|
+
"status": 200,
|
|
577
|
+
"idempotent": false,
|
|
578
|
+
"terminalStates": null,
|
|
579
|
+
"creditCost": "none",
|
|
580
|
+
"cli": {
|
|
581
|
+
"command": "videos select-thumbnail"
|
|
582
|
+
},
|
|
583
|
+
"mcp": {
|
|
584
|
+
"name": "faceless_select_video_thumbnail",
|
|
585
|
+
"enabled": true
|
|
586
|
+
},
|
|
587
|
+
"querySchema": null,
|
|
588
|
+
"requestSchema": {
|
|
589
|
+
"type": "object",
|
|
590
|
+
"properties": {
|
|
591
|
+
"variantId": {
|
|
592
|
+
"type": "string",
|
|
593
|
+
"minLength": 1,
|
|
594
|
+
"description": "Variant id from the thumbnails.variants array on GET /videos/{id}"
|
|
595
|
+
}
|
|
596
|
+
},
|
|
597
|
+
"required": [
|
|
598
|
+
"variantId"
|
|
599
|
+
],
|
|
600
|
+
"additionalProperties": false
|
|
601
|
+
},
|
|
602
|
+
"requestExample": {
|
|
603
|
+
"variantId": "a1b2c3d4-0000-4000-8000-000000000002"
|
|
604
|
+
},
|
|
605
|
+
"responseExample": {
|
|
606
|
+
"success": true,
|
|
607
|
+
"data": {
|
|
608
|
+
"id": "665f1b2a9c31a2b3c4d5e801",
|
|
609
|
+
"thumbnailUrl": "https://exports.faceless.so/thumbnails/665f1b2a9c31a2b3c4d5e801/1/b2c3d4e5.jpg",
|
|
610
|
+
"thumbnails": {
|
|
611
|
+
"status": "ready",
|
|
612
|
+
"selectedVariantId": "a1b2c3d4-0000-4000-8000-000000000002",
|
|
613
|
+
"selectedBy": "user",
|
|
614
|
+
"variants": []
|
|
538
615
|
}
|
|
539
616
|
}
|
|
540
617
|
}
|
|
@@ -770,6 +847,22 @@
|
|
|
770
847
|
},
|
|
771
848
|
"description": "Connected account ids to auto-post to (from GET /accounts)"
|
|
772
849
|
},
|
|
850
|
+
"generateThumbnails": {
|
|
851
|
+
"type": "boolean",
|
|
852
|
+
"description": "Generate 3 AI thumbnail variants for every episode and auto-select the best. Free. Defaults to true."
|
|
853
|
+
},
|
|
854
|
+
"thumbnailSettings": {
|
|
855
|
+
"type": "object",
|
|
856
|
+
"properties": {
|
|
857
|
+
"styleHint": {
|
|
858
|
+
"type": "string",
|
|
859
|
+
"maxLength": 200,
|
|
860
|
+
"description": "Free-text art direction for the thumbnail backgrounds, e.g. \"moody neon, close-up faces\""
|
|
861
|
+
}
|
|
862
|
+
},
|
|
863
|
+
"additionalProperties": false,
|
|
864
|
+
"description": "Thumbnail generation options. Ignored when generateThumbnails is false."
|
|
865
|
+
},
|
|
773
866
|
"autoPostTime": {
|
|
774
867
|
"type": "string",
|
|
775
868
|
"description": "Daily auto-post time \"HH:mm\" in the series timezone"
|
|
@@ -1015,6 +1108,22 @@
|
|
|
1015
1108
|
},
|
|
1016
1109
|
"description": "Connected account ids to auto-post to (from GET /accounts)"
|
|
1017
1110
|
},
|
|
1111
|
+
"generateThumbnails": {
|
|
1112
|
+
"type": "boolean",
|
|
1113
|
+
"description": "Generate 3 AI thumbnail variants for every episode and auto-select the best. Free. Defaults to true."
|
|
1114
|
+
},
|
|
1115
|
+
"thumbnailSettings": {
|
|
1116
|
+
"type": "object",
|
|
1117
|
+
"properties": {
|
|
1118
|
+
"styleHint": {
|
|
1119
|
+
"type": "string",
|
|
1120
|
+
"maxLength": 200,
|
|
1121
|
+
"description": "Free-text art direction for the thumbnail backgrounds, e.g. \"moody neon, close-up faces\""
|
|
1122
|
+
}
|
|
1123
|
+
},
|
|
1124
|
+
"additionalProperties": false,
|
|
1125
|
+
"description": "Thumbnail generation options. Ignored when generateThumbnails is false."
|
|
1126
|
+
},
|
|
1018
1127
|
"autoPostTime": {
|
|
1019
1128
|
"type": "string",
|
|
1020
1129
|
"description": "Daily auto-post time \"HH:mm\" in the series timezone"
|
package/src/index.mjs
CHANGED
|
@@ -435,6 +435,19 @@ videos
|
|
|
435
435
|
print(result, { json: cmd.optsWithGlobals().json });
|
|
436
436
|
});
|
|
437
437
|
|
|
438
|
+
videos
|
|
439
|
+
.command("select-thumbnail <id>")
|
|
440
|
+
.description(getOp("selectVideoThumbnail").summary)
|
|
441
|
+
.requiredOption("--variant <variantId>", "variant id from the thumbnails.variants array on `faceless videos get <id>`")
|
|
442
|
+
.action(async (id, opts, cmd) => {
|
|
443
|
+
const result = await execute(
|
|
444
|
+
"selectVideoThumbnail",
|
|
445
|
+
{ pathParams: { id }, body: { variantId: opts.variant } },
|
|
446
|
+
cmd
|
|
447
|
+
);
|
|
448
|
+
print(result, { json: cmd.optsWithGlobals().json });
|
|
449
|
+
});
|
|
450
|
+
|
|
438
451
|
withWaitFlags(
|
|
439
452
|
videos.command("status <id>").description(getOp("getVideoStatus").summary),
|
|
440
453
|
"video"
|