粘贴链接批量下载各平台无水印视频与图文
30.6/100
综合分
1
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/10/30 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add hzwym8912-code/dsh-everything-down该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:仅索引
是什么
dsh 原生插件 · model
装得上吗
本站尚未做安装检查
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 3 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 108 处,展示前 72 条)
- 读取本地文件lib/server.js:29
saveDir: existsSync('D:\\') ? 'D:\\下载\\短视频' : join(homedir(), 'Downloads', '短视频'), - 写入本地文件lib/server.js:52
function ensureDir(p) { try { mkdirSync(p, { recursive: true }) } catch (e) {} } - 执行外部命令来自配置/变量lib/server.js:63
const r = spawnSync(cmd, args, { encoding: 'utf8', timeout: 8000, windowsHide: true }) - 读取本地文件lib/server.js:79
for (const p of list) if (existsSync(p)) return p - 读取本地文件lib/server.js:86
const ffCheck = /[ /]/.test(ff) ? { ok: existsSync(ff), version: ff } : probe(ff, ['-version']) - 读取本地文件lib/server.js:87
const ytCheck = /[ /]/.test(yt) ? { ok: existsSync(yt), version: yt } : probe(yt, ['--version']) - 读取本地文件lib/server.js:120
try { saved = JSON.parse(readFileSync(SETTINGS_FILE, 'utf8')) } catch (e) {} - 写入本地文件lib/server.js:133
writeFileSync(SETTINGS_FILE, JSON.stringify(merged, null, 2), 'utf8') - 读取本地文件lib/server.js:139
try { return JSON.parse(readFileSync(TASKS_FILE, 'utf8')) } catch (e) { return [] } - 写入本地文件lib/server.js:143
try { writeFileSync(TASKS_FILE, JSON.stringify(list.slice(0, 200), null, 1), 'utf8') } catch (e) {} - 执行外部命令固定命令lib/server.js:195
child = spawn('winget', args, { windowsHide: true }) - 发起网络请求lib/server.js:239
const r = await fetch(u, { signal: AbortSignal.timeout(ms || 3000), redirect: 'manual' }) - 写入本地文件lib/server.js:645
writeFileSync(join(DATA_DIR, 'open.log'), '[' + new Date().toISOString() + '] ' + msg + '\n', { flag: 'a' }) - 执行外部命令来自配置/变量lib/server.js:664
const child = spawn(ps, ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-EncodedCommand', encoded], { windowsHide: true }) - 执行外部命令固定命令lib/server.js:725
spawn('explorer.exe', [folder], { detached: true, stdio: 'ignore' }).unref() - 执行外部命令固定命令lib/server.js:732
spawn('explorer.exe', [p], { detached: true, stdio: 'ignore' }).unref() - 执行外部命令来自配置/变量lib/server.js:768
const r = spawnSync(powershellBin(), ['-NoProfile', '-Command', ps], { encoding: 'utf8', timeout: 10000, windowsHide: true }) - 写入本地文件lib/server.js:856
writeFileSync(transcriptPath(task.id), JSON.stringify({ - 删除本地文件递归lib/server.js:875
try { rmSync(workDir, { recursive: true, force: true }) } catch (e) {} - 删除本地文件lib/server.js:905
for (const n of names) { try { unlinkSync(join(dir, n)) } catch (e) {} } - 删除本地文件lib/server.js:965
const dropPart = function (p) { try { unlinkSync(p + '.part') } catch (e) {} } - 删除本地文件lib/server.js:1039
try { unlinkSync(aTmp) } catch (e) {} - 写入本地文件lib/server.js:1041
copyFileSync(vTmp, out) - 删除本地文件lib/server.js:1043
try { unlinkSync(vTmp) } catch (e) {} - 发起网络请求lib/server.js:1353
const r = await fetch(target, { headers: headers }) - 发起网络请求lib/client.js:48
fetch("http://127.0.0.1:" + port + "/api/ping", { cache: "no-store", signal: ctrl.signal }) - 发起网络请求lib/client.js:77
try { pending = fetch(INFO_PATH, { cache: "no-store" }) } catch (e) { pending = Promise.reject(e) } - 发起网络请求bin/mcp.js:35
const r = await fetch('http://127.0.0.1:' + port + '/api/ping', { signal: ctrl.signal }) - 执行外部命令来自配置/变量bin/mcp.js:64
const child = spawn(process.execPath, [PANEL_SCRIPT, String(PORTS[0])], { - 发起网络请求bin/mcp.js:91
const r = await fetch(base + path, init) - 读取本地文件lib/engine.js:27
if (existsSync(full)) return full - 读取本地文件lib/engine.js:72
if (p.indexOf('/') >= 0 || p.indexOf('\\') >= 0) { if (existsSync(p)) return p } - 读取本地文件lib/engine.js:86
return existsSync(candidate) ? candidate : '' - 执行外部命令来自配置/变量lib/engine.js:114
const child = spawn(cmd, args, { windowsHide: true }) - 发起网络请求lib/engine.js:132
const r = await fetch('http://127.0.0.1:' + port + '/json/version') - 读取本地文件lib/engine.js:145
if (!existsSync(chrome)) throw new Error('浏览器路径不存在:' + chrome) - 执行外部命令来自配置/变量lib/engine.js:149
const child = spawn(chrome, [ - 删除本地文件递归lib/engine.js:169
try { rmSync(profile, { recursive: true, force: true }) } catch (e) {} - 删除本地文件递归lib/engine.js:183
try { rmSync(profile, { recursive: true, force: true }) } catch (err) {} - 删除本地文件递归lib/engine.js:241
setTimeout(function () { try { rmSync(profile, { recursive: true, force: true }) } catch (e) {} }, 1500) - 写入本地文件lib/engine.js:476
mkdirSync(dirname(file), { recursive: true }) - 读取本地文件lib/engine.js:484
if (existsSync(part)) { - 读取本地文件lib/engine.js:485
const s = statSync(part).size - 发起网络请求lib/engine.js:491
const r = await fetch(url, { headers }) - 写入本地文件lib/engine.js:495
try { renameSync(part, file); return { size: startByte, total: startByte, resumed: true } } catch (e) {} - 写入本地文件lib/engine.js:511
try { renameSync(part, file); return { size: startByte, total: total, resumed: true } } catch (e) {} - 删除本地文件lib/engine.js:515
if (startByte > 0) { try { unlinkSync(part) } catch (e) {} } - 写入本地文件lib/engine.js:527
await pipeline(stream, createWriteStream(part, { flags: startByte > 0 ? 'a' : 'w' })) - 写入本地文件lib/engine.js:536
renameSync(part, file) - 写入本地文件lib/engine.js:538
copyFileSync(part, file) - 删除本地文件lib/engine.js:539
try { unlinkSync(part) } catch (err) {} - 发起网络请求lib/engine.js:623
const r = await fetch('http://127.0.0.1:' + port + '/json/version') - 执行外部命令来自配置/变量lib/engine.js:695
const child = spawn(chrome, [ - 执行外部命令来自配置/变量lib/engine.js:753
const child = spawn(chrome, [ - 执行外部命令来自配置/变量lib/transcribe.js:19
const child = spawn(cmd, args, { windowsHide: true }) - 写入本地文件lib/transcribe.js:96
mkdirSync(outDir, { recursive: true }) - 读取本地文件lib/transcribe.js:104
if (r.code !== 0 || !existsSync(out)) throw new Error('抽音频失败:' + String(r.err).slice(-160)) - 写入本地文件lib/transcribe.js:105
writeFileSync(out, canonicalWav(readFileSync(out))) - 读取本地文件lib/transcribe.js:105
writeFileSync(out, canonicalWav(readFileSync(out))) - 写入本地文件lib/transcribe.js:117
mkdirSync(workDir, { recursive: true }) - 读取本地文件lib/transcribe.js:132
if (r.code === 0 && existsSync(file)) { - 写入本地文件lib/transcribe.js:134
try { writeFileSync(file, canonicalWav(readFileSync(file))) } catch (e) {} - 读取本地文件lib/transcribe.js:134
try { writeFileSync(file, canonicalWav(readFileSync(file))) } catch (e) {} - 删除本地文件lib/transcribe.js:138
try { unlinkSync(wav) } catch (e) {} - 读取本地文件lib/transcribe.js:147
const audio = canonicalWav(readFileSync(chunks[i].file)) - 删除本地文件lib/transcribe.js:153
for (const c of chunks) { try { unlinkSync(c.file) } catch (err) {} } - 删除本地文件lib/transcribe.js:167
if (chunks[i].file !== wav) { try { unlinkSync(chunks[i].file) } catch (e) {} } - 写入本地文件lib/transcribe.js:176
mkdirSync(outDir, { recursive: true }) - 读取本地文件lib/transcribe.js:182
if (r.code !== 0 || !existsSync(out)) throw new Error('抽音频失败:' + String(r.err).slice(-160)) - 发起网络请求lib/transcribe.js:221
res = await fetch(base + '/audio/transcriptions', { - 删除本地文件lib/transcribe.js:264
for (const p of parts) { if (p.file !== audio) { try { unlinkSync(p.file) } catch (e) {} } } - 删除本地文件lib/transcribe.js:265
try { unlinkSync(audio) } catch (e) {}
扫描于 2026/11/1(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
展开完整介绍(127 字)↓
多平台短视频无水印下载台:抖音、快手、小红书、B站、TikTok、YouTube 等视频与图文批量下载,支持作者主页整号抓取、断点续传、失败自动重试、本地语音转文字,自带 Web 工作台面板。全部在本机解析,不依赖第三方解析服务,不需要 API key。
README
由 DeepSeek 最新模型翻译生成Everything down
抖音、快手短视频无水印下载,带本地面板。
安装
目前还没上架插件市场,手动装一次就行:
1. 把仓库下载到本地(git clone,或网页上 Download ZIP 解压)
2. 进入 DSH 的 profile 目录(一般是 ~/.dsh/profiles/desktop),执行:
pnpm add link:<解压后的目录>
⚠️ 如果你的 profile 里已经用「插件市场」装过别的插件,这一步可能把它们挪进 node_modules/.ignored(它们不在 dependencies 里,pnpm 会当成多余)。装之前先备份整个 profile 目录,装完打开客户端确认别的插件还在;不在的话把 .ignored 里的目录移回 node_modules 对应位置即可。
展开完整文档(README 剩余 1 节)
Everything down
抖音、快手短视频无水印下载,带本地面板。
安装
目前还没上架插件市场,手动装一次就行:
1. 把仓库下载到本地(git clone,或网页上 Download ZIP 解压)
2. 进入 DSH 的 profile 目录(一般是 ~/.dsh/profiles/desktop),执行:
pnpm add link:<解压后的目录>
⚠️ 如果你的 profile 里已经用「插件市场」装过别的插件,这一步可能把它们挪进 node_modules/.ignored(它们不在 dependencies 里,pnpm 会当成多余)。装之前先备份整个 profile 目录,装完打开客户端确认别的插件还在;不在的话把 .ignored 里的目录移回 node_modules 对应位置即可。
没装过 pnpm 的话,用客户端自带的那个:
node "<客户端安装目录>/resources/runtime/pnpm/bin/pnpm.mjs" add link:<解压后的目录>
3. 打开该目录的 package.json,在 dsh.profile.bundles 数组末尾加一行 "dsh-everything-down"
4. 重启客户端,设置左侧就会出现 Everything down
Chrome、ffmpeg、yt-dlp 这些依赖不用手动装,面板「设置 → 环境依赖」里能看到状态和安装命令。
手动安装 / 彻底卸载(推荐)
不想让 pnpm add 动到别的插件,用仓库里自带的两个脚本。它们只改 package.json (改前自动备份)并建一个目录链接,不重写 pnpm-lock.yaml,也不碰其它插件。
安装:
powershell -ExecutionPolicy Bypass -File scripts\install.ps1
彻底卸载(连同设置、任务记录、文稿一起删,加 -PurgeData;只想移除插件就不加):
powershell -ExecutionPolicy Bypass -File scripts\uninstall.ps1 -PurgeData
两个脚本跑完都要重启客户端。默认 profile 是 %USERPROFILE%\.dsh\profiles\desktop,放在别处就加 -Profile <目录>。
打开
重启客户端后访问 http://127.0.0.1:7788(插件在宿主内启动服务)。
独立测试:
node bin/panel.js 7801
用法
1. 选平台(自动 / 抖音 / 快手 / 小红书 / B站 / 微博)
2. 粘贴链接,或整段分享文案(快手建议粘整段,标题才准)
3. 解析 → 下载
4. 保存目录可在主界面改
下载后用什么打开
设置 → 打开方式,可选:系统默认播放器 / 剪映专业版 / 自定义程序(自己挑 exe)。
队列里那个按钮的文案会跟着变,比如设成剪映就显示「剪映打开」。
剪映路径会自动找(常见目录 + 开始菜单快捷方式,装在 D 盘也能识别)。
可用内存低于 1.2GB 时会提示先关程序,不开剪映,避免把机器拖死。
图文(图集)
面板第三个区「图文链接」:粘抖音 / 快手 / 小红书的图文(图集)链接,解析出全部图片,可以只挑几张保存,也可以一次全存。保存到 保存目录/平台/标题/,按 01、02 命名。
三家取图方式不一样(都实测过):抖音抓页面大图并按变体去重、小红书读页面状态里的 imageList、快手抓 /atlas/ 图集图(要滚动触发懒加载)。页面里混进来的推荐流会被过滤掉。
在客户端设置里打开
重启客户端后,设置左侧会多一项「Everything down」,点进去就是 7788 那个完整工作台(内嵌页面,功能一点不少),顶上可以刷新或在新窗口打开。
它靠 lib/client.js(浏览器半侧)注册;新增/改动这一半需要重启客户端,只刷页面不生效。
端口:默认 7788,被占用会自动往后找(设置页会自动跟随,不用手改书签)。
想换端口在面板「设置 → 面板端口」里填,改完重启客户端生效。
境外平台要开代理
TikTok、YouTube、X、Instagram、Facebook 这些在国内直连不通,需要代理或全局 VPN。
插件会在解析前先探一下(3.5 秒),连不上就直接告诉你,不用干等:
- 主界面有一行小字,实时显示境外网络通不通(抖音/快手/B站不受影响)
- 设置里的「环境依赖」里也有一条「境外网络」
- 解析失败时文案会区分两种情况:完全没开代理 vs 代理开着但节点被平台限了
国内平台(抖音、快手、小红书、B站、微博)不会被这项检查影响。
下载稳定性
- 失败自动重试:网络类错误引擎内重试 3 次,整条任务再重试 3 次,间隔递增。
- 断点续传:先写 .part,断了下次从断点接着下(CDN 支持 Range 时)。
- 直链过期自动恢复:地址返回 403/404/410,就丢掉旧直链重新解析一次再下。
- 卡死自愈:页面嗅探超时会关掉常驻浏览器,下一次解析重新拉起。
- 端口占用:7788 被占就往后试几个端口,不直接报错。
文字提取
默认不自动转写:下载完在队列里点「提取文案」才会转。
想让每次下载都自动转,去设置里打开「下载后自动提取」。
- 服务商默认「本地」(用 DSH 自带的 SenseVoice,免费不联网)
- 也可以换 GLM / OpenAI / 硅基流动,填自己的 key
- 本地模型每段切 110 秒,GLM 只收 30 秒一段
作者主页(批量)
面板上有「作者主页」标签:粘一个抖音主页链接(或 App 里「分享主页」的整段文案),会把该主页的作品都列出来,勾选后一键下载。
- 未登录只能拿到前几条(抖音限制,实测主页 10 条只给 5 条)。
点「登录抖音」,在弹出来的窗口里扫码,登录态会存在 %USERPROFILE%\.everything-down\chrome,以后不用再登。
- 列表是靠浏览器打开页面、截它自己的请求拿的:直接请求 /aweme/v1/web/aweme/post/ 会被 ArgusSecurityPlugin 拦成 403。
- 作品列表里的 play_addr 是带音轨的完整 mp4,不用合并。
- 图文作品目前只统计数量,不下载。
- 批量下载会去重(同一作品已在队列里就跳过),文件名带作品 id 后 6 位防重名。
平台实现
| 平台 | 方式 | 状态 |
| 抖音 | 无头 Chrome 抓 media-video + media-audio,ffmpeg 合并 | ✅ 稳定 |
| 快手 | 移动端分享页 + 微信 UA,直接拿合并好的 mp4 | ✅ 已验收 3/3 |
| 小红书 | 桌面页嗅探 xhscdn 直链,需带 Referer | ✅ 已验收 |
| B 站 | 页面嗅探 DASH 双轨合并(yt-dlp 解析 B 站新版页面会失败) | ✅ 未登录最高 480P |
| YouTube | yt-dlp 直接下载 | ✅ 已验收 |
| Instagram | yt-dlp | ✅ 已验收(公开帖) |
| Facebook | yt-dlp | ✅ 已验收(公开视频) |
| X / Twitter | yt-dlp | ✅ 已验收(公开推文,无需登录) |
| 小红书 | 桌面页嗅探 | ✅ 已验收(xhslink 短链) |
| 微博 | yt-dlp 直取(weibocdn 需带 weibo.com Referer) | ✅ 已验收 |
| TikTok | yt-dlp + 伪装 Chrome 指纹(需能连外网) | ✅ 已验收(720P h264,无预览) |
快手为什么必须用移动端 UA
桌面版 www.kuaishou.com/short-video/{id} 在未登录时不播放目标作品,只播推荐流,所以抓到的会是别的视频(实测 3 条全错)。
换成微信 UA 打开分享短链后,会跳转到 v.m.chenzhongtech.com/fw/photo/{photoId},页面直接渲染目标作品,video.currentSrc 就是无水印 mp4。
注意
- 不要按端口杀进程:7788 由 DeepSeek Harness 宿主持有,按端口杀会打掉客户端。
重启用 powershell -NoProfile -ExecutionPolicy Bypass -File bin\restart.ps1 7801,它只杀「node.exe 且命令行含 panel.js」的进程。
- 抖音解析需要 15~20 秒(要等播放器真正起播)。
依赖
Chrome、ffmpeg、yt-dlp。
性能
解析不再傻等固定时长:
- 浏览器常驻:第一次启动后复用同一个 Chrome,省掉每次 1~2 秒冷启动
- 抓够就停:一旦出现视频流,最多再等 1.2 秒收音轨就返回
- 移动端即停:快手拿到 currentSrc 直接返回
- 冷启动补偿:浏览器刚起来那一次自动多给 7 秒,避免首屏慢导致失败
实测(本机):
| 平台 | 解析耗时 |
| 快手 | 1.7~3.2s |
| Instagram | 3.4s |
| 微博 | 6.1s |
| X | 5.2s |
| 抖音 | 5~9s(偶发限流会到 15s+) |
| B站 | 5.9s |
| 小红书 | 6~7s |
| YouTube | 2.6s |
B 站曾因先等 yt-dlp 失败(7 秒)再嗅探,总耗时 15.6s;现在直接嗅探。
预览
解析结果左侧是可播放的小窗,播放地址走本地代理 /api/media:抖音/快手 CDN 会校验 Referer 和 UA,浏览器直连会被拒,必须由服务端带对应头转发。
- 快手:合并流,有声音
- 抖音:音视频分轨,预览只有画面(标了「预览无声」)
代理支持 Range,可以拖动进度条。
打开文件 / 定位(踩过的坑)
- 播放:spawn('explorer.exe', [file]) 交给系统默认播放器。
- 定位:必须让 PowerShell 的 Start-Process 去调 explorer: $arg = '/select,"' + $path + '"' Start-Process explorer.exe -ArgumentList $arg
两个错误示范(都会打开到"文档"或"桌面"):
1. Node 直接 spawn('explorer.exe', ['/select,"..."']) —— Windows 命令行会多转义一层;
2. Shell.Application COM 的 Windows() 遍历 —— 同名窗口一多就抛 HRESULT E_FAIL。
外部依赖(不是插件的一部分)
插件本身不打包这三样,需要装在本机:
| 依赖 | 谁需要它 | 缺了怎么办 |
| Chrome / Edge | 抖音、快手、小红书(要开网页抓地址) | 装一个 Chrome |
| ffmpeg | 所有平台的合并、转码、HLS 下载 | winget install Gyan.FFmpeg |
| yt-dlp | 微博、B 站等(它是独立的 Python 命令行工具,不是插件) | winget install yt-dlp 或 pip install -U yt-dlp |
面板「设置 → 环境依赖」会实时显示三项状态;缺失时解析会直接告诉你要装哪个、命令是什么,不再是一句含糊的「没找到视频流」。
文字提取(语音转文字)
下载完成后可以把语音转成文字稿,还能导出字幕文件给剪映用。
默认走本机模型,零配置:DSH 客户端自带 SenseVoice 语音识别模型(约 233MB,在 %USERPROFILE%\.dsh\speech-to-text\sensevoice\models),插件直接调用它:
- 不花钱
- 不联网(音频不出这台电脑)
- 不用填任何 key
如果这台机器没启用本地语音(DSH 设置 → 语音输入),可以在插件设置里换服务商填 key:
| 服务商 | 说明 |
| GLM(智谱) | glm-asr-2512,路径与 OpenAI 一致,你有会员就能用 |
| OpenAI | 质量好,国内要挂代理 |
| 硅基流动 | 有免费额度 |
| 自定义 | 填接口地址 + key,兼容 OpenAI 格式的任何服务 |
DeepSeek 目前没有语音转写接口,所以不在列表里。
长音频:本地和接口都会自动切段。
产物:文稿存在 %USERPROFILE%\.everything-down\transcripts\{任务id}.json,界面里能复制全文、导出 TXT、导出 SRT 字幕。预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
hzwym8912-code/dsh-everything-down
粘贴链接批量下载各平台无水印视频与图文
相关插件 · 模型接入
API 中继安全审计toby-bridges/api-relay-audit
面向 AI API 中转与 LLM 代理的本地安全审计。
★ 897已汉化DSH
69.4
免费搜索插件DDDMUC/dsh-free-search
DeepSeek Harness 免费搜索插件 —— 无需 API key,零成本,多引擎可切换。 一个给…
★ 761已汉化DSH
68.7
免费联网搜索liustack/modsearch
在官方 App 里模型能联网,切到 API 就不能了。ModSearch 把联网补回来:网页搜索、X…
★ 863已汉化DSH
68.5
OpenCode 免费模型FishBottle7/opencode2dsh
在 DSHDeepSeek Harness里原生使用 OpenCode Zen 的免费匿名模型。
★ 379已汉化DSH
67.8
AI 模型网关tingly-dev/tingly-box
Tingly Box Web UI 演示
★ 373已汉化DSH
67.4
WorkBuddy 账号池XDTrees/dsh-xdpool
把你能白嫖的模型额度接进 DSH 同一个池:WorkBuddy 多账号自动容错、十三家扫码登录、76…
★ 359已汉化DSH
67.1