🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

深鲸画布 feely0208/dsh-shell-canvas

DeepSeek Harness
feely020821 天前有提交已提供中文文档扫描:含敏感能力

把一段稿子变成横竖双版可发视频

29.9/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/11 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add feely0208/dsh-shell-canvas
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:待复验
是什么
dsh 原生插件 · dev
装得上吗
曾在 dsh 0.2.0-rc.2 下真实安装成功,但当前 dsh 已更新至 0.2.1-rc.5,本站尚未在新版下复验
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 21 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件写入剪贴板(不计风险)发起外部网络请求
查看扫描证据(共 133 处,展示前 96 条)
  • 读取本地文件
    lib/index.js:81
    try { return JSON.parse(readFileSync(prefsFile(), 'utf8')); } catch { return {}; }
  • 写入本地文件
    lib/index.js:84
    try { writeFileSync(prefsFile(), JSON.stringify(obj, null, 2)); } catch (e) { console.warn('[canvas] 偏好写不进去:' + e.message); }
  • 读取本地文件
    lib/index.js:121
    return cands.map((c) => ({ ...c, exists: existsSync(c.dir) }));
  • 读取本地文件
    lib/index.js:217
    const reuse = request.resumeFrom && existsSync(request.resumeFrom) ? resolve(request.resumeFrom) : null;
  • 读取本地文件
    lib/index.js:242
    if (!existsSync(f)) throw httpError(400, `背景音乐文件不存在:${f}`);
  • 写入本地文件
    lib/index.js:253
    mkdirSync(outDir, { recursive: true });
  • 写入本地文件
    lib/index.js:262
    mkdirSync(outDir, { recursive: true });
  • 执行外部命令来自配置/变量
    lib/index.js:411
    child = spawn(cmd, args, { stdio: ['ignore', 'pipe', 'pipe'] });
  • 写入本地文件
    lib/index.js:453
    mkdirSync(abs, { recursive: true });
  • 写入本地文件
    lib/index.js:456
    writeFileSync(probe, 'ok');
  • 删除本地文件
    lib/index.js:457
    rmSync(probe, { force: true });
  • 读取本地文件
    lib/index.js:485
    readText: (f) => readFileSync(resolve(f), 'utf8'),
  • 写入本地文件
    lib/index.js:505
    writeFileSync(file, JSON.stringify({ providers: list }, null, 2) + '\n');
  • 读取本地文件
    lib/index.js:525
    readText: (f) => readFileSync(resolve(f), 'utf8'),
  • 执行外部命令来自配置/变量
    lib/index.js:636
    spawn(cmd[0], cmd[1], { detached: true, stdio: 'ignore' }).unref();
  • 执行外部命令来自配置/变量
    lib/index.js:656
    spawn(cmd[0], cmd[1], { detached: true, stdio: 'ignore' }).unref();
  • 删除本地文件
    lib/index.js:693
    try { rmSync(dest, { force: true }); } catch { }
  • 删除本地文件
    lib/index.js:702
    if (!size) { try { rmSync(dest, { force: true }); } catch { } return send(res, 400, { error: '空文件' }); }
  • 发起网络请求
    lib/client.js:79
    const res = await fetch(`${API}${path}`, {
  • 发起网络请求
    lib/client.js:93
    const res = await fetch(`${API}/upload?name=${encodeURIComponent(file.name)}`, {
  • 写入剪贴板
    lib/client.js:1512
    onClick: () => { try { navigator.clipboard.writeText(f.file); } catch (e) { } },
  • 读取本地文件
    lib/license.mjs:47
    try { return JSON.parse(readFileSync(file(), 'utf8')); } catch { return {}; }
  • 写入本地文件
    lib/license.mjs:54
    mkdirSync(dirname(file()), { recursive: true });
  • 写入本地文件
    lib/license.mjs:55
    writeFileSync(file(), JSON.stringify(next, null, 2));
  • 读取本地文件
    lib/jobs.mjs:43
    if (existsSync(c)) return { path: c, source: 'absolute', tried, warn: null };
  • 读取本地文件
    lib/jobs.mjs:49
    if (existsSync(p)) return { path: p, source: 'PATH', tried, warn: null };
  • 读取本地文件
    lib/jobs.mjs:65
    if (!bin || !existsSync(bin)) return { ok: false, reason: '文件不存在' };
  • 执行外部命令来自配置/变量
    lib/jobs.mjs:74
    child = spawn(bin, [join(HERE, 'electron-probe.cjs'), out], { env, stdio: ['ignore', 'ignore', 'ignore'] });
  • 读取本地文件
    lib/jobs.mjs:83
    const info = JSON.parse(readFileSync(out, 'utf8'));
  • 删除本地文件
    lib/jobs.mjs:88
    try { rmSync(out, { force: true }); } catch { }
  • 读取本地文件
    lib/jobs.mjs:104
    const rel = readFileSync(join(pkg, 'path.txt'), 'utf8').trim();
  • 写入本地文件
    lib/jobs.mjs:190
    mkdirSync(spec.outDir, { recursive: true });
  • 写入本地文件
    lib/jobs.mjs:192
    writeFileSync(jobFile, JSON.stringify(spec, null, 2) + '\n');
  • 执行外部命令来自配置/变量
    lib/jobs.mjs:239
    child = spawn(bin, args, { cwd: spec.engineRoot, env, stdio: ['ignore', 'pipe', 'pipe'] });
  • 删除本地文件递归
    lib/jobs.mjs:368
    rmSync(job.outDir, { recursive: true, force: true });
  • 读取本地文件
    lib/jobs.mjs:445
    retryable: !!job.error?.retryable && existsSync(job.outDir),
  • 读取本地文件
    lib/engine.mjs:41
    const j = JSON.parse(readFileSync(overrideFile(), 'utf8'));
  • 写入本地文件
    lib/engine.mjs:50
    mkdirSync(dirname(f), { recursive: true });
  • 写入本地文件
    lib/engine.mjs:51
    writeFileSync(f, JSON.stringify({ canvasRoot, updatedAt: new Date().toISOString() }, null, 2) + '\n');
  • 读取本地文件
    lib/engine.mjs:58
    if (!existsSync(abs)) return { root: abs, ok: false, missing: ['(目录不存在)'] };
  • 读取本地文件
    lib/engine.mjs:59
    const missing = MARKERS.filter((m) => !existsSync(join(abs, m)));
  • 读取本地文件
    lib/engine.mjs:117
    const key = `${root}:${statSync(registryPath).mtimeMs}`;
  • 读取本地文件
    lib/engine.mjs:141
    if (!existsSync(tdir)) return [];
  • 读取本地文件
    lib/engine.mjs:143
    for (const dir of readdirSync(tdir).sort()) {
  • 写入本地文件
    engine/src/batch.mjs:39
    mkdirSync(root, { recursive: true });
  • 读取本地文件
    engine/src/batch.mjs:59
    item.outSha256 = r && r.outFile && existsSync(r.outFile)
  • 读取本地文件
    engine/src/batch.mjs:60
    ? sha256(readFileSync(r.outFile))
  • 写入本地文件
    engine/src/batch.mjs:87
    writeFileSync(manifestFile, JSON.stringify(manifest, null, 2) + '\n');
  • 执行外部命令来自配置/变量
    engine/src/encode.mjs:8
    const p = spawn(bin, args, { stdio: ['ignore', 'ignore', 'pipe'] });
  • 执行外部命令来自配置/变量
    engine/src/encode.mjs:43
    const p = spawn(bin, ['-v', 'error', '-show_entries', 'format=duration,size,bit_rate', '-show_entries', 'stream=codec_type,codec_name,width,height,r_f
  • 读取本地文件
    engine/src/paths.mjs:10
    if (process.env.CANVAS_CHROMIUM && existsSync(process.env.CANVAS_CHROMIUM)) return process.env.CANVAS_CHROMIUM;
  • 读取本地文件
    engine/src/paths.mjs:11
    if (!existsSync(PW_CACHE)) return null;
  • 读取本地文件
    engine/src/paths.mjs:12
    const dirs = readdirSync(PW_CACHE).filter((d) => d.startsWith('chromium'));
  • 读取本地文件
    engine/src/paths.mjs:22
    return cands.find((p) => existsSync(p)) || null;
  • 读取本地文件
    engine/src/paths.mjs:28
    if (process.env.CANVAS_FFMPEG && existsSync(process.env.CANVAS_FFMPEG)) return process.env.CANVAS_FFMPEG;
  • 读取本地文件
    engine/src/paths.mjs:34
    if (existsSync(p)) return p;
  • 执行外部命令来自配置/变量
    engine/src/pipeline.mjs:25
    execFileSync(ffmpeg, ['-y', '-hide_banner', '-loglevel', 'error', '-f', 'lavfi', '-i', `anullsrc=r=44100:cl=mono`, '-t', (ms / 1000).toFixed(3), '-c:a
  • 写入本地文件
    engine/src/pipeline.mjs:33
    mkdirSync(workDir, { recursive: true });
  • 写入本地文件
    engine/src/pipeline.mjs:53
    writeFileSync(listFile, list.map((f) => `file '${f}'`).join('\n') + '\n');
  • 执行外部命令来自配置/变量
    engine/src/pipeline.mjs:56
    execFileSync(ffmpeg, ['-y', '-hide_banner', '-loglevel', 'error', '-f', 'concat', '-safe', '0', '-i', listFile, '-c:a', 'pcm_s16le', '-ar', '44100', '
  • 写入本地文件
    engine/src/pipeline.mjs:98
    mkdirSync(outDir, { recursive: true });
  • 写入本地文件
    engine/src/pipeline.mjs:108
    mkdirSync(audioDir, { recursive: true });
  • 读取本地文件
    engine/src/pipeline.mjs:113
    if (!existsSync(src)) throw new Error(`配音文件不存在: ${src}`);
  • 写入本地文件
    engine/src/pipeline.mjs:144
    writeFileSync(join(outDir, 'subtitle.srt'), srt);
  • 读取本地文件
    engine/src/registry.mjs:10
    return JSON.parse(readFileSync(file, 'utf8'));
  • 读取本地文件
    engine/src/registry.mjs:25
    if (!existsSync(domainFile)) throw new Error(`找不到领域包: ${domainFile}`);
  • 读取本地文件
    engine/src/registry.mjs:41
    if (existsSync(p)) bgmRegistry = readJson(p);
  • 读取本地文件
    engine/src/registry.mjs:51
    if (!existsSync(root)) return packs;
  • 读取本地文件
    engine/src/registry.mjs:52
    for (const name of readdirSync(root).sort()) {
  • 读取本地文件
    engine/src/registry.mjs:54
    if (!statSync(dir).isDirectory()) continue;
  • 读取本地文件
    engine/src/suite.mjs:41
    sourceText = readFileSync(file, 'utf8');
  • 读取本地文件
    engine/src/validate.mjs:26
    compiledCache.set(path, ajv.compile(JSON.parse(readFileSync(path, 'utf8'))));
  • 读取本地文件
    lib/adapter-system-browser.mjs:48
    if (existsSync(p)) return p;
  • 执行外部命令来自配置/变量
    lib/adapter-system-browser.mjs:116
    this.child = spawn(this.browserPath, [
  • 写入本地文件
    lib/adapter-system-browser.mjs:167
    writeFileSync(htmlFile, html, 'utf-8');
  • 删除本地文件递归
    lib/adapter-system-browser.mjs:218
    try { rmSync(this.profile, { recursive: true, force: true }); } catch { }
  • 写入本地文件
    lib/electron-probe.cjs:14
    fs.writeFileSync(process.argv[2], JSON.stringify({
  • 写入本地文件
    lib/electron-probe.cjs:22
    fs.writeFileSync(process.argv[2], JSON.stringify({ error: String(error && error.message) }, null, 2));
  • 读取本地文件
    lib/osr-main.cjs:26
    const spec = JSON.parse(fs.readFileSync(process.argv[2], 'utf8'));
  • 读取本地文件
    lib/pipeline-run.mjs:46
    if (!frameDir || !existsSync(frameDir)) return 0;
  • 读取本地文件
    lib/pipeline-run.mjs:49
    if (existsSync(manifestPath)) {
  • 读取本地文件
    lib/pipeline-run.mjs:50
    try { existing = JSON.parse(readFileSync(manifestPath, 'utf8')); } catch { existing = null; }
  • 读取本地文件
    lib/pipeline-run.mjs:57
    const pngs = readdirSync(frameDir)
  • 读取本地文件
    lib/pipeline-run.mjs:64
    const buf = readFileSync(full);
  • 读取本地文件
    lib/pipeline-run.mjs:70
    bytes: statSync(full).size,
  • 写入本地文件
    lib/pipeline-run.mjs:74
    writeFileSync(manifestPath, JSON.stringify({
  • 写入本地文件
    lib/pipeline-run.mjs:316
    mkdirSync(outDir, { recursive: true });
  • 写入本地文件
    lib/pipeline-run.mjs:363
    mkdirSync(outDir, { recursive: true });
  • 写入本地文件
    lib/pipeline-run.mjs:365
    mkdirSync(audioDir, { recursive: true });
  • 写入本地文件
    lib/pipeline-run.mjs:433
    writeFileSync(cacheFile, JSON.stringify({
  • 写入本地文件
    lib/pipeline-run.mjs:445
    writeFileSync(srtFile, srt);
  • 删除本地文件
    lib/pipeline-run.mjs:576
    if (f.file !== pick.file) { try { rmSync(join(r.frameDir, f.file), { force: true }); } catch { } }
  • 删除本地文件
    lib/pipeline-run.mjs:580
    try { rmSync(join(r.frameDir, 'manifest.json'), { force: true }); } catch { }
  • 删除本地文件
    lib/pipeline-run.mjs:581
    try { rmSync(r.outFile, { force: true }); } catch { }
  • 删除本地文件递归
    lib/pipeline-run.mjs:653
    rmSync(dir, { recursive: true, force: true });
  • 读取本地文件
    lib/worker.mjs:24
    const spec = JSON.parse(readFileSync(process.argv[2], 'utf8'));
扫描于 2026/10/31(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 文字稿转视频
  • 横竖双版输出
  • 本地处理不联网

深鲸画布 · DSH 插件:把一段文字变成能发的视频。稿子、素材、成片都在你自己的电脑上,不上传、不联网。免费版可用。

README

由 DeepSeek 最新模型翻译生成
深鲸画布 · DSH 插件 把一段文字,变成能发的视频。 贴一段稿子、选几张素材,点一下出横竖双版成片。 稿子、素材、成片都在你自己的电脑上 —— 不上传、不联网,拔掉网线照样出片。 安装 在你所用的、支持 DSH 的载体里打开「插件管理器」,选择从压缩包安装,选中下载好的 .tgz 即可。 命令行安装: 推荐:从 npm 装(始终取最新版,不钉版本号) dsh plugin add @deepwhale-cn/dsh-shell-canvas 也可以从官网下载插件包后,在插件管理器里「从压缩包安装」: <https://www.deepwhale.org.cn/download.html> 装完无需重启,界面跟随所在载体的外观。
展开完整文档(README 剩余 1 节)
深鲸画布 · DSH 插件

把一段文字,变成能发的视频。

贴一段稿子、选几张素材,点一下出横竖双版成片。
稿子、素材、成片都在你自己的电脑上 —— 不上传、不联网,拔掉网线照样出片。

安装

在你所用的、支持 DSH 的载体里打开「插件管理器」,选择从压缩包安装,选中下载好的 .tgz 即可。

命令行安装:

推荐:从 npm 装(始终取最新版,不钉版本号)
dsh plugin add @deepwhale-cn/dsh-shell-canvas

也可以从官网下载插件包后,在插件管理器里「从压缩包安装」: <https://www.deepwhale.org.cn/download.html>

装完无需重启,界面跟随所在载体的外观。

能力

- 一次出三种版式 —— 旁白口播 / 金句引用 / 步骤清单,编排各不相同
- 逐句指定配图 —— 分镜表里逐句安排素材与时长,素材与字幕一一对应
- 一个位置放多张图或一段视频 —— 多图按时间轮播;视频素材会让画面真的动起来
- 每个镜头换版位 —— 尺寸、位置、入场方式逐镜轮换
- 一次出横竖双版 —— 同一份稿子,横版竖版一起给
- 模型不绑任何一家 —— 生图与配音接你自己的接口,密钥留在本机
- 批量出片 —— 一次丢进一整批;一条出错不拖垮整批
- 跨平台 —— macOS / Windows / Linux

授权

| 免费版 | 不限条数出片,成片带水印,直接下载就能用,不用注册 |
| 授权版 | ¥199/年,去掉水印 + 批量出片 + 每条可查 |

有效期 1 年,期间不限出片次数。授权码按时间到期,不绑机器。

平台

装在任意支持 DSH 的载体上,不绑定桌面端。
预览分享卡片长什么样 ↓feely0208/dsh-shell-canvas
分享 · DeepSeek Harness Hub
feely0208/dsh-shell-canvas

把一段稿子变成横竖双版可发视频

回到顶部