@remixmate/cli 0.1.0 → 0.1.1
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 +100 -83
- package/README.zh-CN.md +183 -0
- package/dist/handlers/gen-digital-human.d.ts +12 -0
- package/dist/handlers/gen-digital-human.js +157 -0
- package/dist/handlers/gen-image.js +5 -41
- package/dist/handlers/gen-video.d.ts +18 -0
- package/dist/handlers/gen-video.js +153 -0
- package/dist/handlers/gen-voice.js +2 -12
- package/dist/handlers/index.js +4 -2
- package/dist/handlers/shared.d.ts +26 -0
- package/dist/handlers/shared.js +66 -0
- package/dist/http.d.ts +4 -2
- package/dist/http.js +5 -3
- package/dist/manifest.json +27 -24
- package/dist/registry.d.ts +5 -16
- package/dist/registry.js +11 -17
- package/dist/skill-schema.d.ts +47 -0
- package/dist/skill-schema.js +49 -0
- package/package.json +5 -4
- package/skills/export-jianying/scripts/gen_jianying_draft.py +4 -4
- package/skills/gen-digital-human/SKILL.md +23 -46
- package/skills/gen-digital-human/skill.json +3 -2
- package/skills/gen-digital-human/version.json +1 -1
- package/skills/gen-image/SKILL.md +2 -2
- package/skills/gen-image/skill.json +2 -1
- package/skills/gen-image/version.json +1 -1
- package/skills/gen-script/SKILL.md +13 -13
- package/skills/gen-script/scripts/gen_script.py +11 -12
- package/skills/gen-video/SKILL.md +22 -33
- package/skills/gen-video/skill.json +3 -2
- package/skills/gen-video/version.json +1 -1
- package/skills/gen-voice/SKILL.md +1 -1
- package/skills/gen-voice/version.json +1 -1
- package/skills/prepare-video-assets/SKILL.md +2 -2
- package/skills/prepare-video-assets/skill.json +1 -1
- package/skills/render-video/scripts/render_video.py +8 -8
- package/skills/{template-bind → template-registry}/README.md +4 -4
- package/skills/{template-bind → template-registry}/SKILL.md +14 -12
- package/skills/template-registry/scripts/list_templates.py +129 -0
- package/skills/{template-bind → template-registry}/scripts/match_template.py +4 -3
- package/skills/{template-bind → template-registry}/scripts/registry_loader.py +1 -1
- package/skills/{template-bind → template-registry}/scripts/template_paths.py +7 -7
- package/skills/{template-bind → template-registry}/skill.json +6 -5
- package/skills/template-registry/version.json +7 -0
- package/skills/{template-bind → template-registry}/video_dsl/README.md +2 -2
- package/skills/{template-bind → template-registry}/video_dsl/runtime/__init__.py +1 -1
- package/skills/video-parser/SKILL.md +47 -160
- package/skills/video-parser/skill.json +3 -4
- package/skills/video-parser/version.json +1 -1
- package/skills/web-capture/SKILL.md +407 -116
- package/skills/web-capture/scripts/_media_screenshot/__init__.py +21 -0
- package/skills/web-capture/scripts/_media_screenshot/bootstrap.py +34 -0
- package/skills/web-capture/scripts/_media_screenshot/browser.py +86 -0
- package/skills/web-capture/scripts/_media_screenshot/cli_args.py +111 -0
- package/skills/web-capture/scripts/_media_screenshot/js/arrow.js +86 -0
- package/skills/web-capture/scripts/_media_screenshot/js/caption.js +27 -0
- package/skills/web-capture/scripts/_media_screenshot/js/clear_overlay.js +5 -0
- package/skills/web-capture/scripts/_media_screenshot/js/cursor_bootstrap.js +26 -0
- package/skills/web-capture/scripts/_media_screenshot/js/cursor_hide.js +6 -0
- package/skills/web-capture/scripts/_media_screenshot/js/cursor_move.js +12 -0
- package/skills/web-capture/scripts/_media_screenshot/js/cursor_ripple.js +25 -0
- package/skills/web-capture/scripts/_media_screenshot/js/element_zoom.js +72 -0
- package/skills/web-capture/scripts/_media_screenshot/js/element_zoom_restore.js +21 -0
- package/skills/web-capture/scripts/_media_screenshot/js/fade_out_overlays.js +10 -0
- package/skills/web-capture/scripts/_media_screenshot/js/focus.js +38 -0
- package/skills/web-capture/scripts/_media_screenshot/js/highlight.js +97 -0
- package/skills/web-capture/scripts/_media_screenshot/js/overlay_bootstrap.js +19 -0
- package/skills/web-capture/scripts/_media_screenshot/js/page_zoom_in.js +54 -0
- package/skills/web-capture/scripts/_media_screenshot/js/page_zoom_out.js +11 -0
- package/skills/web-capture/scripts/_media_screenshot/js/page_zoom_restore.js +13 -0
- package/skills/web-capture/scripts/_media_screenshot/js/redact.js +33 -0
- package/skills/web-capture/scripts/_media_screenshot/js/scroll.js +26 -0
- package/skills/web-capture/scripts/_media_screenshot/js/scroll_through.js +18 -0
- package/skills/web-capture/scripts/_media_screenshot/js/sequence.js +76 -0
- package/skills/web-capture/scripts/_media_screenshot/js/settled_check.js +15 -0
- package/skills/web-capture/scripts/_media_screenshot/js/title_card.js +71 -0
- package/skills/web-capture/scripts/_media_screenshot/js_loader.py +14 -0
- package/skills/web-capture/scripts/_media_screenshot/overlay.py +17 -0
- package/skills/web-capture/scripts/_media_screenshot/recording.py +100 -0
- package/skills/web-capture/scripts/_media_screenshot/scenes/__init__.py +39 -0
- package/skills/web-capture/scripts/_media_screenshot/scenes/arrow.py +50 -0
- package/skills/web-capture/scripts/_media_screenshot/scenes/caption.py +20 -0
- package/skills/web-capture/scripts/_media_screenshot/scenes/click.py +35 -0
- package/skills/web-capture/scripts/_media_screenshot/scenes/code_lines.py +54 -0
- package/skills/web-capture/scripts/_media_screenshot/scenes/focus.py +24 -0
- package/skills/web-capture/scripts/_media_screenshot/scenes/highlight.py +54 -0
- package/skills/web-capture/scripts/_media_screenshot/scenes/hover.py +28 -0
- package/skills/web-capture/scripts/_media_screenshot/scenes/redact.py +32 -0
- package/skills/web-capture/scripts/_media_screenshot/scenes/scroll.py +32 -0
- package/skills/web-capture/scripts/_media_screenshot/scenes/sequence.py +43 -0
- package/skills/web-capture/scripts/_media_screenshot/scenes/title_card.py +20 -0
- package/skills/web-capture/scripts/_media_screenshot/scenes/type.py +42 -0
- package/skills/web-capture/scripts/_media_screenshot/scenes/wait.py +9 -0
- package/skills/web-capture/scripts/_media_screenshot/scenes/zoom.py +72 -0
- package/skills/web-capture/scripts/_media_screenshot/screenshot.py +166 -0
- package/skills/web-capture/scripts/_media_screenshot/storyboard.py +88 -0
- package/skills/web-capture/scripts/_media_screenshot/template.py +119 -0
- package/skills/web-capture/scripts/_media_screenshot/trim.py +82 -0
- package/skills/web-capture/scripts/record.py +186 -0
- package/skills/web-capture/scripts/screenshot.py +94 -0
- package/skills/web-capture/skill.json +14 -14
- package/skills/web-capture/templates/github-code-tour.json +59 -0
- package/skills/web-capture/templates/github-readme-tour.json +77 -0
- package/skills/web-capture/templates/github-repo-intro.json +74 -0
- package/skills/web-capture/version.json +2 -2
- package/dist/handlers/template-bind.d.ts +0 -15
- package/dist/handlers/template-bind.js +0 -149
- package/skills/gen-digital-human/scripts/gen_digital_human_video.py +0 -574
- package/skills/gen-video/scripts/gen_video.py +0 -591
- package/skills/template-bind/version.json +0 -7
- package/skills/web-capture/scripts/web_capture.py +0 -461
- /package/skills/{template-bind → template-registry}/scripts/check_contracts.py +0 -0
- /package/skills/{template-bind → template-registry}/scripts/render_job_client.py +0 -0
- /package/skills/{template-bind → template-registry}/scripts/sync_registry.py +0 -0
- /package/skills/{template-bind → template-registry}/video_dsl/runtime/dsl_validator.py +0 -0
- /package/skills/{template-bind → template-registry}/video_dsl/runtime/prompt_enhancer.py +0 -0
- /package/skills/{template-bind → template-registry}/video_dsl/runtime/template_binder.py +0 -0
- /package/skills/{template-bind → template-registry}/video_dsl/runtime/timeline_compiler.py +0 -0
- /package/skills/{template-bind → template-registry}/video_dsl/schema/render-plan-v1alpha1.json +0 -0
- /package/skills/{template-bind → template-registry}/video_dsl/schema/template-binding-v1alpha1.json +0 -0
- /package/skills/{template-bind → template-registry}/video_dsl/schema/template-definition-v1alpha1.json +0 -0
- /package/skills/{template-bind → template-registry}/video_dsl/schema/video-dsl-v1alpha1.json +0 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single source of truth for skill.json shape + validation.
|
|
3
|
+
*
|
|
4
|
+
* Imported directly by `registry.ts` (runtime loader) and — via the compiled
|
|
5
|
+
* `dist/skill-schema.js` — by `scripts/build-manifest.mjs` and `scripts/smoke.mjs`.
|
|
6
|
+
* Previously each of those reimplemented `normalizeEntry` and its own subset of
|
|
7
|
+
* field checks, so "valid at build" ≠ "loadable at runtime". Centralizing here
|
|
8
|
+
* means one definition of a well-formed skill.
|
|
9
|
+
*
|
|
10
|
+
* Error policy is the caller's choice: `validateSkillJson` returns a list of
|
|
11
|
+
* human-readable problems (empty = OK). The runtime loader skips + warns;
|
|
12
|
+
* the build treats them as fatal.
|
|
13
|
+
*/
|
|
14
|
+
export type SkillEntry = {
|
|
15
|
+
type: 'python';
|
|
16
|
+
scriptPath: string;
|
|
17
|
+
} | {
|
|
18
|
+
type: 'http';
|
|
19
|
+
handler: string;
|
|
20
|
+
} | {
|
|
21
|
+
type: 'builtin';
|
|
22
|
+
handler: string;
|
|
23
|
+
};
|
|
24
|
+
export interface RawSkillJson {
|
|
25
|
+
name: string;
|
|
26
|
+
toolName: string;
|
|
27
|
+
description: string;
|
|
28
|
+
title?: string;
|
|
29
|
+
tier?: string;
|
|
30
|
+
parameters?: Record<string, unknown>;
|
|
31
|
+
scriptPath?: string;
|
|
32
|
+
entry?: SkillEntry;
|
|
33
|
+
envVars?: string[];
|
|
34
|
+
}
|
|
35
|
+
export declare const TIER_VALUES: readonly ["atomic", "orchestration", "tool"];
|
|
36
|
+
export declare const REQUIRED_SKILL_JSON_FIELDS: readonly ["name", "tier", "title", "description"];
|
|
37
|
+
/**
|
|
38
|
+
* Resolve the dispatcher entry. A missing `entry` falls back to the legacy
|
|
39
|
+
* top-level `scriptPath`, treated as `{ type: 'python', scriptPath }` so older
|
|
40
|
+
* skills keep working untouched. Returns null when neither is present.
|
|
41
|
+
*/
|
|
42
|
+
export declare function normalizeEntry(raw: Pick<RawSkillJson, 'entry' | 'scriptPath'>): SkillEntry | null;
|
|
43
|
+
/**
|
|
44
|
+
* Validate a parsed skill.json against the directory it lives in. Returns an
|
|
45
|
+
* array of problem strings; an empty array means the record is well-formed.
|
|
46
|
+
*/
|
|
47
|
+
export declare function validateSkillJson(raw: RawSkillJson, skillId: string): string[];
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single source of truth for skill.json shape + validation.
|
|
3
|
+
*
|
|
4
|
+
* Imported directly by `registry.ts` (runtime loader) and — via the compiled
|
|
5
|
+
* `dist/skill-schema.js` — by `scripts/build-manifest.mjs` and `scripts/smoke.mjs`.
|
|
6
|
+
* Previously each of those reimplemented `normalizeEntry` and its own subset of
|
|
7
|
+
* field checks, so "valid at build" ≠ "loadable at runtime". Centralizing here
|
|
8
|
+
* means one definition of a well-formed skill.
|
|
9
|
+
*
|
|
10
|
+
* Error policy is the caller's choice: `validateSkillJson` returns a list of
|
|
11
|
+
* human-readable problems (empty = OK). The runtime loader skips + warns;
|
|
12
|
+
* the build treats them as fatal.
|
|
13
|
+
*/
|
|
14
|
+
export const TIER_VALUES = ['atomic', 'orchestration', 'tool'];
|
|
15
|
+
export const REQUIRED_SKILL_JSON_FIELDS = ['name', 'tier', 'title', 'description'];
|
|
16
|
+
/**
|
|
17
|
+
* Resolve the dispatcher entry. A missing `entry` falls back to the legacy
|
|
18
|
+
* top-level `scriptPath`, treated as `{ type: 'python', scriptPath }` so older
|
|
19
|
+
* skills keep working untouched. Returns null when neither is present.
|
|
20
|
+
*/
|
|
21
|
+
export function normalizeEntry(raw) {
|
|
22
|
+
if (raw.entry)
|
|
23
|
+
return raw.entry;
|
|
24
|
+
if (raw.scriptPath)
|
|
25
|
+
return { type: 'python', scriptPath: raw.scriptPath };
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Validate a parsed skill.json against the directory it lives in. Returns an
|
|
30
|
+
* array of problem strings; an empty array means the record is well-formed.
|
|
31
|
+
*/
|
|
32
|
+
export function validateSkillJson(raw, skillId) {
|
|
33
|
+
const errors = [];
|
|
34
|
+
for (const field of REQUIRED_SKILL_JSON_FIELDS) {
|
|
35
|
+
const value = raw[field];
|
|
36
|
+
if (value == null || value === '')
|
|
37
|
+
errors.push(`skill.json missing required field '${field}'`);
|
|
38
|
+
}
|
|
39
|
+
if (raw.tier != null && !TIER_VALUES.includes(raw.tier)) {
|
|
40
|
+
errors.push(`skill.json.tier must be one of ${TIER_VALUES.join(' | ')}, got '${raw.tier}'`);
|
|
41
|
+
}
|
|
42
|
+
if (raw.name && raw.name !== skillId) {
|
|
43
|
+
errors.push(`skill.json.name='${raw.name}' does not match directory name '${skillId}'`);
|
|
44
|
+
}
|
|
45
|
+
if (!normalizeEntry(raw)) {
|
|
46
|
+
errors.push("skill.json missing 'entry' (or legacy 'scriptPath')");
|
|
47
|
+
}
|
|
48
|
+
return errors;
|
|
49
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remixmate/cli",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "AI media generation skills for Claude Code / Codex —
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "AI media generation skills for Claude Code / Codex — 11 skills covering image, video, voice, digital human, web capture, script, template registry, rendering, Jianying export, and video deconstruction.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
@@ -15,13 +15,14 @@
|
|
|
15
15
|
"LICENSE"
|
|
16
16
|
],
|
|
17
17
|
"scripts": {
|
|
18
|
-
"build": "tsc && node scripts/build-manifest.mjs",
|
|
18
|
+
"build": "node scripts/clean-dist.mjs && tsc && node scripts/build-manifest.mjs",
|
|
19
19
|
"prepare": "npm run build",
|
|
20
20
|
"list": "node dist/cli.js --list",
|
|
21
21
|
"smoke": "node scripts/smoke.mjs",
|
|
22
|
+
"test:cli": "npm run build && node --test test/*.test.mjs",
|
|
22
23
|
"test:validators": "PYTHONDONTWRITEBYTECODE=1 python3 scripts/test-validators.py",
|
|
23
24
|
"test:template-pipeline": "PYTHONDONTWRITEBYTECODE=1 python3 scripts/test-template-pipeline.py",
|
|
24
|
-
"test:contracts": "PYTHONDONTWRITEBYTECODE=1 python3 skills/template-
|
|
25
|
+
"test:contracts": "PYTHONDONTWRITEBYTECODE=1 python3 skills/template-registry/scripts/check_contracts.py",
|
|
25
26
|
"clean": "node scripts/clean.mjs"
|
|
26
27
|
},
|
|
27
28
|
"keywords": [
|
|
@@ -986,13 +986,13 @@ Scene fields:
|
|
|
986
986
|
if not PRIVATE_TOKEN:
|
|
987
987
|
print("❌ --from-job-id mode requires PRIV_TOKEN", file=sys.stderr)
|
|
988
988
|
sys.exit(1)
|
|
989
|
-
# render_job_client lives in skills/template-
|
|
989
|
+
# render_job_client lives in skills/template-registry/scripts/ — the
|
|
990
990
|
# shared location for cross-skill Python helpers (matches the pattern
|
|
991
991
|
# render-video uses for the same import).
|
|
992
|
-
|
|
993
|
-
os.path.dirname(__file__), "..", "..", "template-
|
|
992
|
+
_template_registry_scripts = os.path.join(
|
|
993
|
+
os.path.dirname(__file__), "..", "..", "template-registry", "scripts"
|
|
994
994
|
)
|
|
995
|
-
sys.path.insert(0,
|
|
995
|
+
sys.path.insert(0, _template_registry_scripts)
|
|
996
996
|
from render_job_client import get_plan as rjc_get_plan
|
|
997
997
|
try:
|
|
998
998
|
render_plan_str = rjc_get_plan(args.from_job_id, PRIVATE_TOKEN)
|
|
@@ -19,7 +19,9 @@ triggers:
|
|
|
19
19
|
|
|
20
20
|
# Digital-Human Skill
|
|
21
21
|
|
|
22
|
-
Wraps ab-api's digital-human endpoints (the same ones the web studio uses), authenticated with the **Tianyan privateToken**. Two providers: **Jimeng** (image-driven) and **HiFly** (video-driven).
|
|
22
|
+
Wraps ab-api's digital-human endpoints (the same ones the web studio uses), authenticated with the **Tianyan privateToken**. Two providers: **Jimeng** (image-driven) and **HiFly** (video-driven). Generation is async — the handler submits the task and polls `/digital-human/video/status` until completion.
|
|
23
|
+
|
|
24
|
+
> This skill was migrated from a Python script to an ab-skill CLI HTTP handler (`entry.type: http`). The agent invocation is unchanged (same tool name `gen_digital_human`, same params as in `skill.json`); local repro goes through `ab-skill gen-digital-human ...`.
|
|
23
25
|
|
|
24
26
|
## Capabilities
|
|
25
27
|
|
|
@@ -34,54 +36,52 @@ Wraps ab-api's digital-human endpoints (the same ones the web studio uses), auth
|
|
|
34
36
|
|
|
35
37
|
## Auth & environment
|
|
36
38
|
|
|
37
|
-
No skill-local env file — the executing process inherits the system environment.
|
|
39
|
+
No skill-local env file — the executing process inherits the system environment.
|
|
38
40
|
|
|
39
41
|
- **Enterprise OpenClaw**: auth is already injected, **no need** for `PRIV_TOKEN` / `--priv-token`.
|
|
40
|
-
- **Other environments**: configure the token. Without a token, non-interactive runs fail
|
|
42
|
+
- **Other environments**: configure the token. Without a token, non-interactive runs fail.
|
|
41
43
|
|
|
42
44
|
| Env var | Description | Default |
|
|
43
45
|
|---------|-------------|---------|
|
|
44
46
|
| `PRIV_TOKEN` | Tianyan token; `--priv-token` overrides | none |
|
|
45
|
-
| `MM_API_BASE_URL` | API root |
|
|
47
|
+
| `MM_API_BASE_URL` | API root; `--api-base-url` overrides | `http://localhost:2999/api` |
|
|
46
48
|
| `AGENT_NAME` | Optional `x-invoke-agent` header | none |
|
|
47
49
|
|
|
48
50
|
## Operations
|
|
49
51
|
|
|
50
|
-
|
|
52
|
+
By default only the URL is printed; generation is async and the handler polls until done (typically 1–5 minutes), emitting `__progress__` lines. The resulting video URL is cloud-persisted — show it directly, no download needed.
|
|
51
53
|
|
|
52
54
|
### 1. List avatars
|
|
53
55
|
|
|
54
56
|
```bash
|
|
55
|
-
|
|
57
|
+
ab-skill gen-digital-human --list-avatars
|
|
56
58
|
```
|
|
57
59
|
|
|
58
60
|
Optional filters:
|
|
59
61
|
|
|
60
62
|
```bash
|
|
61
63
|
# Filter by source (jimeng = image-driven, hifly = video-driven)
|
|
62
|
-
|
|
63
|
-
|
|
64
|
+
ab-skill gen-digital-human --list-avatars --source jimeng
|
|
65
|
+
ab-skill gen-digital-human --list-avatars --source hifly
|
|
64
66
|
|
|
65
67
|
# Filter by gender
|
|
66
|
-
|
|
68
|
+
ab-skill gen-digital-human --list-avatars --gender female
|
|
67
69
|
|
|
68
70
|
# Show your custom avatars
|
|
69
|
-
|
|
71
|
+
ab-skill gen-digital-human --list-avatars --mine
|
|
70
72
|
|
|
71
73
|
# Filter by name
|
|
72
|
-
|
|
74
|
+
ab-skill gen-digital-human --list-avatars --name "alice"
|
|
73
75
|
```
|
|
74
76
|
|
|
75
|
-
> Custom avatars require `--mine`. When generating a video the
|
|
77
|
+
> Custom avatars require `--mine`. When generating a video the handler auto-falls back from the public list to `mine: true` if needed.
|
|
76
78
|
|
|
77
79
|
### 2. Generate a digital-human video
|
|
78
80
|
|
|
79
|
-
By default only the URL is printed; pass `--download` (and optional `--output`) to save locally. Generation is async; the script polls until done (typically 1–5 minutes).
|
|
80
|
-
|
|
81
81
|
#### TTS mode
|
|
82
82
|
|
|
83
83
|
```bash
|
|
84
|
-
|
|
84
|
+
ab-skill gen-digital-human \
|
|
85
85
|
--avatar-id 7 \
|
|
86
86
|
--text "Hi everyone, welcome to the live stream — today I'll introduce a new product." \
|
|
87
87
|
--voice-id "male-qn-qingse"
|
|
@@ -90,7 +90,7 @@ python3 <SkillDir>/scripts/gen_digital_human_video.py \
|
|
|
90
90
|
#### TTS + custom voice + aspect ratio
|
|
91
91
|
|
|
92
92
|
```bash
|
|
93
|
-
|
|
93
|
+
ab-skill gen-digital-human \
|
|
94
94
|
--avatar-id 7 \
|
|
95
95
|
--text "Hi class, here's our brand-new course." \
|
|
96
96
|
--voice-id "female-shaonv" \
|
|
@@ -100,37 +100,19 @@ python3 <SkillDir>/scripts/gen_digital_human_video.py \
|
|
|
100
100
|
#### Audio-driven mode
|
|
101
101
|
|
|
102
102
|
```bash
|
|
103
|
-
|
|
103
|
+
ab-skill gen-digital-human \
|
|
104
104
|
--avatar-id 39 \
|
|
105
105
|
--source hifly \
|
|
106
106
|
--audio-url "https://example.com/voice.mp3" \
|
|
107
107
|
--aspect-ratio "16:9"
|
|
108
108
|
```
|
|
109
109
|
|
|
110
|
-
#### Download to disk
|
|
111
|
-
|
|
112
|
-
```bash
|
|
113
|
-
python3 <SkillDir>/scripts/gen_digital_human_video.py \
|
|
114
|
-
--avatar-id 7 \
|
|
115
|
-
--text "Hello world" \
|
|
116
|
-
--download \
|
|
117
|
-
--output "digital_human_output.mp4"
|
|
118
|
-
```
|
|
119
|
-
|
|
120
110
|
### 3. Check job status
|
|
121
111
|
|
|
122
112
|
```bash
|
|
123
|
-
|
|
124
|
-
python3 <SkillDir>/scripts/gen_digital_human_video.py \
|
|
125
|
-
--check-status --generation-id 123
|
|
126
|
-
|
|
127
|
-
# Download once it's done
|
|
128
|
-
python3 <SkillDir>/scripts/gen_digital_human_video.py \
|
|
129
|
-
--check-status --generation-id 123 --download --output result.mp4
|
|
113
|
+
ab-skill gen-digital-human --check-status --generation-id 123
|
|
130
114
|
```
|
|
131
115
|
|
|
132
|
-
For the full flag list: `python3 <SkillDir>/scripts/gen_digital_human_video.py --help`.
|
|
133
|
-
|
|
134
116
|
## Common CLI flags
|
|
135
117
|
|
|
136
118
|
### List avatars
|
|
@@ -155,11 +137,8 @@ For the full flag list: `python3 <SkillDir>/scripts/gen_digital_human_video.py -
|
|
|
155
137
|
| `--source` | `jimeng` / `hifly` (inferable from avatar) | auto |
|
|
156
138
|
| `--aspect-ratio` | `9:16` / `16:9` / `3:4` / `1:1` | avatar's default |
|
|
157
139
|
| `--prompt` | Action prompt (e.g. "more hand gestures") | none |
|
|
158
|
-
| `--
|
|
159
|
-
|
|
|
160
|
-
| `--poll-interval` | Polling interval (seconds) | `5` |
|
|
161
|
-
| `--max-wait` | Max wait time (seconds) | `600` |
|
|
162
|
-
| `--private-token` | Override token | see env vars |
|
|
140
|
+
| `--api-base-url` | Override API root | see env vars |
|
|
141
|
+
| `--priv-token` | Override token | see env vars |
|
|
163
142
|
|
|
164
143
|
### Check status
|
|
165
144
|
|
|
@@ -167,8 +146,6 @@ For the full flag list: `python3 <SkillDir>/scripts/gen_digital_human_video.py -
|
|
|
167
146
|
|------|-------------|---------|
|
|
168
147
|
| `--check-status` | Enter status-check mode | — |
|
|
169
148
|
| `--generation-id` | Job id (required) | — |
|
|
170
|
-
| `--download` | Download when finished | off |
|
|
171
|
-
| `-o` / `--output` | Download path | `digital_human_video.mp4` |
|
|
172
149
|
|
|
173
150
|
## Typical flows
|
|
174
151
|
|
|
@@ -180,7 +157,7 @@ For the full flag list: `python3 <SkillDir>/scripts/gen_digital_human_video.py -
|
|
|
180
157
|
3. Confirm or polish the speech text
|
|
181
158
|
4. (Optional) pick a voice → use gen-voice --list-voices
|
|
182
159
|
5. Generate → --avatar-id <id> --text "..." --voice-id "female-shaonv"
|
|
183
|
-
6. Show URL
|
|
160
|
+
6. Show URL
|
|
184
161
|
```
|
|
185
162
|
|
|
186
163
|
### Flow B — Audio-driven
|
|
@@ -189,7 +166,7 @@ For the full flag list: `python3 <SkillDir>/scripts/gen_digital_human_video.py -
|
|
|
189
166
|
1. List avatars → --list-avatars [--mine]
|
|
190
167
|
2. Prepare an audio URL (gen-voice can produce one)
|
|
191
168
|
3. Generate → --avatar-id <id> --audio-url "https://..." [--source hifly]
|
|
192
|
-
4. Show URL
|
|
169
|
+
4. Show URL
|
|
193
170
|
```
|
|
194
171
|
|
|
195
172
|
## Text guidance (TTS)
|
|
@@ -203,7 +180,7 @@ For the full flag list: `python3 <SkillDir>/scripts/gen_digital_human_video.py -
|
|
|
203
180
|
- **401** / **token missing** (non-OpenClaw): set `PRIV_TOKEN`.
|
|
204
181
|
- **Business `code != 0`**: read `msg` on stderr.
|
|
205
182
|
- **429**: rate-limited; retry later.
|
|
206
|
-
- **Generation timeout**:
|
|
183
|
+
- **Generation timeout**: the handler caps polling at ~10 minutes; use `--check-status --generation-id <id>` later.
|
|
207
184
|
- **Empty TTS text**: provide non-empty `--text` or use `--audio-url`.
|
|
208
185
|
- **Invalid voice id**: re-check via `gen-voice --list-voices`.
|
|
209
186
|
- **Avatar id not found**: re-check via `--list-avatars` (or `--list-avatars --mine`).
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"title": "Digital-Human Talking-Head",
|
|
6
6
|
"description": "Digital-human video: list available avatars; produce a talking-head video from text via TTS, or drive an avatar from an existing audio URL.",
|
|
7
7
|
"envVars": ["PRIV_TOKEN", "MM_API_BASE_URL", "AGENT_NAME"],
|
|
8
|
-
"
|
|
8
|
+
"entry": { "type": "http", "handler": "gen-digital-human" },
|
|
9
9
|
"parameters": {
|
|
10
10
|
"type": "object",
|
|
11
11
|
"properties": {
|
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
"text": { "type": "string", "description": "Narration text (TTS mode)" },
|
|
17
17
|
"audio_url": { "type": "string", "description": "Audio URL (audio-driven mode)" },
|
|
18
18
|
"voice_id": { "type": "string", "description": "Voice id" },
|
|
19
|
-
"aspect_ratio": { "type": "string", "description": "Aspect ratio" }
|
|
19
|
+
"aspect_ratio": { "type": "string", "description": "Aspect ratio" },
|
|
20
|
+
"json_output": { "type": "boolean", "description": "Emit a JSON result (generate: { url, generationId }; list: { avatars }; check-status: { status, url }) instead of human-readable output" }
|
|
20
21
|
},
|
|
21
22
|
"required": []
|
|
22
23
|
}
|
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
"skillName": "gen-digital-human",
|
|
3
3
|
"repoName": "agent-skill-media-maker",
|
|
4
4
|
"skillId": "336",
|
|
5
|
-
"version": "
|
|
5
|
+
"version": "V7",
|
|
6
6
|
"skillDescription": "数字人口播视频技能,支持查询形象、TTS 口播、音频驱动口播和查询生成状态(调用 ab-api 数字人接口,即梦 / 飞影)。\n\n当用户提到以下任何需求时,立即使用本 skill:\n- 数字人、数字人视频、数字人口播、生成数字人视频\n- 用户提供已有音频 URL(MP3 等)、用外链音频驱动数字人口型\n- AI 主播、虚拟主播、虚拟人物视频、口播视频\n- 让数字人说话、让虚拟人说一段话、让 AI 人物播报\n- 查看/列出数字人形象、有哪些数字人可以用\n- 使用即梦/飞影数字人\n\n即使用户没有明确说「使用 AI」,只要他们想要让一个虚拟人物朗读/播报一段文字并生成视频,也要使用本 skill。"
|
|
7
7
|
}
|
|
@@ -23,7 +23,7 @@ Wraps ab-api's `POST /model/genImg` (the same endpoint the web studio uses), aut
|
|
|
23
23
|
|
|
24
24
|
## Models and sizes
|
|
25
25
|
|
|
26
|
-
Aligned with
|
|
26
|
+
Aligned with the gen-image handler's model presets and the backend `ModelGenImgDTO`:
|
|
27
27
|
|
|
28
28
|
| LiteLLM `model` | Display name | Provider |
|
|
29
29
|
|-----------------|--------------|----------|
|
|
@@ -46,7 +46,7 @@ No skill-local env file — the executing process inherits the system environmen
|
|
|
46
46
|
|---------|-------------|---------|
|
|
47
47
|
| `PRIV_TOKEN` | Tianyan token; `--priv-token` overrides | none |
|
|
48
48
|
| `MM_IMAGE_MODEL` | Default model id | `doubao/doubao-seedream-4-5-251128` |
|
|
49
|
-
| `MM_API_BASE_URL` | API root |
|
|
49
|
+
| `MM_API_BASE_URL` | API root; `--api-base-url` overrides | `http://localhost:2999/api` |
|
|
50
50
|
| `AGENT_NAME` | Optional `x-invoke-agent` header | none |
|
|
51
51
|
|
|
52
52
|
## Operations
|
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
"resolution": { "type": "string", "enum": ["1K", "2K", "4K"], "description": "Output resolution (Gemini only)" },
|
|
16
16
|
"n": { "type": "number", "description": "Number of images, 1-4" },
|
|
17
17
|
"reference": { "type": "string", "description": "Reference image path or URL" },
|
|
18
|
-
"negative_prompt": { "type": "string", "description": "Negative prompt — content to avoid" }
|
|
18
|
+
"negative_prompt": { "type": "string", "description": "Negative prompt — content to avoid" },
|
|
19
|
+
"json_output": { "type": "boolean", "description": "Emit a JSON result ({ urls: [...] }) instead of human-readable output" }
|
|
19
20
|
},
|
|
20
21
|
"required": ["prompt"]
|
|
21
22
|
}
|
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
"skillName": "gen-image",
|
|
3
3
|
"repoName": "agent-skill-media-maker",
|
|
4
4
|
"skillId": "337",
|
|
5
|
-
"version": "
|
|
5
|
+
"version": "V8",
|
|
6
6
|
"skillDescription": "AI 生图技能,根据文字描述生成图片,也支持参考图进行图生图(调用 ab-api /model/genImg,支持 Seedream 与 Gemini)。\n\n当用户提到以下任何需求时,立即使用本 skill:\n- AI 生图、AI 画图、文生图、文字生成图片、生成图像、帮我画、生成一张图\n- 图生图、以图生图、参考图、风格迁移、图片变体\n- 使用 doubao / 豆包 / seedream、Gemini 等生成图片\n- 用户提供图片提示词并希望生成图片\n\n即使用户没有明确说「使用 AI」,只要他们想要根据描述生成图片,也要使用本 skill。"
|
|
7
7
|
}
|
|
@@ -28,11 +28,11 @@ Turns a user-supplied **topic** into a **Video DSL v1alpha1** JSON describing wh
|
|
|
28
28
|
|
|
29
29
|
## DSL schema
|
|
30
30
|
|
|
31
|
-
The full schema is `template-
|
|
31
|
+
The full schema is `template-registry` skill's `video_dsl/schema/video-dsl-v1alpha1.json`; examples live in `video_dsl/schema/examples/` (locate them through `template-registry`'s `Base directory for this skill`).
|
|
32
32
|
|
|
33
33
|
## Agent behavior: DSL generation when a template is selected
|
|
34
34
|
|
|
35
|
-
**When the user explicitly specifies a template id, the agent must first read the existing `*.dsl.json` and `*.binding.json` examples in `template-
|
|
35
|
+
**When the user explicitly specifies a template id, the agent must first read the existing `*.dsl.json` and `*.binding.json` examples in `template-registry`'s `video_dsl/schema/examples/`, then generate the DSL in the template's native shape using both those examples and the template's `template.json`. The agent must not generate the DSL from scratch ignoring the examples, and must not produce a generic DSL first and rely on `template-registry` to force-match the template later.**
|
|
36
36
|
|
|
37
37
|
The intent is to reuse the validated example shapes already in the repo and to avoid the failure mode where "the generic DSL looks compatible on the surface, but is missing template-specific fields, has the wrong nesting, or binds incorrectly — only to fail later at binding or render time". Examples:
|
|
38
38
|
|
|
@@ -41,7 +41,7 @@ The intent is to reuse the validated example shapes already in the repo and to a
|
|
|
41
41
|
|
|
42
42
|
### Mandatory steps
|
|
43
43
|
|
|
44
|
-
1. Visit `template-
|
|
44
|
+
1. Visit `template-registry/video_dsl/schema/examples/` and locate the closest existing `*.dsl.json` and `*.binding.json` for the requested template.
|
|
45
45
|
2. Read those examples and understand the actual DSL shape, the `templateData` fields, the scene organization, and the binding style the template uses.
|
|
46
46
|
3. Read the template's `template.json`.
|
|
47
47
|
4. Combine the examples and `template.json` to understand the template's `slotMapping`, `requiredProps`, `optionalProps`, `propExtractors`, `assetRequirements`, `supportedAspectRatios`, and `scenePatterns`.
|
|
@@ -51,15 +51,15 @@ The intent is to reuse the validated example shapes already in the repo and to a
|
|
|
51
51
|
|
|
52
52
|
### Hard constraints
|
|
53
53
|
|
|
54
|
-
- **Forbidden**: the user specified a template, but the agent generated the DSL without reading any of the existing examples under `template-
|
|
54
|
+
- **Forbidden**: the user specified a template, but the agent generated the DSL without reading any of the existing examples under `template-registry/video_dsl/schema/examples/`.
|
|
55
55
|
- **Forbidden**: only reading `template.json` while ignoring the existing `*.dsl.json` and `*.binding.json` examples.
|
|
56
|
-
- **Forbidden**: the user specified a template, but the agent first generated a generic DSL and then passed `--template-id` to `template-
|
|
56
|
+
- **Forbidden**: the user specified a template, but the agent first generated a generic DSL and then passed `--template-id` to `template-registry` to force-bind it.
|
|
57
57
|
- **Forbidden**: continuing into binding / rendering despite knowing that template-specific fields, scene shapes, or binding details are missing.
|
|
58
58
|
- **Forbidden**: silently degrading to a generic DSL because the current script cannot support a template, leaving the failure to the downstream stage.
|
|
59
59
|
|
|
60
60
|
### When a template is not yet supported
|
|
61
61
|
|
|
62
|
-
If `template-
|
|
62
|
+
If `template-registry/video_dsl/schema/examples/` has no matching example for the requested template, or `gen_script.py` cannot yet build the required DSL shape, the agent must clearly tell the user "this template is not yet supported for auto-generation from existing examples" and explain what key fields, structure, or binding info are missing. Possible next steps:
|
|
63
63
|
|
|
64
64
|
1. Ask the user to switch to a template that has an example and is already supported.
|
|
65
65
|
2. Have the agent take the closest `*.dsl.json` / `*.binding.json` as a reference and hand-craft the required DSL structure for this template, then show it to the user for confirmation.
|
|
@@ -67,7 +67,7 @@ If `template-bind/video_dsl/schema/examples/` has no matching example for the re
|
|
|
67
67
|
|
|
68
68
|
### Design principle
|
|
69
69
|
|
|
70
|
-
When the user specifies a template, `gen-script`'s goal is no longer "produce a generally-compatible DSL" but "produce a template-native DSL based on the existing examples in `template-
|
|
70
|
+
When the user specifies a template, `gen-script`'s goal is no longer "produce a generally-compatible DSL" but "produce a template-native DSL based on the existing examples in `template-registry`".
|
|
71
71
|
|
|
72
72
|
## Authentication & environment
|
|
73
73
|
|
|
@@ -75,16 +75,16 @@ This skill does not hit any external API; no token required. The script only doe
|
|
|
75
75
|
|
|
76
76
|
| Env var | Description | Default |
|
|
77
77
|
|---------|-------------|---------|
|
|
78
|
-
| `VIDEO_DSL_SCHEMA_PATH` | DSL schema file path. | Reads `template-
|
|
78
|
+
| `VIDEO_DSL_SCHEMA_PATH` | DSL schema file path. | Reads `template-registry` skill's `video_dsl/schema/video-dsl-v1alpha1.json` by default. |
|
|
79
79
|
|
|
80
80
|
## Agent behavior: script confirmation
|
|
81
81
|
|
|
82
|
-
**After the agent has generated a DSL it must first show the script summary to the user and get explicit confirmation before forwarding to downstream skills (template-
|
|
82
|
+
**After the agent has generated a DSL it must first show the script summary to the user and get explicit confirmation before forwarding to downstream skills (template-registry / prepare-video-assets / render-video).** This lets the user review and adjust the scene structure, narration text, etc. before any asset is produced.
|
|
83
83
|
|
|
84
84
|
### Confirmation flow
|
|
85
85
|
|
|
86
86
|
1. After the agent generates or modifies the DSL, **show the script summary first; do not pass it downstream yet**.
|
|
87
|
-
2. Wait for the user to explicitly confirm (e.g. "OK", "looks good", "continue with template binding") before handing it to `prepare-video-assets` (or `template-
|
|
87
|
+
2. Wait for the user to explicitly confirm (e.g. "OK", "looks good", "continue with template binding") before handing it to `prepare-video-assets` (or `template-registry` for a list-only lookup).
|
|
88
88
|
3. If the user asks for changes (adjust narration, add or remove scenes, change durations), the agent updates the DSL and shows the summary again, then waits for confirmation once more.
|
|
89
89
|
|
|
90
90
|
### Summary content
|
|
@@ -174,7 +174,7 @@ Env vars `STUB_IMAGE_URL` / `STUB_VIDEO_URL` also work — their priority is low
|
|
|
174
174
|
|
|
175
175
|
1. **Script path**: read the system-injected `Base directory for this skill: <path>` as `<SkillDir>`. Every command below uses `<SkillDir>/scripts/gen_script.py`; never hard-code paths.
|
|
176
176
|
2. **Understand the request**: extract topic, target platform, duration, style, audience, etc.
|
|
177
|
-
3. **If the user specifies a template, read it first**: load the matching `template.json` via `template-
|
|
177
|
+
3. **If the user specifies a template, read it first**: load the matching `template.json` via `template-registry` and confirm its template-specific fields and asset requirements. Do not skip this step.
|
|
178
178
|
4. **Generate the DSL**: pick the right command or DSL shape for the target template (see the per-template commands below).
|
|
179
179
|
5. **Schema validation**: make sure the output DSL conforms to v1alpha1.
|
|
180
180
|
6. **User confirmation**: show the script summary and wait for confirmation, per the rules above.
|
|
@@ -208,7 +208,7 @@ python3 <SkillDir>/scripts/gen_script.py \
|
|
|
208
208
|
--output output.dsl.json
|
|
209
209
|
```
|
|
210
210
|
|
|
211
|
-
5. **Result handling**: pass the generated DSL to `template-
|
|
211
|
+
5. **Result handling**: pass the generated DSL to `template-registry` for template lookup, or directly to `prepare-video-assets` (which auto-invokes template binding when `template_id` is provided).
|
|
212
212
|
|
|
213
213
|
## Common CLI flags
|
|
214
214
|
|
|
@@ -280,4 +280,4 @@ Mirrors the `gen-image` skill and `GEN_IMG_MODEL_PRESETS` in `gen_image.py`. **O
|
|
|
280
280
|
| `knowledge_card_script.json` | Intermediate knowledge-card script result. |
|
|
281
281
|
| `script_knowledge_card.json` | Full knowledge-card script example. |
|
|
282
282
|
|
|
283
|
-
These JSON files are reference data for development / debugging; they do not participate in runtime logic. The authoritative DSL examples live under `template-
|
|
283
|
+
These JSON files are reference data for development / debugging; they do not participate in runtime logic. The authoritative DSL examples live under `template-registry/video_dsl/schema/examples/`.
|
|
@@ -12,7 +12,7 @@ Usage:
|
|
|
12
12
|
|
|
13
13
|
Environment variables:
|
|
14
14
|
VIDEO_DSL_SCHEMA_PATH - DSL schema file path
|
|
15
|
-
(default: skills/template-
|
|
15
|
+
(default: skills/template-registry/video_dsl/schema/video-dsl-v1alpha1.json)
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
18
|
import argparse
|
|
@@ -24,20 +24,19 @@ import uuid
|
|
|
24
24
|
|
|
25
25
|
SCHEMA_PATH = os.environ.get(
|
|
26
26
|
"VIDEO_DSL_SCHEMA_PATH",
|
|
27
|
-
"skills/template-
|
|
27
|
+
"skills/template-registry/video_dsl/schema/video-dsl-v1alpha1.json",
|
|
28
28
|
)
|
|
29
29
|
|
|
30
30
|
# prompt_enhancer 路径动态添加
|
|
31
|
-
_TEMPLATE_DSL_DIR = os.path.join(os.path.dirname(__file__), "..", "..", "template-
|
|
31
|
+
_TEMPLATE_DSL_DIR = os.path.join(os.path.dirname(__file__), "..", "..", "template-registry", "video_dsl")
|
|
32
32
|
if os.path.isdir(_TEMPLATE_DSL_DIR):
|
|
33
33
|
sys.path.insert(0, os.path.abspath(os.path.join(_TEMPLATE_DSL_DIR, "..")))
|
|
34
34
|
|
|
35
|
-
# Shared Python lib lives under skills/template-
|
|
36
|
-
# cross-skill module location (registry_loader, template_paths, etc.).
|
|
37
|
-
#
|
|
38
|
-
# caller. See AGENTS.md for the convention.
|
|
35
|
+
# Shared Python lib lives under skills/template-registry/scripts/ — the de-facto
|
|
36
|
+
# cross-skill module location (registry_loader, template_paths, etc.). See
|
|
37
|
+
# AGENTS.md for the convention.
|
|
39
38
|
_SHARED_SCRIPTS_DIR = os.path.join(
|
|
40
|
-
os.path.dirname(__file__), "..", "..", "template-
|
|
39
|
+
os.path.dirname(__file__), "..", "..", "template-registry", "scripts"
|
|
41
40
|
)
|
|
42
41
|
if os.path.isdir(_SHARED_SCRIPTS_DIR):
|
|
43
42
|
sys.path.insert(0, os.path.abspath(_SHARED_SCRIPTS_DIR))
|
|
@@ -58,7 +57,7 @@ except ImportError:
|
|
|
58
57
|
_HAS_REGISTRY_LOADER = False
|
|
59
58
|
|
|
60
59
|
try:
|
|
61
|
-
# Centralized monorepo-path resolver living in template-
|
|
60
|
+
# Centralized monorepo-path resolver living in template-registry/scripts/;
|
|
62
61
|
# the import works because the same sys.path.insert above pointed at it.
|
|
63
62
|
from template_paths import monorepo_template_src_dir as _monorepo_template_src_dir
|
|
64
63
|
except ImportError:
|
|
@@ -326,7 +325,7 @@ def _load_template_config(template_id: str) -> dict | None:
|
|
|
326
325
|
解析顺序(与 match_template / template_binder 保持一致):
|
|
327
326
|
1. 通过 registry_loader 从 monorepo template-library/packages/metadata/registry.json
|
|
328
327
|
(或 VIDEO_TEMPLATE_REGISTRY[_URL] 环境变量)加载,并按 templateId 匹配。
|
|
329
|
-
2. 兜底:旧路径
|
|
328
|
+
2. 兜底:旧路径 template-registry/video_dsl/templates/<id>/template.json
|
|
330
329
|
(仅在仓库还残留旧目录时使用)。
|
|
331
330
|
返回完整 template dict(含 supportedAspectRatios / assetRequirements / slotMapping 等),
|
|
332
331
|
找不到时返回 None。
|
|
@@ -343,7 +342,7 @@ def _load_template_config(template_id: str) -> dict | None:
|
|
|
343
342
|
|
|
344
343
|
# 兜底:旧的本地目录布局
|
|
345
344
|
legacy_dir = os.path.join(
|
|
346
|
-
os.path.dirname(__file__), "..", "..", "template-
|
|
345
|
+
os.path.dirname(__file__), "..", "..", "template-registry", "video_dsl", "templates"
|
|
347
346
|
)
|
|
348
347
|
legacy_file = os.path.join(legacy_dir, template_id, "template.json")
|
|
349
348
|
if os.path.isfile(legacy_file):
|
|
@@ -408,7 +407,7 @@ def _locate_template_dir(template_id: str) -> str | None:
|
|
|
408
407
|
"""定位模板源码目录(template-library/packages/templates/src/<id>/)。
|
|
409
408
|
|
|
410
409
|
路径解析已集中到 ``template_paths.monorepo_template_src_dir``;
|
|
411
|
-
当 helper 不可用(template-
|
|
410
|
+
当 helper 不可用(template-registry/scripts/ 不在 sys.path)时回退到 None,
|
|
412
411
|
与原始函数"找不到就返回 None"的语义一致。
|
|
413
412
|
"""
|
|
414
413
|
if _monorepo_template_src_dir is None:
|