dsh-ffmpeg 0.3.0 → 0.4.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.en.md +4 -2
- package/README.md +6 -3
- package/lib/args.d.ts +26 -0
- package/lib/args.js +66 -0
- package/lib/tools.d.ts +1 -1
- package/lib/tools.js +66 -8
- package/package.json +60 -60
package/README.en.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
[中文](README.md)
|
|
2
2
|
|
|
3
|
+
   
|
|
4
|
+
|
|
3
5
|
# dsh-ffmpeg
|
|
4
6
|
|
|
5
7
|
[](https://awesome-dsh-plugin.com)
|
|
@@ -8,7 +10,7 @@ DSH (DeepSeek Harness) video-processing plugin: seven tools covering probing, cu
|
|
|
8
10
|
|
|
9
11
|
## Compatibility
|
|
10
12
|
|
|
11
|
-
Verified against `@deepseek-ai/dsh@0.1.
|
|
13
|
+
Verified against `@deepseek-ai/dsh@0.1.2-alpha.2` on 2026-08-31. Built for the cordis patch-bundle plugin model (`cordis.patch.yml` + `dsh.bundle.patch`). No runtime imports of `@deepseek-ai/*` internals.
|
|
12
14
|
|
|
13
15
|
## Installation
|
|
14
16
|
|
|
@@ -80,4 +82,4 @@ pnpm test # build + 57 tests, including a real-ffmpeg end-to-end suite (au
|
|
|
80
82
|
|
|
81
83
|
## License
|
|
82
84
|
|
|
83
|
-
MIT
|
|
85
|
+
MIT
|
package/README.md
CHANGED
|
@@ -2,18 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
# dsh-ffmpeg
|
|
4
4
|
|
|
5
|
-
> **你的 agent 会剪视频了**:探测/剪辑/拼接/转码/字幕/抽帧/GIF
|
|
5
|
+
> **你的 agent 会剪视频了**:探测/剪辑/拼接/转码/字幕/抽帧/GIF/变速旋转调音,十个工具一条命令。
|
|
6
6
|
|
|
7
7
|
   
|
|
8
8
|
|
|
9
9
|
[](https://awesome-dsh-plugin.com)
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
DSH(DeepSeek Harness
|
|
12
|
+
DSH(DeepSeek Harness)视频处理工具插件:十个工具:探测、剪辑、拼接、转码、字幕、提取、GIF、抽帧、调整(变速/音量/静音/旋转)与自检,全部由 ffmpeg/ffprobe 完成。
|
|
13
13
|
|
|
14
14
|
## 兼容性
|
|
15
15
|
|
|
16
|
-
在 `@deepseek-ai/dsh@0.1.
|
|
16
|
+
在 `@deepseek-ai/dsh@0.1.2-alpha.2` 上验证(2026-08-31)。遵循 cordis 组合包补丁模型(`cordis.patch.yml` + `dsh.bundle.patch`),运行时不 import 任何 `@deepseek-ai/*` 内部模块。
|
|
17
17
|
|
|
18
18
|
## 安装
|
|
19
19
|
|
|
@@ -57,6 +57,9 @@ dsh plugin --profile web remove dsh-ffmpeg
|
|
|
57
57
|
| `ffmpeg_subtitle` | 字幕烧录(SRT/ASS 硬字幕) | `input`+`subtitle` 必填 |
|
|
58
58
|
| `ffmpeg_extract` | 提取音轨(m4a)/ 抽帧序列 / 单帧 / 字幕流 | `input`+`what` 必填 |
|
|
59
59
|
| `ffmpeg_gif` | 视频转高质量 GIF(两遍调色板) | `input` 必填;`fps`/`width`/`duration` 可选 |
|
|
60
|
+
| `ffmpeg_frames` | 批量抽帧给视觉模型读图(定间隔或指定时间点,PNG/JPG) | `input` 必填;`every`/`times` 二选一 |
|
|
61
|
+
| `ffmpeg_adjust` | 变速(音视频同步)/ 音量 / 静音 / 旋转(竖横屏互转),可组合 | `input` 必填;`speed`/`volume`/`mute`/`rotate` 至少一个 |
|
|
62
|
+
| `ffmpeg_health` | 自检 ffmpeg / ffprobe 可执行文件 | 无 |
|
|
60
63
|
|
|
61
64
|
### 示例
|
|
62
65
|
|
package/lib/args.d.ts
CHANGED
|
@@ -87,3 +87,29 @@ export interface GifSpec {
|
|
|
87
87
|
export declare function gifPaletteArgs(ffmpeg: string, spec: GifSpec): string[];
|
|
88
88
|
/** GIF 第二遍:paletteuse 合成。 */
|
|
89
89
|
export declare function gifUseArgs(ffmpeg: string, spec: GifSpec): string[];
|
|
90
|
+
export type RotateDeg = 90 | 180 | 270;
|
|
91
|
+
export interface AdjustSpec {
|
|
92
|
+
input: string;
|
|
93
|
+
output: string;
|
|
94
|
+
overwrite: boolean;
|
|
95
|
+
/** 倍速:>1 加速,<1 减速(0.1-100)。 */
|
|
96
|
+
speed?: number;
|
|
97
|
+
/** 音量:倍数(如 1.5 / 0.6)或分贝(如 -3dB)。 */
|
|
98
|
+
volume?: string;
|
|
99
|
+
mute?: boolean;
|
|
100
|
+
rotate?: RotateDeg;
|
|
101
|
+
/** 输入是否含音频流(probe 结果),决定是否构建音频滤镜。 */
|
|
102
|
+
hasAudio: boolean;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* atempo 单滤镜只接受约 [0.5, 100],超出范围用多个 atempo 级联
|
|
106
|
+
* (0.25 → atempo=0.5,atempo=0.5)。
|
|
107
|
+
*/
|
|
108
|
+
export declare function atempoChain(speed: number): string;
|
|
109
|
+
/** 顺时针旋转滤镜:90/270 用 transpose,180 用双翻转。 */
|
|
110
|
+
export declare function rotateFilter(deg: RotateDeg): string;
|
|
111
|
+
/**
|
|
112
|
+
* 调整:变速(视频 setpts + 音频 atempo)、音量、静音、旋转。
|
|
113
|
+
* 只静音/调音量(无变速旋转)时视频走流拷贝;动了画面就重编码。
|
|
114
|
+
*/
|
|
115
|
+
export declare function adjustArgs(ffmpeg: string, spec: AdjustSpec): string[];
|
package/lib/args.js
CHANGED
|
@@ -111,3 +111,69 @@ export function gifUseArgs(ffmpeg, spec) {
|
|
|
111
111
|
const filter = 'fps=' + spec.fps + ',scale=' + spec.width + ':-1:flags=lanczos[x];[x][1:v]paletteuse';
|
|
112
112
|
return [ffmpeg, overwriteFlag(spec.overwrite), '-i', spec.input, '-ss', fmtSeconds(spec.start), '-t', fmtSeconds(spec.duration), '-i', spec.palettePath, '-filter_complex', filter, spec.output];
|
|
113
113
|
}
|
|
114
|
+
/**
|
|
115
|
+
* atempo 单滤镜只接受约 [0.5, 100],超出范围用多个 atempo 级联
|
|
116
|
+
* (0.25 → atempo=0.5,atempo=0.5)。
|
|
117
|
+
*/
|
|
118
|
+
export function atempoChain(speed) {
|
|
119
|
+
const parts = [];
|
|
120
|
+
let remaining = speed;
|
|
121
|
+
while (remaining < 0.5) {
|
|
122
|
+
parts.push('atempo=0.5');
|
|
123
|
+
remaining /= 0.5;
|
|
124
|
+
}
|
|
125
|
+
while (remaining > 100) {
|
|
126
|
+
parts.push('atempo=100');
|
|
127
|
+
remaining /= 100;
|
|
128
|
+
}
|
|
129
|
+
parts.push('atempo=' + Number(remaining.toFixed(4)));
|
|
130
|
+
return parts.join(',');
|
|
131
|
+
}
|
|
132
|
+
/** 顺时针旋转滤镜:90/270 用 transpose,180 用双翻转。 */
|
|
133
|
+
export function rotateFilter(deg) {
|
|
134
|
+
if (deg === 90)
|
|
135
|
+
return 'transpose=1';
|
|
136
|
+
if (deg === 270)
|
|
137
|
+
return 'transpose=2';
|
|
138
|
+
return 'hflip,vflip';
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* 调整:变速(视频 setpts + 音频 atempo)、音量、静音、旋转。
|
|
142
|
+
* 只静音/调音量(无变速旋转)时视频走流拷贝;动了画面就重编码。
|
|
143
|
+
*/
|
|
144
|
+
export function adjustArgs(ffmpeg, spec) {
|
|
145
|
+
const parts = [ffmpeg, overwriteFlag(spec.overwrite), '-i', spec.input];
|
|
146
|
+
const vf = [];
|
|
147
|
+
const af = [];
|
|
148
|
+
const audioUsable = spec.hasAudio && spec.mute !== true;
|
|
149
|
+
if (spec.speed !== undefined) {
|
|
150
|
+
vf.push('setpts=PTS/' + spec.speed);
|
|
151
|
+
if (audioUsable)
|
|
152
|
+
af.push(atempoChain(spec.speed));
|
|
153
|
+
}
|
|
154
|
+
if (spec.volume !== undefined && audioUsable)
|
|
155
|
+
af.push('volume=' + spec.volume);
|
|
156
|
+
if (spec.rotate !== undefined)
|
|
157
|
+
vf.push(rotateFilter(spec.rotate));
|
|
158
|
+
if (vf.length > 0)
|
|
159
|
+
parts.push('-vf', vf.join(','));
|
|
160
|
+
if (af.length > 0)
|
|
161
|
+
parts.push('-af', af.join(','));
|
|
162
|
+
if (vf.length > 0) {
|
|
163
|
+
parts.push('-c:v', 'libx264', '-preset', 'veryfast', '-crf', '18', '-pix_fmt', 'yuv420p');
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
parts.push('-c:v', 'copy');
|
|
167
|
+
}
|
|
168
|
+
if (spec.mute === true || !spec.hasAudio) {
|
|
169
|
+
parts.push('-an');
|
|
170
|
+
}
|
|
171
|
+
else if (af.length > 0) {
|
|
172
|
+
parts.push('-c:a', 'aac', '-b:a', '192k');
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
parts.push('-c:a', 'copy');
|
|
176
|
+
}
|
|
177
|
+
parts.push('-movflags', '+faststart', spec.output);
|
|
178
|
+
return parts;
|
|
179
|
+
}
|
package/lib/tools.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* 九个面向模型的视频工具:probe / cut / concat / encode / subtitle / extract / gif / frames / adjust。
|
|
3
3
|
* 直接调用 ctx.tools.register 注册【编译好的 JSON Schema】参数与 canonical 输出。
|
|
4
4
|
*
|
|
5
5
|
* @module dsh-ffmpeg/tools
|
package/lib/tools.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* 九个面向模型的视频工具:probe / cut / concat / encode / subtitle / extract / gif / frames / adjust。
|
|
3
3
|
* 直接调用 ctx.tools.register 注册【编译好的 JSON Schema】参数与 canonical 输出。
|
|
4
4
|
*
|
|
5
5
|
* @module dsh-ffmpeg/tools
|
|
@@ -8,7 +8,7 @@ import { mkdirSync, readdirSync, rmSync, writeFileSync } from 'node:fs';
|
|
|
8
8
|
import { randomUUID } from 'node:crypto';
|
|
9
9
|
import { tmpdir } from 'node:os';
|
|
10
10
|
import { basename, dirname, extname, join } from 'node:path';
|
|
11
|
-
import { concatArgs, concatListContent, cutArgs, ENCODE_PRESETS, encodeArgs, extractArgs, fmtSeconds, frameAtArgs, gifPaletteArgs, gifUseArgs, probeArgs, subtitleArgs, } from './args.js';
|
|
11
|
+
import { adjustArgs, concatArgs, concatListContent, cutArgs, ENCODE_PRESETS, encodeArgs, extractArgs, fmtSeconds, frameAtArgs, gifPaletteArgs, gifUseArgs, probeArgs, subtitleArgs, } from './args.js';
|
|
12
12
|
import { parseProbeJson } from './ffprobe.js';
|
|
13
13
|
import { assertInputFile, resolveOutputPath, sanitizeName } from './paths.js';
|
|
14
14
|
import { parseTimeArg } from './config.js';
|
|
@@ -80,12 +80,12 @@ function buildTextRenderer(lines) {
|
|
|
80
80
|
const baseSchema = { type: 'object', additionalProperties: true };
|
|
81
81
|
const videoStreamSchema = {
|
|
82
82
|
type: 'object',
|
|
83
|
-
properties: { width: { type: 'number' }, height: { type: 'number' }, fps: { type: 'number' }, codec: { type: 'string' }, durationSeconds: { type: 'number' }, bitrate: { type: 'number' } },
|
|
83
|
+
properties: { width: { type: 'number' }, height: { type: 'number' }, fps: { oneOf: [{ type: 'number' }, { type: 'null' }] }, codec: { type: 'string' }, durationSeconds: { oneOf: [{ type: 'number' }, { type: 'null' }] }, bitrate: { oneOf: [{ type: 'number' }, { type: 'null' }] } },
|
|
84
84
|
additionalProperties: true,
|
|
85
85
|
};
|
|
86
86
|
const audioStreamSchema = {
|
|
87
87
|
type: 'object',
|
|
88
|
-
properties: { codec: { type: 'string' }, sampleRate: { type: 'number' }, channels: { type: 'number' }, durationSeconds: { type: 'number' } },
|
|
88
|
+
properties: { codec: { type: 'string' }, sampleRate: { oneOf: [{ type: 'number' }, { type: 'null' }] }, channels: { oneOf: [{ type: 'number' }, { type: 'null' }] }, durationSeconds: { oneOf: [{ type: 'number' }, { type: 'null' }] } },
|
|
89
89
|
additionalProperties: true,
|
|
90
90
|
};
|
|
91
91
|
const subtitleStreamSchema = {
|
|
@@ -100,9 +100,9 @@ const probeSchema = {
|
|
|
100
100
|
input: { type: 'string' },
|
|
101
101
|
summary: { type: 'string' },
|
|
102
102
|
formatName: { type: 'string' },
|
|
103
|
-
durationSeconds: { type: 'number' },
|
|
104
|
-
sizeBytes: { type: 'number' },
|
|
105
|
-
bitrate: { type: 'number' },
|
|
103
|
+
durationSeconds: { oneOf: [{ type: 'number' }, { type: 'null' }] },
|
|
104
|
+
sizeBytes: { oneOf: [{ type: 'number' }, { type: 'null' }] },
|
|
105
|
+
bitrate: { oneOf: [{ type: 'number' }, { type: 'null' }] },
|
|
106
106
|
video: videoStreamSchema,
|
|
107
107
|
videos: { type: 'array', items: videoStreamSchema },
|
|
108
108
|
audio: { type: 'array', items: audioStreamSchema },
|
|
@@ -507,6 +507,64 @@ export function buildFfmpegTools(config, runner) {
|
|
|
507
507
|
},
|
|
508
508
|
timeoutMs: timeout,
|
|
509
509
|
};
|
|
510
|
+
const adjust = {
|
|
511
|
+
name: 'ffmpeg_adjust',
|
|
512
|
+
description: '调整媒体:变速(speed 倍率,>1 加速 <1 减速,音视频同步变速)、音量(volume 倍数如 1.5 或分贝如 -3dB)、静音(mute)、顺时针旋转(rotate 90/180/270,竖横屏互转)。可组合使用。只静音/调音量时视频走流拷贝(快);变速/旋转会重编码。四个操作至少给一个。',
|
|
513
|
+
parameters: compileParameters({
|
|
514
|
+
input: { type: 'string', required: true, description: '输入文件(必填)。' },
|
|
515
|
+
speed: { type: 'number', description: '倍速 0.1-100:2 为两倍速,0.5 为半速(可选)。' },
|
|
516
|
+
volume: { type: 'string', description: '音量:倍数如 1.5 / 0.6,或分贝如 -3dB / +2dB(可选)。' },
|
|
517
|
+
mute: { type: 'boolean', description: 'true 时移除音轨(可选)。' },
|
|
518
|
+
rotate: { type: 'integer', description: '顺时针旋转角度:90 / 180 / 270(可选)。' },
|
|
519
|
+
output: { type: 'string', description: '输出路径(可选,默认输入同目录加 .adjust 后缀)。' },
|
|
520
|
+
}),
|
|
521
|
+
output: {
|
|
522
|
+
schema: produceSchema,
|
|
523
|
+
render: buildTextRenderer((_args, value) => {
|
|
524
|
+
const rec = asRecord(value);
|
|
525
|
+
const ops = Array.isArray(rec.ops) ? rec.ops.join(',') : '';
|
|
526
|
+
return ['调整完成:' + rec.output + '(' + ops + ')'];
|
|
527
|
+
}),
|
|
528
|
+
},
|
|
529
|
+
async execute(rawArgs) {
|
|
530
|
+
const args = asRecord(rawArgs);
|
|
531
|
+
const input = assertInputFile(requiredString(args, 'input', '输入文件'));
|
|
532
|
+
const speed = optionalNumber(args, 'speed');
|
|
533
|
+
if (speed !== undefined && (speed < 0.1 || speed > 100))
|
|
534
|
+
throw new Error('speed 必须在 0.1-100 之间(当前:' + speed + ')。');
|
|
535
|
+
const volume = optionalString(args, 'volume');
|
|
536
|
+
if (volume !== undefined && !/^\d+(\.\d+)?$|^-?\d+(\.\d+)?dB$/.test(volume)) {
|
|
537
|
+
throw new Error('volume 格式必须是倍数(如 1.5)或分贝(如 -3dB)。');
|
|
538
|
+
}
|
|
539
|
+
const mute = args.mute === true;
|
|
540
|
+
let rotate;
|
|
541
|
+
const rotateRaw = args.rotate;
|
|
542
|
+
if (rotateRaw !== undefined) {
|
|
543
|
+
if (rotateRaw !== 90 && rotateRaw !== 180 && rotateRaw !== 270)
|
|
544
|
+
throw new Error('rotate 只支持 90 / 180 / 270。');
|
|
545
|
+
rotate = rotateRaw;
|
|
546
|
+
}
|
|
547
|
+
if (speed === undefined && volume === undefined && !mute && rotate === undefined) {
|
|
548
|
+
throw new Error('speed / volume / mute / rotate 至少提供一个。');
|
|
549
|
+
}
|
|
550
|
+
// 先探测:确认有没有音轨,避免对无声文件构建音频滤镜报错
|
|
551
|
+
const probeResult = await runChecked(runner, probeArgs(cfg.ffprobePath, input), Math.min(timeout, 60000), 'ffprobe');
|
|
552
|
+
const hasAudio = parseProbeJson(probeResult.stdout).audio.length > 0;
|
|
553
|
+
const output = resolveOutputPath(input, optionalString(args, 'output'), '.adjust', extname(input) || '.mp4', cfg.overwrite);
|
|
554
|
+
await runChecked(runner, adjustArgs(cfg.ffmpegPath, { input, output, overwrite: cfg.overwrite, speed, volume, mute, rotate, hasAudio }), timeout, 'ffmpeg 调整');
|
|
555
|
+
const ops = [];
|
|
556
|
+
if (speed !== undefined)
|
|
557
|
+
ops.push('倍速 x' + speed);
|
|
558
|
+
if (volume !== undefined)
|
|
559
|
+
ops.push('音量 ' + volume);
|
|
560
|
+
if (mute)
|
|
561
|
+
ops.push('静音');
|
|
562
|
+
if (rotate !== undefined)
|
|
563
|
+
ops.push('旋转 ' + rotate + '°');
|
|
564
|
+
return { output, ops, hasAudio };
|
|
565
|
+
},
|
|
566
|
+
timeoutMs: timeout,
|
|
567
|
+
};
|
|
510
568
|
const health = {
|
|
511
569
|
name: 'ffmpeg_health',
|
|
512
570
|
description: 'dsh-ffmpeg 自检:验证 ffmpeg / ffprobe 可执行文件是否可用(执行 -version)。遇到问题时先运行本工具定位。',
|
|
@@ -548,5 +606,5 @@ export function buildFfmpegTools(config, runner) {
|
|
|
548
606
|
},
|
|
549
607
|
timeoutMs: 30000,
|
|
550
608
|
};
|
|
551
|
-
return [probe, cut, concat, encode, subtitle, extract, gif, frames, health];
|
|
609
|
+
return [probe, cut, concat, encode, subtitle, extract, gif, frames, adjust, health];
|
|
552
610
|
}
|
package/package.json
CHANGED
|
@@ -1,60 +1,60 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "dsh-ffmpeg",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "DSH 视频处理工具插件:ffmpeg_probe/cut/concat/encode/subtitle/extract/gif 七工具,进程走官方 subprocess 服务,超时树级终止、环境变量路径回退与多视频流探测,零运行时依赖(ffmpeg 本体除外)。",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "lib/index.js",
|
|
7
|
-
"types": "lib/index.d.ts",
|
|
8
|
-
"exports": {
|
|
9
|
-
".": {
|
|
10
|
-
"types": "./lib/index.d.ts",
|
|
11
|
-
"default": "./lib/index.js"
|
|
12
|
-
},
|
|
13
|
-
"./cordis.patch.yml": "./cordis.patch.yml",
|
|
14
|
-
"./package.json": "./package.json"
|
|
15
|
-
},
|
|
16
|
-
"files": [
|
|
17
|
-
"lib",
|
|
18
|
-
"cordis.patch.yml",
|
|
19
|
-
"README.md",
|
|
20
|
-
"README.en.md"
|
|
21
|
-
],
|
|
22
|
-
"scripts": {
|
|
23
|
-
"build": "tsc -p tsconfig.json",
|
|
24
|
-
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
25
|
-
"test": "pnpm run build && node --test \"test/*.test.mjs\"",
|
|
26
|
-
"prepublishOnly": "pnpm run build"
|
|
27
|
-
},
|
|
28
|
-
"dsh": {
|
|
29
|
-
"bundle": {
|
|
30
|
-
"patch": "./cordis.patch.yml"
|
|
31
|
-
}
|
|
32
|
-
},
|
|
33
|
-
"keywords": [
|
|
34
|
-
"dsh",
|
|
35
|
-
"deepseek-harness",
|
|
36
|
-
"plugin",
|
|
37
|
-
"ffmpeg",
|
|
38
|
-
"video",
|
|
39
|
-
"media",
|
|
40
|
-
"dsh-plugin"
|
|
41
|
-
],
|
|
42
|
-
"license": "MIT",
|
|
43
|
-
"engines": {
|
|
44
|
-
"node": ">=22"
|
|
45
|
-
},
|
|
46
|
-
"devDependencies": {
|
|
47
|
-
"@types/node": "^24.0.0",
|
|
48
|
-
"typescript": "^5.6.0"
|
|
49
|
-
},
|
|
50
|
-
"repository": {
|
|
51
|
-
"type": "git",
|
|
52
|
-
"url": "git+https://github.com/STARDUSTLC666/dsh-ffmpeg.git"
|
|
53
|
-
},
|
|
54
|
-
"bugs": {
|
|
55
|
-
"url": "https://github.com/STARDUSTLC666/dsh-ffmpeg/issues"
|
|
56
|
-
},
|
|
57
|
-
"homepage": "https://github.com/STARDUSTLC666/dsh-ffmpeg#readme",
|
|
58
|
-
"author": "stardustlc",
|
|
59
|
-
"packageManager": "pnpm@11.7.0"
|
|
60
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "dsh-ffmpeg",
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "DSH 视频处理工具插件:ffmpeg_probe/cut/concat/encode/subtitle/extract/gif 七工具,进程走官方 subprocess 服务,超时树级终止、环境变量路径回退与多视频流探测,零运行时依赖(ffmpeg 本体除外)。",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "lib/index.js",
|
|
7
|
+
"types": "lib/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./lib/index.d.ts",
|
|
11
|
+
"default": "./lib/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./cordis.patch.yml": "./cordis.patch.yml",
|
|
14
|
+
"./package.json": "./package.json"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"lib",
|
|
18
|
+
"cordis.patch.yml",
|
|
19
|
+
"README.md",
|
|
20
|
+
"README.en.md"
|
|
21
|
+
],
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsc -p tsconfig.json",
|
|
24
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
25
|
+
"test": "pnpm run build && node --test \"test/*.test.mjs\"",
|
|
26
|
+
"prepublishOnly": "pnpm run build"
|
|
27
|
+
},
|
|
28
|
+
"dsh": {
|
|
29
|
+
"bundle": {
|
|
30
|
+
"patch": "./cordis.patch.yml"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"keywords": [
|
|
34
|
+
"dsh",
|
|
35
|
+
"deepseek-harness",
|
|
36
|
+
"plugin",
|
|
37
|
+
"ffmpeg",
|
|
38
|
+
"video",
|
|
39
|
+
"media",
|
|
40
|
+
"dsh-plugin"
|
|
41
|
+
],
|
|
42
|
+
"license": "MIT",
|
|
43
|
+
"engines": {
|
|
44
|
+
"node": ">=22"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@types/node": "^24.0.0",
|
|
48
|
+
"typescript": "^5.6.0"
|
|
49
|
+
},
|
|
50
|
+
"repository": {
|
|
51
|
+
"type": "git",
|
|
52
|
+
"url": "git+https://github.com/STARDUSTLC666/dsh-ffmpeg.git"
|
|
53
|
+
},
|
|
54
|
+
"bugs": {
|
|
55
|
+
"url": "https://github.com/STARDUSTLC666/dsh-ffmpeg/issues"
|
|
56
|
+
},
|
|
57
|
+
"homepage": "https://github.com/STARDUSTLC666/dsh-ffmpeg#readme",
|
|
58
|
+
"author": "stardustlc",
|
|
59
|
+
"packageManager": "pnpm@11.7.0"
|
|
60
|
+
}
|