把一段稿子变成横竖双版可发视频
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
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 21 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
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 的载体上,不绑定桌面端。
预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
feely0208/dsh-shell-canvas
把一段稿子变成横竖双版可发视频
相关插件 · 开发 / 工程
隐私简历生成器reactive-resume/reactive-resume
Reactive Resume 已迁至 GitHub 上的…
★ 45,125已汉化MCP
71.7
AI 架构文档生成器sopaco/deepwiki-rs
🚀 Litho 已进化为 Terrain —— 给你的 AI 智能体一张会呼吸的代码库地图。
★ 3,157已汉化DSH
70.8
长时任务执行闭环AMAP-ML/LongHorizon-Harness
面向 Computer-Use Agent 的 Loop Engineering
★ 1,764已汉化DSH
70.5
AI 编程纪律方法包GanyuanRan/Aegis
让 AI 编程 agent 变得可信:少返工、更安全、说“完成”前先给证据。
★ 1,384已汉化DSH
69.6
多代理编排运行时Enderfga/claw-orchestrator
面向编程智能体的运行时。把 Claude Code、Codex、Antigravity、Grok…
★ 586已汉化MCP
69.4
记忆进化插件csyangwen/dsh-memory-evolve
dsh-memory-evolve 使用场景指南
★ 461已汉化DSH
67.9