dsh-media-converter 1.1.0 → 1.2.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 +79 -15
- package/client.js +31 -3
- package/client.js.map +1 -1
- package/dist/index.js +922 -0
- package/dist/lib/base64.js +87 -0
- package/dist/lib/plan.js +425 -0
- package/dist/lib/platform.js +110 -0
- package/package.json +25 -7
- package/index.js +0 -518
- package/lib/base64.js +0 -73
- package/lib/plan.js +0 -342
- package/lib/platform.js +0 -100
package/README.md
CHANGED
|
@@ -19,6 +19,22 @@ DeepSeek Harness 的本地多媒体工具箱插件:转换、裁剪、提取音
|
|
|
19
19
|
|
|
20
20
|
界面是一个「动作面板」:选文件 → 搜索或点动作 → 参数就地展开 → 结果就地显示。支持 `⌘K` 聚焦搜索、回车执行第一个动作、Esc 收起。
|
|
21
21
|
|
|
22
|
+
## 给 Agent 用的工具
|
|
23
|
+
|
|
24
|
+
同一个引擎也注册成工具 `media_toolbox`,助手可以直接调用:
|
|
25
|
+
|
|
26
|
+
| action | 作用 |
|
|
27
|
+
| --- | --- |
|
|
28
|
+
| `probe` | 读时长、分辨率、编码、音轨、字幕轨、标签 |
|
|
29
|
+
| `convert` | 转格式(可带 `trim` 裁剪、`quality` 图片质量) |
|
|
30
|
+
| `extract-audio` / `extract-video` | 抽音轨 / 抽画面,不重编码 |
|
|
31
|
+
| `subtitle` | 导出内嵌字幕为 `.srt` |
|
|
32
|
+
| `rewrite-tags` | 改写标题/作者/专辑/备注/日期/流派 |
|
|
33
|
+
|
|
34
|
+
工具吃的是**本机绝对路径**,不走上传:产物写在同一个输出目录,返回新文件路径。调用被取消或超时(30 分钟)时,ffmpeg 会被终止,半成品会被清掉。
|
|
35
|
+
|
|
36
|
+
输入框工具排(「+」按钮那一排)有一个「媒体工具箱」按钮:点一下把示例指令 `把 xx.mov 裁 0:10 到 1:00 转成 mp4` 插进输入框,改成你的文件和区间后发送即可。
|
|
37
|
+
|
|
22
38
|
## 大文件
|
|
23
39
|
|
|
24
40
|
- **不整文件进内存**:上传边收边落盘;Base64 结果边编码边发回;预览走 HTTP Range,拖进度条不会整段下载。
|
|
@@ -56,7 +72,9 @@ dsh plugin add github:a1121611810/dsh-media-converter --profile <profile>
|
|
|
56
72
|
|
|
57
73
|
## 配置
|
|
58
74
|
|
|
59
|
-
|
|
75
|
+
设置弹窗侧边栏的「媒体工具箱」页可直接编辑配置:保存经宿主的 settings 服务校验并写入 profile(`cordis.patch.yml` 里会出现对应的 `config` 块),同时**立即应用到运行中的插件**——宿主加载器不会热重载,是插件在保存后自行应用合并,所以无需重启;直接手改 `cordis.patch.yml` 才需要重启。留空的字段保持默认(输出目录默认 `~/Downloads/media-toolbox`,ffmpeg 自动查找,上传上限 2048 MB)。
|
|
76
|
+
|
|
77
|
+
同一个配置也驱动「内置插件」页里本插件行的官方配置表单(来自插件导出的 Schemastery schema,字段标记 `volatile()` 才可编辑):
|
|
60
78
|
|
|
61
79
|
```yaml
|
|
62
80
|
- id: media-converter
|
|
@@ -64,44 +82,89 @@ dsh plugin add github:a1121611810/dsh-media-converter --profile <profile>
|
|
|
64
82
|
config:
|
|
65
83
|
outputDir: ~/Movies/converted
|
|
66
84
|
ffmpegPath: /opt/homebrew/bin/ffmpeg
|
|
85
|
+
maxUploadMb: 2048
|
|
67
86
|
```
|
|
68
87
|
|
|
69
|
-
|
|
88
|
+
- `outputDir`:`~` 会展开成主目录,路径会被解析成绝对路径。
|
|
89
|
+
- `ffmpegPath`:找不到 ffmpeg 时手动指定。
|
|
90
|
+
- `maxUploadMb`:单次上传上限(默认 2048 MB),超了直接拒绝,不写盘。
|
|
91
|
+
- `composerButton`:是否在输入框工具排显示「媒体工具箱」按钮(默认开)。
|
|
92
|
+
- `groups`:动作面板的模块顺序与显隐(`convert,edit,view`,写进字符串的才显示)。
|
|
93
|
+
- 设置页右上角还有版本号显示与「刷新界面」(等同 Ctrl+R)。
|
|
94
|
+
|
|
95
|
+
插件导出 `Config` schema 供宿主的 settings 服务投影表单(这是唯一的运行时依赖 `@deepseek-ai/schemastery`,由 npm 正常安装)。
|
|
70
96
|
|
|
71
97
|
## 开发
|
|
72
98
|
|
|
73
99
|
```bash
|
|
74
|
-
npm test #
|
|
100
|
+
npm test # 类型检查 + 构建(宿主 dist/ 与浏览器 client.js)+ 六套自检
|
|
101
|
+
npm run build # 构建:宿主 tsrs → dist/,浏览器 vite → client.js
|
|
102
|
+
npm run build:host # 只构建宿主半边(tsrs → dist/)
|
|
75
103
|
npm run build:client # 只构建浏览器半边(vite → client.js + sourcemap)
|
|
104
|
+
npm run typecheck # 只做类型检查(tsrs,连 .vue 一起查)
|
|
76
105
|
npm run check:build # 改了源码却没重新构建时失败(CI 用)
|
|
77
106
|
```
|
|
78
107
|
|
|
79
|
-
|
|
108
|
+
源码是 TypeScript(strict):宿主是 `index.ts` + `lib/*.ts`,浏览器是 `src/client/*.ts` + `.vue`(`<script setup lang="ts">`)。类型只进编译期,**运行时零新增依赖**——npm 包里只有编译好的 JS。测试保持 `test/*.test.mjs` 不转,但改成跑**编译产物**,测的正是发布形态的代码。
|
|
109
|
+
|
|
110
|
+
编译器用 [`tsrs`](https://github.com/oxc-project/tsrs)(TypeScript 7 的 Rust 移植版,drop-in 替换 `tsc`):`.vue` 走 TypeScript 7 的 content-mapper 协议检查(`@vue/content-mapper` 把 SFC 变成虚拟 TS),所以**没有 `vue-tsc`**。副作用:检查时编译产物与 tsc 5.9 逐字节相同,宿主检查快约 3 倍。
|
|
111
|
+
|
|
112
|
+
两半都是**构建产物**:
|
|
113
|
+
|
|
114
|
+
- 浏览器半边:`src/client/` 是源码,`client.js` 提交进仓库(DSH 直接从包目录读它,链接安装不会触发构建)。改了 `src/client/` 之后必须 `npm run build:client`,否则 `check:build` 会红。
|
|
115
|
+
- 宿主半边:源码是 `index.ts` + `lib/*.ts`,`tsrs` 编到 `dist/`,npm 包的入口是 `dist/index.js`。改完必须 `npm run build:host`,再**重启 DSH**。
|
|
116
|
+
|
|
117
|
+
两半之间的 JSON 契约**没有单独一份文件**:类型就住在产出数据的那段代码旁边(`lib/plan.ts`、`index.ts`),能推导的就推导(`ReturnType<typeof parseMeta>`),只有被多状态改写的形状(Job 状态机)才手写一次。面板用 `import type` 引入——编译期完全擦除,浏览器包不会因此拖进 `node:fs`。
|
|
80
118
|
|
|
81
119
|
```bash
|
|
82
120
|
node test/client-bundle.test.mjs # 产物契约:loader 握手、React 注入、两个槽位
|
|
121
|
+
node test/client-lib.test.mjs # 面板纯函数:格式化、时间码、裁剪窗口
|
|
83
122
|
node test/plan.test.mjs # 格式表、参数、元数据解析、裁剪
|
|
84
123
|
node test/base64.test.mjs # 魔数嗅探、Base64 往返、文本回退
|
|
85
|
-
node test/platform.test.mjs # ffmpeg
|
|
86
|
-
node test/host.test.mjs # 真 ffmpeg 端到端:27 种格式矩阵 + 字幕 + 标签改写 + 取消 + 失败路径
|
|
124
|
+
node test/platform.test.mjs # ffmpeg 查找顺序、文件管理器命令、文件名规则、目录归属判定(含 Windows 分支)
|
|
125
|
+
node test/host.test.mjs # 真 ffmpeg 端到端:27 种格式矩阵 + 字幕 + 标签改写 + 取消 + 失败路径 + Agent 工具 + 上传上限
|
|
87
126
|
```
|
|
88
127
|
|
|
89
128
|
`test/host.test.mjs` 需要本机有 ffmpeg;没有会**失败**(不是跳过——静默跳过等于假绿)。
|
|
90
129
|
|
|
130
|
+
## 代码风格
|
|
131
|
+
|
|
132
|
+
- **[oxlint](https://oxc.rs/docs/guide/usage/linter)**:配置在 `.oxlintrc.json`。只开 `correctness` 一类——`suspicious`/`perf`/`style`/`restriction` 全开是 11/13/1750/137 条意见,基本是风格口味,其中 `no-await-in-loop`(上传和转码是**故意**串行的)、`no-underscore-dangle`(`__dshReact` 是 loader 的契约名)和这个仓库的写法正面冲突。插件开 `typescript`/`oxc`/`unicorn`/`import`/`node`/`vue`;`.vue` 的 `<script>` 块会被查(`vue` 插件)。两处 `no-control-regex` 是故意的(文件名里的控制字符就是要剔掉),在代码里就地豁免;`reportUnusedDisableDirectives` 会把失效的豁免报成错——它已经抓到过一条 2024 年留下的死豁免。
|
|
133
|
+
- **[oxfmt](https://oxc.rs/docs/guide/usage/formatter)**:配置在 `.oxfmtrc.json`(单引号、行宽 120、`sortPackageJson: false`——不动已发布的 keywords 顺序)。`client.js`(压缩产物)和 `README.md` 不进格式化范围:前者是产物,后者一格式化就会按字符数给中文表格补列宽(CJK 是双宽字符,补出来的分隔线长短不齐)。`.editorconfig` 让编辑器跟格式化器用同一套缩进和行宽。
|
|
134
|
+
- **类型相关的 lint 规则没开**:`oxlint --type-aware`(需要额外的 `oxlint-tsgolint`)在这个仓库只报出 4 条,全是误报——`const h = React.createElement`、`export const apply = plugin.apply` 这种解引用方法(本来就不依赖 `this`)、测试里故意用的 `new Function`、以及断言里的 `.sort()`。类型层面的问题由 `tsrs` 负责,重复跑一套类型引擎不值。
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
npm run lint # oxlint
|
|
138
|
+
npm run lint:fix # oxlint --fix
|
|
139
|
+
npm run format # oxfmt,就地改写
|
|
140
|
+
npm run format:check # oxfmt --check,只报不改
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
`npm test` 里已经带上 `lint` 与 `format:check`,所以 CI 和发版都会拦住风格漂移。
|
|
144
|
+
|
|
145
|
+
### 发版
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
npm run release -- 1.2.0
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
一条命令做完全部步骤:校验在 main、工作区干净、跑 `npm test`、确认产物不是旧的、bump 版本、打 tag、push。**tag 推上去之后由 CI 发布**——本地 `npm publish` 会被 `prepublishOnly` 拒绝,所以不存在"手动发一半"的状态。CI 发布前会重跑全部测试并比对 tag 与 `package.json` 的版本。
|
|
152
|
+
|
|
91
153
|
## 结构
|
|
92
154
|
|
|
93
155
|
```
|
|
94
|
-
src/client/index.
|
|
156
|
+
src/client/index.ts 加载器握手 + React 8 行壳 + 侧边栏图标 + i18n 字典 + CSS
|
|
95
157
|
src/client/App.vue <media-panel>:状态机、动作面板、预览/对比、Base64、元数据
|
|
96
158
|
src/client/vue/ CompareSlider、ResultBlock(普通 Vue 组件)
|
|
97
|
-
src/client/lib.
|
|
98
|
-
vite.config.
|
|
159
|
+
src/client/lib.ts 纯函数(格式化/时间码/裁剪窗口)+ fetch 封装,不碰 DOM
|
|
160
|
+
vite.config.ts 构建:IIFE + __ModuleLoader__ 握手 + React 走宿主模块表
|
|
99
161
|
client.js 构建产物(提交进仓库,勿手改)
|
|
100
|
-
index.
|
|
101
|
-
lib/plan.
|
|
102
|
-
lib/base64.
|
|
103
|
-
lib/platform.
|
|
104
|
-
test/
|
|
162
|
+
index.ts 宿主:/api/media-convert/* 路由、ffmpeg 任务、预览与 Base64、Agent 工具 media_toolbox
|
|
163
|
+
lib/plan.ts 格式表、参数生成、元数据解析、裁剪(也定义面板要用的媒体类型)
|
|
164
|
+
lib/base64.ts Base64 嗅探与还原
|
|
165
|
+
lib/platform.ts ffmpeg 查找、文件管理器、文件名规则(纯函数,跨平台分支可测)
|
|
166
|
+
test/ 六套自检(.mjs,跑编译产物)
|
|
167
|
+
dist/ 构建产物:宿主入口 dist/index.js(npm 包入口)+ dist/lib/、dist/src/
|
|
105
168
|
```
|
|
106
169
|
|
|
107
170
|
React 只剩一个壳:把 `<media-panel>` 挂进槽位并传 `t`。面板本身是 Vue,`shadowRoot: false`(light DOM),样式由壳注入的 `<style>` 提供——Vue 的 `defineCustomElement` 在 light DOM 下不会注入 SFC 样式。
|
|
@@ -109,6 +172,7 @@ React 只剩一个壳:把 `<media-panel>` 挂进槽位并传 `t`。面板本
|
|
|
109
172
|
## 限制
|
|
110
173
|
|
|
111
174
|
- Base64 单文件上限 24 MB。
|
|
175
|
+
- 上传单文件上限 2048 MB(`maxUploadMb` 可调)。
|
|
112
176
|
- 裁剪区间必须落在文件时长内;区间无效时按钮不可用。
|
|
113
177
|
- 视频转 GIF 会缩到宽 640、12 fps。
|
|
114
178
|
- 上传的临时副本保留 2 小时后自动删除。
|
|
@@ -126,4 +190,4 @@ React 只剩一个壳:把 `<media-panel>` 挂进槽位并传 `t`。面板本
|
|
|
126
190
|
[dsh-media-converter] upload failed: aborted # 连接中断
|
|
127
191
|
```
|
|
128
192
|
|
|
129
|
-
宿主的这些行在 DSH 的日志里;改了 `index.
|
|
193
|
+
宿主的这些行在 DSH 的日志里;改了 `index.ts` 之后必须 `npm run build:host` 并**重启 DSH**才会生效(运行中的宿主用的是启动时那份代码)。
|