dsh-kylin-media 0.2.1 → 0.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 CHANGED
@@ -1,147 +1,149 @@
1
- # dsh-kylin-media
2
-
3
- 把本地 **comfyui-gateway** 接进麒麟(QiLin)/ DSH 会话:出图、出视频、出音乐、对口型、图片超分,以及语音转写、语音合成与人声/伴奏分离。
4
-
5
- 插件由两半组成,同一份包同时服务两个宿主:
6
-
7
- - **Host**(`entry.js` + `lib/`):注册 6 个 `media_*` 工具、一个随包的 `kylin-media` 技能,以及一个只允许回环访问的 JSON API;
8
- - **Client**(`client.js`):只注册 **设置页面** 的一个菜单「多媒体网关」,用于配置网关地址、访问 Key、等待时长与产物目录,并展示实时能力目录。
9
-
10
- 访问 Key 只写入插件私有目录下的 `settings.json`(POSIX 下目录 0700 / 文件 0600;Windows 由用户私有目录的 ACL 保护),UI 与 API 都只回显脱敏串。
11
-
12
- ## 安装
13
-
14
- 发布到 registry 后:
15
-
16
- ```bash
17
- qilin plugin --profile <profile> add dsh-kylin-media
18
- # 或 DSH
19
- dsh plugin --profile <profile> add dsh-kylin-media
20
- ```
21
-
22
- 本地目录安装(开发 / 内网分发):
23
-
24
- ```bash
25
- qilin plugin --profile <profile> add /path/to/dsh-kylin-media
26
- ```
27
-
28
- 安装后如果页面没有出现菜单,刷新一次浏览器;替换同版本包需要重启宿主进程才能加载新的客户端 JavaScript。
29
-
30
- ## 发布到 npm
31
-
32
- 包已在 `package.json` 里配置 `publishConfig.registry = https://registry.npmjs.org/`,`npm publish` 不会误发到本机配置的 npmmirror(镜像是只读的,发不上去)。
33
-
34
- ```bash
35
- npm login --registry=https://registry.npmjs.org/
36
- npm whoami --registry=https://registry.npmjs.org/
37
-
38
- cd dsh-kylin-media
39
- npm publish # prepack 会自动跑 smoke
40
- ```
41
-
42
- - 发布前可先 `npm pack --dry-run` 检查载荷(`files` 白名单,约 17-19 个文件)。
43
- - 版本一旦发布不可覆盖;升级用 `npm version patch|minor|major` 后再 publish。
44
- - 刚发布的版本可能被宿主 profile 的 `minimumReleaseAge`(pnpm 默认 24h)拒绝安装,等一段时间或把包名加入该 profile 的排除项。
45
- - 安装:`qilin plugin --profile <profile> add dsh-kylin-media`。
46
-
47
- ## 设置
48
-
49
- 打开 **设置 → 多媒体网关**:
50
-
51
- | 项 | 说明 |
52
- |---|---|
53
- | 网关地址 | 默认 `http://127.0.0.1:8288`;局域网用 `http://<主机IP>:8288`,frp / 反代填对外地址。编辑的是「当前线路」的地址 |
54
- | 连接线路 | 可同时保存多条地址(本机 / 局域网 / frp 公网),点圆点切换当前线路,「测试连接」与所有 `media_*` 都用它;「全部测速」并发探测每条线路并标出最快可用的那条 |
55
- | 访问 Key | 网关 `API_KEY_MODE=always` 时必填;保存后不再回显明文,留空表示沿用已保存的值 |
56
- | 单次最多等待 | 工具调用内等待任务的秒数(10-600);超时不影响网关侧任务,可继续用 `media_job` |
57
- | 产物目录 | 留空 = `<会话目录>/media-output/<任务 id>/`;也可填绝对路径 |
58
- | 自动下载 | 关闭后只返回远端 URL,用 `media_job action=download` 取回 |
59
- | 默认模型 | 「可用能力」卡片里逐类型列出网关实时目录中的模型,点选即设为该类型默认模型并立即保存;`media_*` 未传 `model` 时用它,没选则用该类型第一个可用模型 |
60
-
61
- 页面上的「测试连接」会读取 `/api/health` 与 `/api/models`,显示网关版本、鉴权模式、ComfyUI 与双卡队列,并按能力类型列出具体模型(含可用性与权重缺失),可直接点选默认模型。连接失败时会给出排查提示。
62
-
63
- > 常见坑:网关默认监听明文 HTTP(`API_PORT=8288`)。frp / 反代把 8288 映射出去后仍然是 HTTP,地址要写 `http://<对外地址>:<端口>`;写成 `https://` 会在 TLS 握手阶段被断开,错误信息里会提示「这个端口没有完成 TLS 握手…把地址改成 http:// 再试」。反过来,如果前面套了 nginx / Caddy 的 HTTPS,则必须写 `https://`(自签证书还需要让运行宿主信任该 CA)。
64
-
65
- > 为什么「本机 / 局域网」地址连不上:
66
- > 1. `127.0.0.1` / `localhost` 只有**网关和插件跑在同一台机器**时才通。网关在远端(例如 Windows 主机)而插件在 Mac 上时,本机地址必然被拒绝。
67
- > 2. 局域网地址要求两者**在同一网段**,且网关监听 `HOST=0.0.0.0`(默认)、系统防火墙放行 8288(仓库里有 `add-firewall-rule.bat`)。可先用 `curl http://<主机IP>:8288/api/health` 验证。
68
- > 3. 上面两条都不满足时只能用 frp / 公网地址。把三条地址都加进「连接线路」,点「全部测速」即可看出哪条通、哪条最快;失败原因直接写在行内(拒绝连接 / 不可达 / 域名解析失败 / 协议写反)。
69
- >
70
- > 局域网里偶发 `EHOSTUNREACH`(刚唤醒、Wi-Fi 切换、ARP 未就绪)不用管:所有 GET 探测都会自动重试最多 2 次;仍失败时先在本机 `curl http://<主机IP>:8288/api/health` 复核。
71
-
72
- ## 工具
73
-
74
- | 工具 | 作用 |
75
- |---|---|
76
- | `media_health` | 网关 / ComfyUI / 队列 / 鉴权状态;`action=test` 附带能力目录 |
77
- | `media_models` | 按类型列模型、可用性与缺失文件;传 `model` 看参数 schema |
78
- | `media_generate` | 按「类型 + 模型」提交生成,支持等待与自动下载 |
79
- | `media_audio` | `transcribe` / `speech` / `separate` 三种语音能力 |
80
- | `media_job` | `status` / `wait` / `list` / `cancel` / `delete` / `download` |
81
- | `media_upload` | 上传参考图 / 音频 / 视频,返回可填进 `params.image` 等的 `name` |
82
-
83
- 生成类型:`text2image`、`image_edit`、`text2video`、`image2video`、`lipsync`、`music`、`upscale`。
84
- 语音能力:`asr`(whisper)、`tts`(本地 MeloTTS / 小米 MiMo)、`separate`(demucs 4 轨)。
85
-
86
- ### 例子
87
-
88
- ```text
89
- media_generate type=text2image params={"prompt":"雪夜里的红灯笼,浅景深","width":1024,"height":576,"seed":42}
90
-
91
- media_upload file=D:\refs\frame.png
92
- media_generate type=image2video params={"prompt":"她转身微笑","image":"frame.png","length":96} wait=false
93
- media_job action=wait id=<上一步的 job id> waitSeconds=300
94
-
95
- media_audio action=transcribe file=D:\audio\song.wav language=zh srt=true
96
- media_audio action=speech text="你好,这是本地语音合成。" format=mp3
97
- ```
98
-
99
- 产物默认落到会话目录的 `media-output/<任务 id>/`,返回绝对路径;图片可直接用 `read_image` 查看。
100
-
101
- ## 包契约
102
-
103
- - `package.json` 同时声明 `dsh.bundle.patch` 与 `qilin.bundle.patch`,两者指向同一份 `cordis.patch.yml`;
104
- - `dsh.client.bundle` / `qilin.client.bundle` 指向手写零构建的 `client.js`,通过 `window.__ModuleLoader__.load` 自注册;
105
- - `files` 是发布载荷白名单,新增模块或资源时同步更新;
106
- - 无运行时依赖,Node ≥ 20。
107
-
108
- ## 安全边界
109
-
110
- - 插件 API 只接受回环 `Host`(`127.0.0.1` / `localhost` / `::1`),其它来源一律 403;
111
- - 访问 Key 不写入 composition,不走宿主设置 RPC,只存在 `<QILIN_HOME|DSH_HOME|~/.kcoder>/.dsh-kylin-media/settings.json`;
112
- - 任何响应都不包含明文 Key;UI 输入框保存后即清空;
113
- - 产物下载只允许当前网关同源的 `/api/files/*` 地址,避免被任务数据带去任意主机。
114
-
115
- ## 开发
116
-
117
- ```bash
118
- cd dsh-kylin-media
119
- npm test # smoke(包契约 + 客户端自注册 + locale/icon/技能)+ selftest(mock ctx + mock 网关)+ client-test(渲染自测)
120
- ```
121
-
122
- `selftest` 会用临时 HOME 与 `127.0.0.1` 上的 mock 网关跑完整链路:设置持久化、403 / 400 / 404 / 405 围栏、默认模型选择与回退、提交轮询、产物下载、鉴权头、注册与卸载。
123
-
124
- `client-test` 用最小 React 替身渲染设置页的「可用能力」卡片:类型卡片列出具体模型、默认模型高亮、点选后 POST `settings.update`、缺权重模型不可选,且渲染树不含明文 Key。
125
-
126
- ## 目录
127
-
128
- ```
129
- dsh-kylin-media/
130
- ├── entry.js # 宿主入口:设置播种、工具 / 路由 / 技能注册
131
- ├── client.js # 设置页菜单(手写零构建)
132
- ├── lib/
133
- │ ├── home.js # 插件私有目录解析
134
- │ ├── store.js # settings.json(0600、原子写、Key 脱敏)
135
- │ ├── gateway.js # comfyui-gateway 客户端
136
- │ ├── runner.js # 轮询、终态、下载
137
- │ ├── catalog.js # 类型标签与能力摘要
138
- │ ├── tools.js # media_* 工具面
139
- │ └── routes.js # fenced JSON API
140
- ├── skills/kylin-media/ # 随包技能
141
- ├── locale/ # 插件管理器展示元数据
142
- └── scripts/ # smoke / selftest / client-test
143
- ```
144
-
145
- ## License
146
-
147
- MIT
1
+ # dsh-kylin-media
2
+
3
+ 把本地 **comfyui-gateway** 接进麒麟(QiLin)/ DSH 会话:出图、出视频、出音乐、对口型、图片超分,以及语音转写、语音合成与人声/伴奏分离。
4
+
5
+ 插件由两半组成,同一份包同时服务两个宿主:
6
+
7
+ - **Host**(`entry.js` + `lib/`):注册 6 个 `media_*` 工具、一个随包的 `kylin-media` 技能,以及一个只允许回环访问的 JSON API;
8
+ - **Client**(`client.js`):只注册 **设置页面** 的一个菜单「多媒体网关」,用于配置网关地址、访问 Key、等待时长与产物目录,并展示实时能力目录。
9
+
10
+ 访问 Key 只写入插件私有目录下的 `settings.json`(POSIX 下目录 0700 / 文件 0600;Windows 由用户私有目录的 ACL 保护),UI 与 API 都只回显脱敏串。
11
+
12
+ ## 安装
13
+
14
+ 发布到 registry 后:
15
+
16
+ ```bash
17
+ qilin plugin --profile <profile> add dsh-kylin-media
18
+ # 或 DSH
19
+ dsh plugin --profile <profile> add dsh-kylin-media
20
+ ```
21
+
22
+ 本地目录安装(开发 / 内网分发):
23
+
24
+ ```bash
25
+ qilin plugin --profile <profile> add /path/to/dsh-kylin-media
26
+ ```
27
+
28
+ 安装后如果页面没有出现菜单,刷新一次浏览器;替换同版本包需要重启宿主进程才能加载新的客户端 JavaScript。
29
+
30
+ ## 发布到 npm
31
+
32
+ 包已在 `package.json` 里配置 `publishConfig.registry = https://registry.npmjs.org/`,`npm publish` 不会误发到本机配置的 npmmirror(镜像是只读的,发不上去)。
33
+
34
+ ```bash
35
+ npm login --registry=https://registry.npmjs.org/
36
+ npm whoami --registry=https://registry.npmjs.org/
37
+
38
+ cd dsh-kylin-media
39
+ npm publish # prepack 会自动跑 smoke
40
+ ```
41
+
42
+ - 发布前可先 `npm pack --dry-run` 检查载荷(`files` 白名单,约 17-19 个文件)。
43
+ - 版本一旦发布不可覆盖;升级用 `npm version patch|minor|major` 后再 publish。
44
+ - 刚发布的版本可能被宿主 profile 的 `minimumReleaseAge`(pnpm 默认 24h)拒绝安装,等一段时间或把包名加入该 profile 的排除项。
45
+ - 安装:`qilin plugin --profile <profile> add dsh-kylin-media`。
46
+
47
+ ## 设置
48
+
49
+ 打开 **设置 → 多媒体网关**:
50
+
51
+ | 项 | 说明 |
52
+ |---|---|
53
+ | 网关地址 | 默认 `http://127.0.0.1:8288`;局域网用 `http://<主机IP>:8288`,frp / 反代填对外地址。编辑的是「当前线路」的地址 |
54
+ | 连接线路 | 可同时保存多条地址(本机 / 局域网 / frp 公网),点圆点切换当前线路,「测试连接」与所有 `media_*` 都用它;「全部测速」并发探测每条线路并标出最快可用的那条 |
55
+ | 访问 Key | 网关 `API_KEY_MODE=always` 时必填;保存后不再回显明文,留空表示沿用已保存的值 |
56
+ | 单次最多等待 | 工具调用内等待任务的秒数(10-600);超时不影响网关侧任务,可继续用 `media_job` |
57
+ | 产物目录 | 留空 = `<会话目录>/media-output/<任务 id>/`;也可填绝对路径 |
58
+ | 自动下载 | 关闭后只返回远端 URL,用 `media_job action=download` 取回 |
59
+ | 默认模型 | 「可用能力」卡片里逐类型列出网关实时目录中的模型,点选即设为该类型默认模型并立即保存;`media_*` 未传 `model` 时用它,没选则用该类型第一个可用模型 |
60
+
61
+ 页面上的「测试连接」会读取 `/api/health` 与 `/api/models`,显示网关版本、鉴权模式、ComfyUI 与双卡队列,并按能力类型列出具体模型(含可用性与权重缺失),可直接点选默认模型。连接失败时会给出排查提示。
62
+
63
+ > 常见坑:网关默认监听明文 HTTP(`API_PORT=8288`)。frp / 反代把 8288 映射出去后仍然是 HTTP,地址要写 `http://<对外地址>:<端口>`;写成 `https://` 会在 TLS 握手阶段被断开,错误信息里会提示「这个端口没有完成 TLS 握手…把地址改成 http:// 再试」。反过来,如果前面套了 nginx / Caddy 的 HTTPS,则必须写 `https://`(自签证书还需要让运行宿主信任该 CA)。
64
+
65
+ > 为什么「本机 / 局域网」地址连不上:
66
+ > 1. `127.0.0.1` / `localhost` 只有**网关和插件跑在同一台机器**时才通。网关在远端(例如 Windows 主机)而插件在 Mac 上时,本机地址必然被拒绝。
67
+ > 2. 局域网地址要求两者**在同一网段**,且网关监听 `HOST=0.0.0.0`(默认)、系统防火墙放行 8288(仓库里有 `add-firewall-rule.bat`)。可先用 `curl http://<主机IP>:8288/api/health` 验证。
68
+ > 3. 上面两条都不满足时只能用 frp / 公网地址。把三条地址都加进「连接线路」,点「全部测速」即可看出哪条通、哪条最快;失败原因直接写在行内(拒绝连接 / 不可达 / 域名解析失败 / 协议写反)。
69
+ >
70
+ > 局域网里偶发 `EHOSTUNREACH`(刚唤醒、Wi-Fi 切换、ARP 未就绪)不用管:所有 GET 探测都会自动重试最多 2 次;仍失败时先在本机 `curl http://<主机IP>:8288/api/health` 复核。
71
+
72
+ ## 工具
73
+
74
+ | 工具 | 作用 |
75
+ |---|---|
76
+ | `media_health` | 网关 / ComfyUI / 队列 / 鉴权状态;`action=test` 附带能力目录 |
77
+ | `media_models` | 按类型列模型、可用性与缺失文件;传 `model` 看参数 schema |
78
+ | `media_generate` | 按「类型 + 模型」提交生成,支持等待与自动下载 |
79
+ | `media_audio` | `transcribe` / `speech` / `separate` 三种语音能力 |
80
+ | `media_job` | `status` / `wait` / `list` / `cancel` / `delete` / `download` |
81
+ | `media_upload` | 上传参考图 / 音频 / 视频,返回可填进 `params.image` 等的 `name` |
82
+
83
+ 生成类型:`text2image`、`image_edit`、`text2video`、`image2video`、`reference2video`、`lipsync`、`music`、`upscale`、`video_upscale`、`extract_frame`。
84
+ 同族模型带 `tier`(`fast`/`balanced`/`quality`)与 `group`;不给 `model` 时可传 `tier` + `group` 选档,例如 `media_generate type=video_upscale tier=fast group=video-upscale params={"video":"clip.mp4"}`。
85
+ 错误码 `missing-nodes`(缺 ComfyUI 节点)、`tier-not-found`、`ambiguous-group` 会附带修复建议。
86
+ 语音能力:`asr`(whisper)、`tts`(本地 MeloTTS / 小米 MiMo)、`separate`(demucs 4 轨)。
87
+
88
+ ### 例子
89
+
90
+ ```text
91
+ media_generate type=text2image params={"prompt":"雪夜里的红灯笼,浅景深","width":1024,"height":576,"seed":42}
92
+
93
+ media_upload file=D:\refs\frame.png
94
+ media_generate type=image2video params={"prompt":"她转身微笑","image":"frame.png","length":124} wait=false
95
+ media_job action=wait id=<上一步的 job id> waitSeconds=300
96
+
97
+ media_audio action=transcribe file=D:\audio\song.wav language=zh srt=true
98
+ media_audio action=speech text="你好,这是本地语音合成。" format=mp3
99
+ ```
100
+
101
+ 产物默认落到会话目录的 `media-output/<任务 id>/`,返回绝对路径;图片可直接用 `read_image` 查看。
102
+
103
+ ## 包契约
104
+
105
+ - `package.json` 同时声明 `dsh.bundle.patch` 与 `qilin.bundle.patch`,两者指向同一份 `cordis.patch.yml`;
106
+ - `dsh.client.bundle` / `qilin.client.bundle` 指向手写零构建的 `client.js`,通过 `window.__ModuleLoader__.load` 自注册;
107
+ - `files` 是发布载荷白名单,新增模块或资源时同步更新;
108
+ - 无运行时依赖,Node ≥ 20。
109
+
110
+ ## 安全边界
111
+
112
+ - 插件 API 只接受回环 `Host`(`127.0.0.1` / `localhost` / `::1`),其它来源一律 403;
113
+ - 访问 Key 不写入 composition,不走宿主设置 RPC,只存在 `<QILIN_HOME|DSH_HOME|~/.kcoder>/.dsh-kylin-media/settings.json`;
114
+ - 任何响应都不包含明文 Key;UI 输入框保存后即清空;
115
+ - 产物下载只允许当前网关同源的 `/api/files/*` 地址,避免被任务数据带去任意主机。
116
+
117
+ ## 开发
118
+
119
+ ```bash
120
+ cd dsh-kylin-media
121
+ npm test # smoke(包契约 + 客户端自注册 + locale/icon/技能)+ selftest(mock ctx + mock 网关)+ client-test(渲染自测)
122
+ ```
123
+
124
+ `selftest` 会用临时 HOME 与 `127.0.0.1` 上的 mock 网关跑完整链路:设置持久化、403 / 400 / 404 / 405 围栏、默认模型选择与回退、提交轮询、产物下载、鉴权头、注册与卸载。
125
+
126
+ `client-test` 用最小 React 替身渲染设置页的「可用能力」卡片:类型卡片列出具体模型、默认模型高亮、点选后 POST `settings.update`、缺权重模型不可选,且渲染树不含明文 Key。
127
+
128
+ ## 目录
129
+
130
+ ```
131
+ dsh-kylin-media/
132
+ ├── entry.js # 宿主入口:设置播种、工具 / 路由 / 技能注册
133
+ ├── client.js # 设置页菜单(手写零构建)
134
+ ├── lib/
135
+ │ ├── home.js # 插件私有目录解析
136
+ │ ├── store.js # settings.json(0600、原子写、Key 脱敏)
137
+ │ ├── gateway.js # comfyui-gateway 客户端
138
+ │ ├── runner.js # 轮询、终态、下载
139
+ │ ├── catalog.js # 类型标签与能力摘要
140
+ │ ├── tools.js # media_* 工具面
141
+ │ └── routes.js # fenced JSON API
142
+ ├── skills/kylin-media/ # 随包技能
143
+ ├── locale/ # 插件管理器展示元数据
144
+ └── scripts/ # smoke / selftest / client-test
145
+ ```
146
+
147
+ ## License
148
+
149
+ MIT