dsh-at-file
FSMargoo/dsh-at-fileCodex 风格的 `@file` 文件引用,输入框里直接搜索并引用工作区文件。
侧栏浮动窗口里的抖音式刷视频:本地/SMB NAS 文件夹上下滑动,或粘贴在线视频地址(yt-dlp 解析,支持 bilibili/YouTube 与 cookies.txt 登录态);窗口随视频宽高比自适应,支持全屏、拖动缩放、Range 流式播放,并提供 agent 视频推送队列端点。
DSH web GUI client plugin: TikTok-style vertical video feed in a floating window.
DSH web GUI 客户端插件:浮动窗口里的抖音式竖屏刷视频(窗口随视频自适应 + SMB NAS)。
A client plugin for the DSH web GUI: adds a "video" button at the bottom of the sidebar. Clicking it opens a floating window where you point at a folder (local or SMB-mounted), press "play this folder", and swipe through its videos TikTok-style — arrow keys, mouse wheel, or drag.
↑/↓ keys, mouse wheel, or drag on the video (1:1 tracking; releases dock to the nearest video; paused while dragging, resumes on release);←/→ ±5 seconds with a ⏩/⏪ flash; the bottom progress bar is click-to-seek;Space or single-click toggles pause; M mutes; Esc or ✕ closes; auto-play blocked by the browser degrades to muted with an "unmute" hint;sessionStorage; double-click the title bar to reset position and re-enable auto-fit;F or the ⛶ button; Esc exits fullscreen first, second Esc (or ✕) closes the window;smb://host/share/sub, or \\host\share\sub — the host resolves it to the local mount by parsing mount output (Chinese share names in raw or percent-encoded form all match);/video-player/stream (HTTP 206) — seeking sends ranged requests, never a full-file download;--flat-playlist (in-memory, 30 min); single-file progressive streams are proxied by the host (browser UA + Referer + Cookie, Range passed through); DASH/HLS segment streams (all bilibili) are auto-downloaded and merged to a local mp4 (≤1080p, needs ffmpeg) and then served as a local Range stream — each video downloads once, replays are instant;?token= variants over bare duplicates) and lists whatever it finds for you to pick — covers "plain" sites with no yt-dlp extractor;cookies.txt (stored under ~/.dsh/video-player/cookies/); only non-expired, domain-matching cookies are forwarded (a whole-browser export stays under CDN header limits); needed for high-quality / members-only / login-gated content;~/.dsh/video-player/config.json → {"ytdlp": "<path>", "ffmpeg": "<path-or-dir>", "extractorArgs": ["generic:impersonate", "youtube:player_client=mweb,android"]} > DVP_YTDLP env > PATH (yt-dlp / yt-dlp.exe) > python -m yt_dlp; the first candidate that answers --version wins (cached); each extractorArgs entry is passed as its own --extractor-args flag (re-read on every call — no restart needed);POST /video-player/queue {"url","title"} (in-memory, 10 items max, 30 min TTL); an open player window polls every 2 s and auto-plays the first pending item (📥 toast); while the window is closed the items wait and play as soon as it opens; the agent can search first with yt-dlp (bilisearch5:<topic> / ytssearch5:<topic>) and push the pick;GET/DELETE /video-player/cache; files locked by active playback are skipped and reported)./video-player-prefixed routes; list/stream are GET/HEAD only — write routes: /video-player/cookies (POST upload / DELETE, name-validated [A-Za-z0-9][A-Za-z0-9._-]{0,63}, 5 MB cap, stored under ~/.dsh/video-player/cookies/), /video-player/cache (DELETE, only the plugin's own cache dir), /video-player/queue (POST, in-memory push queue — no file or network side effects);mount output — credentials never touch the plugin (mounting is system-level: Finder ⌘K / mount_smbfs); a dropped mount yields a "please remount" hint instead of a raw EIO.| File | Role |
|---|---|
package.json | Package manifest + dsh.bundle (install layer) + dsh.client (browser-half discovery) |
cordis.patch.yml | Bundle patch layer activated by dsh plugin add; registers the video-player Loader row |
index.js | Host half (node): /video-player/list (local + yt-dlp remote lists) + /video-player/stream (local Range / online proxy / DASH cache download) + /video-player/cookies (GET/POST/DELETE) + /video-player/cache (GET/DELETE) + /video-player/queue (GET/POST), incl. SMB path resolution |
client.js | Browser half (classic script bundle, no build step) |
Install the official runtime with Node.js:
npx @deepseek-ai/dsh web
Install this plugin into a profile (the ecosystem convention):
dsh plugin --profile web add "github:anitman/dsh-plugin-video-player#main"
dsh plugin forwards package operations to pnpm, so npm, Git/GitHub, local path, file: and link: package specs are all supported — e.g. from a local clone:
dsh plugin --profile web add .
Only packages declaring dsh.bundle.patch become active profile layers; this package declares it, so dsh plugin add completes the link and layer activation in one step. Pure JS, no build scripts — a git install needs no allowBuilds approval.
Restart dsh --profile web after installing or updating a bundle: the "▶ 刷视频" button then appears at the bottom of the sidebar (above the settings button); manage it under Settings → Plugins.
dsh plugin --profile web remove dsh-plugin-video-player
Removes the dependency and the patch layer together; restart dsh to take effect.
dsh-plugin-video-player in ~/.dsh/profiles/web/node_modules/ pointing at this directory (or copy the directory if symlinks fail);dependencies in ~/.dsh/profiles/web/package.json: "dsh-plugin-video-player": "file:<absolute path to this repo>";~/.dsh/profiles/web/cordis.patch.yml:
- insert:
- id: video-player
name: "dsh-plugin-video-player"
client.js changed: no restart needed, client-HMR hot-reloads the plugin (requires the host-side watch chain to be active; otherwise refresh the page);index.js (host half) changed: dsh restart required;add .: git pull, then restart dsh;github:: re-run the install command with a new #ref to upgrade;DSH web GUI 客户端插件:侧栏底部多一个「▶ 刷视频」按钮,点开是一个浮动窗口,指向一个文件夹(本地或 SMB 挂载的 NAS)后按「播放此文件夹」,即可抖音式连续刷视频。
↑/↓ 键、鼠标滚轮、或按住视频上下拖拽(1:1 跟手,松手自动停靠到最近的视频;拖拽中自动暂停、松手恢复);←/→ 键 ±5 秒(带 ⏩/⏪ 大提示),底部进度条可点击跳转;空格 或单击视频暂停/播放;M 静音;Esc 或 ✕ 关闭;自动播放被浏览器拦截时降级为静音并显示「解除静音」提示;sessionStorage;双击标题栏同时复位位置并恢复自动适配;F 或 ⛶ 按钮;Esc 先退出全屏,第二次 Esc(或 ✕)关窗;smb://主机/共享名/子目录 或 \\主机\共享名\子目录 —— 宿主解析 mount 输出自动换算成本地挂载路径(中文共享名的原始/percent-encoded 形式都能匹配);未挂载时给出具体挂载命令;/video-player/stream Range 流式播放(HTTP 206):快进/拖动进度条只发分段请求,不整段下载;?token= 签名的变体)后全部列出让用户挑——覆盖没有 yt-dlp 提取器的"朴素"站点;~/.dsh/video-player/cookies/);只转发未过期且域匹配的条目(整浏览器导出也不会超 CDN 头限制);高清/会员/需登录内容必备;~/.dsh/video-player/config.json → {"ytdlp": "<路径>", "ffmpeg": "<路径或目录>", "extractorArgs": ["generic:impersonate", "youtube:player_client=mweb,android"]} > 环境变量 DVP_YTDLP > PATH(yt-dlp/yt-dlp.exe)> python -m yt_dlp;第一个能通过 --version 的候选胜出并缓存;extractorArgs 每条作为独立 --extractor-args 传入,每次调用重读配置(改完即生效,不用重启);POST /video-player/queue {"url","title"}(纯内存,最多 10 条,30 分钟过期);打开中的播放窗口每 2 秒轮询一次,自动播放第一条待播视频(📥 提示);窗口没开时视频先排队,开窗即播;agent 可先用 yt-dlp 搜索(bilisearch5:<话题> / ytssearch5:<话题>)挑一个再推;GET/DELETE /video-player/cache;正在播放占用的文件跳过并报告)。/video-player 前缀路由;list/stream 仅 GET/HEAD;写入路由:/video-player/cookies(POST 上传 / DELETE,名称白名单 [A-Za-z0-9][A-Za-z0-9._-]{0,63}、正文 ≤5MB,只写入 ~/.dsh/video-player/cookies/)、/video-player/cache(DELETE,只动插件自己的缓存目录)、/video-player/queue(POST,纯内存推送队列,无文件/网络副作用);mount 输出换算,凭据不经过本插件(挂载由系统完成:Finder ⌘K / mount_smbfs);挂载断开后给出「请重新挂载」提示而非裸 EIO 错误。| 文件 | 说明 |
|---|---|
package.json | 包清单 + dsh.bundle(安装层)+ dsh.client(浏览器半边发现) |
cordis.patch.yml | 由 dsh plugin add 激活的 bundle 补丁层;注册 video-player Loader 行 |
index.js | 宿主半边(node):/video-player/list(本地目录 + yt-dlp 在线列表)+ /video-player/stream(本地 Range / 在线代理 / DASH 缓存下载)+ /video-player/cookies + /video-player/cache + /video-player/queue,含 SMB 路径解析 |
client.js | 浏览器半边(classic script bundle,无构建步骤) |
用 Node.js 安装官方运行时:
npx @deepseek-ai/dsh web
把本插件装入某个 profile(生态约定):
dsh plugin --profile web add "github:anitman/dsh-plugin-video-player#ref"
dsh plugin 把包操作转发给 pnpm,因此 npm、Git/GitHub、本地路径、file:、link: 等包描述符都支持 —— 例如从本地 clone 安装:
dsh plugin --profile web add .
只有声明了 dsh.bundle.patch 的包才会成为生效的 profile 层;本包已声明,所以 dsh plugin add 一步完成链接与层激活。纯 JS、无构建脚本 —— git 安装不需要 allowBuilds 审批。
安装/更新 bundle 后重启 dsh --profile web 生效:侧栏底部(设置按钮上方)出现「▶ 刷视频」按钮;可在 设置 → 插件 中管理。
dsh plugin --profile web remove dsh-plugin-video-player
依赖与补丁层一并移除;重启 dsh 生效。
~/.dsh/profiles/web/node_modules/ 创建指向本目录的软链接 dsh-plugin-video-player(软链失败则直接拷贝目录);~/.dsh/profiles/web/package.json 的 dependencies 中加:"dsh-plugin-video-player": "file:<本仓库绝对路径>";~/.dsh/profiles/web/cordis.patch.yml 顶层数组追加:
- insert:
- id: video-player
name: "dsh-plugin-video-player"
client.js:无需重启,client-HMR 热加载插件(需要宿主侧 watch 链处于活动状态;否则刷新页面);index.js(宿主半边):必须重启 dsh;add . 安装的:git pull 后重启 dsh;github: 安装的:带新 #ref 重跑安装命令升级;