DSH Video Preview
Play workspace videos directly in DeepSeek Harness's right-side context / document preview panel. Instead of showing "unsupported file type", the panel renders a native video player with working seeking, including files larger than the 32 MiB RPC preview read limit.
- Package:
@lifenrir/dsh-video-preview - DSH:
>= 0.2.1-rc.2 - Node:
^22.19 || >=24
Features
- Inline
<video controls playsInline preload="metadata">inside the right-side document panel: play, pause, seek, and fullscreen. - Authenticated Host route
/api/dsh-video-preview/streamthat implements HTTPRange(206/416), so seeking is not limited by the RPC preview cap. - 4 MiB chunked reads through
ctx.fs.readByteRange; aHEADprobe validates the path, MIME type, and workspace permission before the browser issues itsGET. - Only known video extensions are accepted; everything else returns
415. - The player follows the DSH theme through
--dsw-alias-*design tokens.
Supported containers and codecs
| Extension | Content-Type |
|---|---|
.mp4, .m4v |
video/mp4 |
.mov |
video/quicktime |
.webm |
video/webm |
.ogv, .ogg |
video/ogg |
.mkv |
video/x-matroska |
Container recognition does not imply codec support. The browser still has to decode the stream:
- H.264/AAC in MP4 and VP8/VP9 in WebM have the widest compatibility.
.movoften contains ProRes, and.mkvoften contains H.265/AC-3 or other codecs browsers do not ship decoders for. When decoding fails the panel shows "This browser cannot play this video format" with a Retry button.
Install
From npm
dsh plugin add @lifenrir/dsh-video-preview
From a local directory
git clone https://github.com/LiFenrir/dsh-video-preview.git
dsh plugin add /absolute/path/to/dsh-video-preview
No build step is required: the Host half is the ESM entry index.js, and the browser half is client.js, loaded through window.__ModuleLoader__.
From git
dsh plugin add git+https://github.com/LiFenrir/dsh-video-preview.git
Reload the Web UI (or restart the profile) after adding and enabling the plugin.
Usage
- Open a workspace video from the Files tab.
- The right-side preview panel shows the player.
- Use the native controls to play, seek, and enter fullscreen.
How it works
index.jsregisters the streaming route on the authenticated connection layer viactx.connection.fetch.register.- The route resolves the session workspace through the
workspaceFileScopelookup, then resolves and stats the requested path withctx.fs, which keeps sandbox rules in force. client.jsregisters a document-preview definition for the supported extensions and the panel component. It parses thedsh-resource://file/session/<sessionId>/<path>address, performs theHEADprobe, and only then points the<video>element at the stream URL.
Security
- The stream route is served through DSH's authenticated connection layer; paths are resolved relative to the session's workspace root and remain subject to the
ctx.fssandbox. - Responses use
Cache-Control: private, no-storeandX-Content-Type-Options: nosniff. - Error responses do not leak internal error details.
- Request paths containing NUL bytes are rejected, and only the extensions listed above are served.
Verify
- Enable the plugin and reload the Web UI.
- Open a
.mp4file from the Files tab. - The right-side preview should show a player, and dragging the progress bar should seek correctly.
- Optionally open a file larger than 32 MiB and confirm that seeking still works.
If the panel reports a load failure, check that the file exists, lies inside the current session workspace, and has a supported extension. If it reports an unsupported format, the container may be recognized but the codec is not decodable by the browser.
Development
This package has no build step and no runtime dependencies. The source files are the shipped files:
index.js Host half (stream route)
client.js Browser half (document preview + player)
cordis.patch.yml Bundle manifest
locale/{en,zh}.json Display metadata
icon.svg Plugin icon
To test a change locally, point dsh plugin add at this directory and reload the Web UI.
License
MIT. See LICENSE.
No comments yet. Be the first to write one.