@ninkch/dsh-infinite-canvas 0.17.9 → 0.17.11
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 +20 -15
- package/assets/canvas-studio/SKILL.md +61 -14
- package/client.js +987 -163
- package/index.js +135 -13
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -17,11 +17,12 @@ Everything runs locally in your Harness. Bring your own generation APIs, or use
|
|
|
17
17
|
```mermaid
|
|
18
18
|
flowchart LR
|
|
19
19
|
A[Script node<br>AI screenplay] --> B[Storyboard node<br>AI shot list]
|
|
20
|
-
B --> C[Expand to canvas
|
|
21
|
-
C --> D[
|
|
22
|
-
D --> E[
|
|
23
|
-
E --> F[
|
|
24
|
-
|
|
20
|
+
B --> C[Expand to canvas]
|
|
21
|
+
C --> D[Multi-shot video gen<br>all shots in ONE prompt]
|
|
22
|
+
D --> E[Final cut<br>transitions · subtitles · voices]
|
|
23
|
+
E --> F[Export<br>WebM preview / FilmCraft MP4]
|
|
24
|
+
A --> G[Reference image gen<br>characters · scenes · props]
|
|
25
|
+
G --> D
|
|
25
26
|
```
|
|
26
27
|
|
|
27
28
|
## Highlights
|
|
@@ -33,13 +34,16 @@ A per-project **series bible** (style baseline + character/scene/prop cards) is
|
|
|
33
34
|
Reference images connect as an ordered, visible list — `[图1] 角色:Lin Ning`, `[图2] 场景:The Old House` — and that exact order is what reaches the model. Multi-character frames stay unambiguous, and Volcano Engine **Seedance**'s native `[图N]` convention is supported end to end (first frame, up to 4 reference images, official task API).
|
|
34
35
|
|
|
35
36
|
### From shots to a watchable cut
|
|
36
|
-
The **Final Cut node** stitches
|
|
37
|
+
**One storyboard = one multi-shot video generation.** Expanding a storyboard wires it to a single video node: every shot (order + per-shot duration) is composed into one multi-shot prompt and your video model renders the whole clip in one call — the model makes the hard cuts, no per-shot stitching seams. The **Final Cut node** then stitches segments in order — crossfade or black transitions, burned-in subtitles, original audio and TTS voices mixed in — and exports a preview cut instantly. For real post-production, one click writes a **FCP7 XML timeline + SRT** to disk and hands the render to [ArtCraft](#artcraft-bridge) (FilmCraft) for a true MP4.
|
|
37
38
|
|
|
38
39
|
### An editor-grade canvas
|
|
39
40
|
Pan, zoom, marquee select, alignment guides, groups that fold, a minimap, 60-step undo/redo, per-node media history (last 8 results), mask-based inpainting, and middle-click everything — the canvas part should feel like an editor, not a chat sidebar.
|
|
40
41
|
|
|
41
42
|
### Bring your own models
|
|
42
|
-
Text models come from Harness itself (no extra keys). Image, video and TTS backends are **multi-config** — define as many endpoints as you want, mark a default, and pick per node. No backend configured? Demo mode synthesizes placeholder images and animated videos locally so the entire pipeline is testable offline.
|
|
43
|
+
Text models come from Harness itself (no extra keys, no per-plugin parameters). Image, video and TTS backends are **multi-config** — define as many endpoints as you want, mark a default, and pick per node. Every gateway call is relayed through the local Harness host process, so **any vendor works** (no CORS headaches). No backend configured? Demo mode synthesizes placeholder images and animated videos locally so the entire pipeline is testable offline.
|
|
44
|
+
|
|
45
|
+
### A portable data root
|
|
46
|
+
Set a **data root folder** once and everything lands there, organized by **project name**: nodes and the series bible in `project.json`, the asset index in `assets.json`, media under `image/ video/ audio/ text/`, and Craft post-production under `craft/`. Move to a new machine by copying the folder and clicking **Import from data root**.
|
|
43
47
|
|
|
44
48
|
## Quick start
|
|
45
49
|
|
|
@@ -57,28 +61,29 @@ Text models come from Harness itself (no extra keys). Image, video and TTS backe
|
|
|
57
61
|
|---|---|---|
|
|
58
62
|
| Text | Harness LLM service | Script & storyboard writers; pick any configured model, or override per node |
|
|
59
63
|
| Image | OpenAI-compatible `/images/generations`, multi-reference via `/images/edits` | Size (1K/2K/4K) × ratio; mask inpainting via `edits` + PNG mask |
|
|
60
|
-
| Video | Generic submit+poll, or **Volcano Seedance official tasks** | duration
|
|
64
|
+
| Video | Generic submit+poll, or **Volcano Seedance official tasks** | duration up to 15 s, 480P/720P/1080P, ratio, first frame, up to 4 reference images |
|
|
61
65
|
| TTS | OpenAI-compatible `/audio/speech` | Per-shot voices mixed into the final cut |
|
|
62
66
|
|
|
67
|
+
All gateway calls are relayed by the local Harness host process (no browser CORS limits) — any vendor endpoint with an OpenAI-style shape works.
|
|
68
|
+
|
|
63
69
|
## ArtCraft bridge
|
|
64
70
|
|
|
65
|
-
When the companion [`dsh-artcraft`](../dsh-artcraft/README.md) plugin is installed, the canvas talks to the local **PhotoCraft
|
|
71
|
+
When the companion [`dsh-artcraft`](../dsh-artcraft/README.md) plugin is installed, the canvas talks to the local **Craft family** (PhotoCraft, FilmCraft, EffectCraft, LightCraft, VectorCraft, DesignCraft, … — every bin the Craft suite reports, currently 12) over same-origin HTTP. Point ArtCraft's data root at the same folder as the canvas data root and all post-production lands in `projects/<project>/craft/` next to your other data: assets sync per project, images get headless PhotoCraft grading (single or batch), and final cuts export as FCP7 XML + SRT for FilmCraft to render as MP4. A status card in Settings shows one light per craft with an n/n ready summary.
|
|
66
72
|
|
|
67
73
|
## Publishing (maintainers)
|
|
68
74
|
|
|
69
|
-
|
|
75
|
+
The maintainer runbook (red lines, branch model, versioning) lives in [`RELEASING.md`](RELEASING.md); the operations detail in [`docs/release.md`](docs/release.md); released changes in [`CHANGELOG.md`](CHANGELOG.md) — **GitHub Release notes are written in English** and copied from the changelog.
|
|
70
76
|
|
|
71
77
|
Publishing runs through **npm Trusted Publishing** (OIDC) — no npm token exists anywhere:
|
|
72
78
|
|
|
73
|
-
- **Release flow**: create a GitHub Release (tag `v0.17.
|
|
74
|
-
-
|
|
75
|
-
- The `publish.yml` workflow resolves the version from the release tag (or your input) and publishes with a `provenance` badge.
|
|
79
|
+
- **Release flow**: dev tested & approved → merge to `main` → create a GitHub Release (tag `v0.17.9`, …) → Actions publishes that version automatically.
|
|
80
|
+
- The `publish.yml` workflow guards on the release commit being on `main` and the tag matching `package.json`, then publishes with a `provenance` badge.
|
|
76
81
|
|
|
77
82
|
## Data & privacy
|
|
78
83
|
|
|
79
|
-
- Canvas documents, projects
|
|
84
|
+
- Canvas documents, projects and settings live in browser `localStorage` (`dsh-ic:*`); asset metadata lives in IndexedDB (`dsh-infinite-canvas`) while media files persist **on disk** once a data root is set (per-project folders by project name, served by the plugin backend with HTTP Range support for video seeking).
|
|
80
85
|
- AI text generation runs through the Harness host process (your configured models, no extra keys).
|
|
81
|
-
- Image/video/TTS calls
|
|
86
|
+
- Image/video/TTS gateway calls are relayed by the local Harness host process (avoids browser CORS limits); your endpoints and keys stay local.
|
|
82
87
|
- Nothing is uploaded anywhere by the plugin itself.
|
|
83
88
|
|
|
84
89
|
## Requirements & limitations
|
|
@@ -35,32 +35,79 @@ description: 用无限画布(Infinite Canvas)做短剧/视频创作时使用
|
|
|
35
35
|
6. **删除是破坏性操作。** 先 `canvas_list_projects` 确认 id,且仅在用户明确要求时执行
|
|
36
36
|
(`canvas_delete_node` / `canvas_delete_project`)。
|
|
37
37
|
7. **完成后让用户看到结果**:调用 `canvas_open({ projectId })`,画布会在数秒内自动跳转。
|
|
38
|
-
8.
|
|
38
|
+
8. **一致性告警必须闭环。** 分镜节点生成/更新后,`canvas_node_status` 会返回 `warnings`——
|
|
39
|
+
分镜中出现但**未在设定集登记**或**已登记但描述为空**的实体清单(含画面/动作文本里的 @提及)。
|
|
40
|
+
只要 `warnings` 非空:**逐条** `canvas_update_bible` 补全(名称与告警**逐字一致**、描述写实可生成),
|
|
41
|
+
再生成参考图;**绝不忽略、绝不跳过、绝不只补一部分**。设定集更新后告警会自动重算
|
|
42
|
+
(几秒内随文档同步刷新),以最新一次 `canvas_node_status` 为准。
|
|
43
|
+
9. **分镜容量铁律:一个分镜节点 = 一个 10–15s 的完整场景视频,是剧本的一小部分。**
|
|
44
|
+
- 一个分镜节点只吃**一个场景**的剧本:各镜 2–5s、时长之和 **≤ 15s(上限)**;
|
|
45
|
+
- **长剧本必须按场景拆分**为多个场景剧本节点(命名「第X节-场Y剧本」…),
|
|
46
|
+
每个场景剧本作为**各自分镜表**的源端——**绝不把长剧本整根连线给一个分镜表**;
|
|
47
|
+
- 全集剧本(若有)只作总纲存档,**不作为分镜源端**;
|
|
48
|
+
- 体量感:一个 10–15s 场景 ≈ 剧本 60–150 字(含该场全部对白);分镜表 `shots` 上限 24 镜,
|
|
49
|
+
超长剧本会被截断且触发生成告警(warnings 会出现"剧本较长…请按场景拆分");
|
|
50
|
+
- **镜头数量不固定**:分镜表镜头数默认「自动(按内容节拍)」——一个连续动作段落 = 一镜,
|
|
51
|
+
3–10 镜都正常,绝不凑数、绝不用固定数量;全部镜头时长之和 ≤ 15s(超限客户端会自动压缩最长镜);
|
|
52
|
+
- 拆分操作:全集剧本已生成后,按场景把对应片段 `canvas_write_node(target:'output')`
|
|
53
|
+
写入各场景剧本节点(这是**分配已有内容**,不是代写)。
|
|
54
|
+
10. **汇报固定要素**:项目名 + 项目 id + 节点名/id + 成稿摘要(若已生成);有错误如实说明。
|
|
55
|
+
11. **生成节点前置检查单(创建任何 image-gen / video-gen 前逐条确认,任一不过 = 停止创建)**:
|
|
56
|
+
① **镜头清单来源**:这一段的镜头序列已经从分镜表节点的 `shots` 读到了吗?(`canvas_node_status`)
|
|
57
|
+
没读到 → 停止创建,先读分镜表节点;仍读不到 → **问用户要分镜内容**。绝不自己按剧本推导/编造镜头表。
|
|
58
|
+
② **视频节点数量 = 1**:一个分镜表对应一个完整视频(多镜头一次生成)。
|
|
59
|
+
准备为不同镜头建第 2 个视频节点 → 立即停止,走错路了。
|
|
60
|
+
③ **先建 1 个、验证、再继续**:批量预建生成节点会放大错误——先建第 1 个,
|
|
61
|
+
用 `canvas_node_status` 验证连线与产物正确,再继续下一个。
|
|
62
|
+
12. **读不到就问**:必需的项目状态(分镜内容/镜头清单/设定集条目)读不到时,那是**应当向用户确认的缺口**,
|
|
63
|
+
不是可以自行绕过的障碍——绝不把"编一份"当作替代方案。
|
|
39
64
|
|
|
40
65
|
## 二、标准工作流(对话填提示词+连线+触发,生成由节点完成)
|
|
41
66
|
|
|
42
67
|
0. **读/补设定集**:`canvas_get_bible` → 缺什么用 `canvas_update_bible` 补。
|
|
43
68
|
创作意图、世界观、风格 → 写进设定集的 worldview/style 字段。
|
|
44
69
|
1. `canvas_list_projects` —— 查重 + 拿到 projectId 与节点 id
|
|
45
|
-
2.
|
|
46
|
-
- 新项目:`canvas_create_project({ name, scriptText:
|
|
70
|
+
2. **剧本节点(一集 = 成片 60–120 秒,按【场N】分场)**:只写提示词,让节点自己生成剧本——
|
|
71
|
+
- 新项目:`canvas_create_project({ name, scriptText: 本集创作提示词, nodeName: '第X节剧本' })`
|
|
47
72
|
- 已有项目:`canvas_write_node({ projectId, text: 提示词, target: 'idea', name: '第X节剧本' })`
|
|
48
73
|
- 触发生成:`canvas_run_node({ projectId, nodeId })` → `canvas_node_status` 轮询直到 done/error
|
|
74
|
+
- 生成契约(自动注入,无需复述):整集 **4–10 场、每场 10–15 秒成片**;**每场以「【场N】场景名(地点·时间)」单独一行开头**
|
|
75
|
+
——这是"铺开到场景"自动拆分的解析标记,格式不可变;对白逐行「角色:台词」;结尾附人物/场景/道具清单;
|
|
49
76
|
- **【铁律】不要把成稿直接填进 output**——生成是节点的工作(用户在画布上看得到过程与结果)。
|
|
50
77
|
仅当用户明确说"你直接把剧本写出来、不用节点生成"时,才允许 `target:'output'` 直接写成稿。
|
|
51
|
-
3.
|
|
52
|
-
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
- `canvas_create_node({ projectId, type: 'video-gen', name: '第X
|
|
61
|
-
(不传 connectFrom
|
|
78
|
+
3. **铺开到场景(每场 = 场景文本节点 + 分镜表节点,连线一次生成场景分镜)**:
|
|
79
|
+
- 画布:剧本节点的**「铺开到场景」按钮**一键完成(按【场N】自动分段);
|
|
80
|
+
- Agent 等价操作:`canvas_node_status` 读成稿 → 按【场N】分段 → **逐场**:
|
|
81
|
+
`canvas_create_node({ type: 'text', name: '第X节-场Y文本' })` +
|
|
82
|
+
`canvas_write_node({ projectId, nodeId: 文本节点id, target: 'output', text: 该场原文 })` +
|
|
83
|
+
`canvas_create_node({ projectId, type: 'storyboard', name: '第X节-场Y分镜表', connectFrom: 该场文本节点id })`;
|
|
84
|
+
- **【铁律】每个分镜表的源端 = 对应场景文本(连线取)**;整集剧本节点**绝不**直接连分镜表(体量超限,见硬约束 9)。
|
|
85
|
+
4. **逐场生成视频(多镜头一次生成)**:
|
|
86
|
+
- `canvas_run_node({ 分镜表 })` → `canvas_node_status` 读 `shots`(镜头清单以此为准,绝不编造镜头表);
|
|
87
|
+
- `canvas_create_node({ projectId, type: 'video-gen', name: '第X节-场Y视频', connectFrom: 分镜表节点id, duration: 各镜时长之和 })`
|
|
88
|
+
(不传 connectFrom 且项目里有已拆解镜头的分镜表时会自动连线;prompt 留空);
|
|
89
|
+
- **【禁止逐镜建节点】**一段 10–15 秒的视频**不需要逐镜的图片节点或"镜头图→镜头视频"链路**:
|
|
90
|
+
多镜头一致性靠角色/场景/道具**参考图资产**(@引用自动挂载)保证,视频模型在一次调用里完成全部镜头。
|
|
91
|
+
最多为**开场首帧或 1–2 个关键镜头**补定帧图(接同一视频节点的 frame/ref 端口)。
|
|
92
|
+
一旦发现自己在批量创建"第X节-场Y-镜Z"这类镜头图片/视频节点 = 走错路,**立即停止**并回到本条。
|
|
62
93
|
- 参考图:把角色/场景/道具参考图资产连到视频生成节点的 `ref` 端口(`canvas_connect`);
|
|
63
94
|
提示词里的 `@引用` 命中的资产也会自动挂上
|
|
95
|
+
- **【跨段连贯:尾帧 → 首帧】**每个视频节点生成完成后会**自动提取尾帧**并挂到 `last` 输出端口。
|
|
96
|
+
多场视频按顺序串联:上一视频节点的 `last` 端口 → 下一视频节点的 `frame` 端口
|
|
97
|
+
(`canvas_connect({ projectId, fromNode: 上一段, toNode: 下一段, fromPort: 'last', toPort: 'frame' })`),
|
|
98
|
+
下一段就会以上一段的最后一帧为开场,保证段间画面连贯。
|
|
99
|
+
第一段的 `frame` 用开场定帧图(若生成了首帧关键图)或留空。
|
|
100
|
+
**按顺序触发**:上一段 `canvas_node_status` 为 done 后再连线、再触发下一段
|
|
101
|
+
(连线可以提前建好——frame 在下一段真正运行时才解析)。
|
|
102
|
+
- **【声音一致(可选)】**视频接口配置里的「生成同步音频」勾选后才发送 `generate_audio:true`——
|
|
103
|
+
模型生成**自带音轨**的视频(对白/环境声与画面同步);不勾 = 无声视频(声音另行 TTS 配音)。
|
|
104
|
+
要让同一角色**跨视频保持音色**:用视频/成片节点的「提取声音参考」按钮——
|
|
105
|
+
**输入角色名即可**:系统自动按分镜 `dialogue` 台词标注定位该角色的全部时间窗,
|
|
106
|
+
逐窗取音轨**拼接为一个声音参考文件**(`角色-<名> 声音`,自动绑定实体),
|
|
107
|
+
之后该角色的视频提示词里 `@<名称>` 会自动把这条声音参考放进 `audios[]`,
|
|
108
|
+
模型生成的对白将向参考音色对齐(携带声音参考时会自动强制开启同步音频)。
|
|
109
|
+
时间窗归属靠分镜的 `dialogue` 标注(对白逐字来自剧本、按镜头分配,一镜尽量单说话人);
|
|
110
|
+
分镜缺少台词标注时按钮会降级为手动模式并提示重新生成分镜。
|
|
64
111
|
- 触发:`canvas_run_node` → 轮询;整段视频一次生成完成
|
|
65
112
|
5. **生成角色/场景/道具参考图**:为设定集里的每个条目
|
|
66
113
|
`canvas_create_node({ projectId, type: 'image-gen', name: '角色-张山 多视图', prompt: '按设定集写外观关键词' })`
|