Preface¶
The built-in document preview of DSH Web UI supports text, PDF, Excel, and images, but not video. Clicking a .mp4, .webm, or .mov in the file tree often results in a message saying “preview is not available for this file type yet,” or being blocked by the platform’s size limit and forced to read the entire segment before playing.
The lvxianchao/dsh-video-preview introduced below fills in this renderer: clicking a video file plays it locally, using a byte-range route with authentication, supporting seek and large files, with no build steps and zero runtime dependencies.
What is this¶
@lvxianchao/dsh-video-preview, maintained by lvxianchao, MIT license, current version 1.1.1, requires Node.js >= 22.19. Category is client-side plugin.
One-sentence positioning: Adds a video preview renderer to the DeepSeek Harness (DSH) Web UI sidebar, covering video file types that were previously missing. It has a separate page on the community plugin directory SkillHub. The directory site is an independent site with no official affiliation to DeepSeek / Huafan.
Core Features¶
- Suffix matching rendering:
mp4/m4v/webm/ogv/ogg/mov, playable when clicked from the file tree,@reference, or workspace change list. - True streaming playback:
<video>requests the byte-range route directly (returning206 Partial Content), seeking is instant; no limit on reading the entire file, watching a 5 GB video only consumes the bytes actually played. - Muted auto-play: Browsers do not allow auto-play with sound, so the preview starts muted by default; unmute by clicking once with native controls.
- Metadata display: Filename, container format, size (from stat route).
- Readable failure: Explicitly prompts when codec or container is not supported, instead of leaving a white screen player.
- Zero runtime dependencies: React comes from the host, the rest uses standard Node/Browser APIs; the browser side is a hand-written
__ModuleLoader__module, no build steps required. - No coupling with host: Browser side registers via public
documentPreviews/slots/localeservices; host side usesconnection.fetchroutes, within the same browser authentication fence as other/apiroutes.
Installation and Enablement¶
Official installation command, choose any of the three sources:
# npm
dsh plugin --profile web add @lvxianchao/dsh-video-preview
# from GitHub
dsh plugin --profile web add "github:lvxianchao/dsh-video-preview"
# from a local checkout
dsh plugin --profile web add /path/to/dsh-video-preview
The main branch only carries published code; the first two remote installation forms install the latest stable version. After installation, restart dsh, and the Web UI will reload frontend modules on startup:
sudo systemctl restart dsh-web # Adjust according to your deployment method
The package declares dsh.bundle, so the installation process appends the package to the profile’s bundle list and automatically mounts this line; no need to manually edit cordis.patch.yml.
If you want to test without modifying the existing profile, you can use an overlay:
dsh --profile web --patch ./dev.yml --host 127.0.0.1 --port 3099 --no-open
# dev.yml
- insert:
- id: video-preview
name: '/absolute/path/to/dsh-video-preview/lib/index.js'
Typical Usage¶
- Type
@in the input box and select a video file (can also be opened from the workspace change list). - Click the file reference, the right sidebar opens the player and starts muted playback.
- Use native controls to drag the progress, unmute, and go fullscreen. When dragging, it only requests bytes near the new position.
Configuration¶
There is only one configuration item rangeBytes:
| Key | Default | Meaning |
|---|---|---|
rangeBytes |
2097152 (2 MiB) |
The byte window returned by each stream request. The browser makes multiple range requests continuously during playback, so this is a latency/throughput knob, not a size limit. |
# ~/.dsh/profiles/web/cordis.patch.yml
- id: video-preview
config:
rangeBytes: 4194304 # 4 MiB windows
How it works¶
The plugin is split into a host side and a browser side:
| Half | File | Role |
|---|---|---|
| Host | lib/index.js |
Registers GET/HEAD /api/video-preview.stream (provided via workspaceFiles.readBytes(range) for byte range, returning 206 + Content-Range), and GET /api/video-preview.stat (size/version/type), mounted on connection.fetch |
| Browser | lib/client.js |
Registers renderer metadata (loading: "renderer") and document bodies with keys; renders <video src=…> pointing to the stream route, and reports the loaded version |
The renderer uses loading: "renderer", so the preview framework never reads the video file as a whole byte stream—this is exactly why the platform’s 32 MB whole-file limit is removed from the video path.
The browser side does not require build steps; it is already a module format directly recognized by the host loader:
window.__ModuleLoader__.load({ id: "@lvxianchao/dsh-video-preview", factory: (require) => { /* … */ } });
Limitations and Use Cases¶
Suitable for: Users already using DSH Web UI who want to view videos directly in the sidebar, or those who need to handle large video files. Before installation, check the source code and license (MIT), and note that the plugin runs with the current dsh process permissions.
Known limitations, already listed in the README:
| Limit | Cause | Workaround |
|---|---|---|
Does not support mkv |
Chrome cannot decode Matroska | Re-encode to mp4/webm |
| Depends on codecs | Browsers can only play content the platform can decode; HEVC/AV1 performance varies | mp4 with H.264/AAC is the most stable |
| Session must be parseable | The stream route parses the file based on the session in the file address | Previews from an active session are always parsable; a missing session results in a 404 |
| Only authenticated browsers are available | The route is within the same authentication fence as other /api routes |
This is by design; no unauthenticated file distribution |
If you want to expose the Web UI on the public internet, the README suggests placing dsh-web-guard by the same author in front of it. This plugin only changes how files are previewed, not who can open them: if the UI’s reachable scope exceeds loopback, you need to place dsh-web-guard in front.
Conclusion¶
The value of this plugin lies in filling the video rendering gap in the DSH sidebar and changing the 32 MB whole-file limit issue in the original Blob solution to byte-range streaming. Zero runtime dependencies, no build steps, low barrier to entry; limitations are also clearly written in the README.
Directory page: https://www.skillhub.cn/plugins/lvxianchao/dsh-video-preview
GitHub: https://github.com/lvxianchao/dsh-video-preview