PLAN.md: video and audio playback in the Files viewer, as the file is

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Mitchell-Johnson
2026-10-11 16:43:03 -07:00
co-authored by Claude Fable 5.1
parent d7f56ee0b3
commit beec9269fe
+20
View File
@@ -707,6 +707,26 @@ something long in one, switch away and back, refresh — it's all still there.
refused outright rather than half-copied. Progress every 500 files or 512 MiB. refused outright rather than half-copied. Progress every 500 files or 512 MiB.
Verified on `grid` ext4 → ZFS with a tree holding a 0600 file, a symlink and an old Verified on `grid` ext4 → ZFS with a tree holding a 0600 file, a symlink and an old
mtime, all intact on the other side. mtime, all intact on the other side.
- **Video and audio play in the viewer** — **shipped 2026-10-11** (v0.1.0-208). Asked for
as "keep it simple for now, and just send whatever codec the file is in to the client,
and let the client try to decode and watch it" — and that is the whole design. Opening a
video or audio file shows a `<video>`/`<audio>` with the browser's own controls, fed the
file as it is by `/api/files/read`; nothing is transcoded or remuxed, so what plays is
what the browser decodes (Safari: h264/hevc/aac in mp4/mov; Chrome: those plus vp9/av1 in
mkv/webm, hevc only where the machine has a hardware decoder; nothing plays MPEG-TS or a
GoPro `.360`'s raw EAC strip). When the element errors the viewer says so and leaves the
download. What the server gained is the part a player cannot do without: reads of a
real file with a known size go through `http.ServeContent`, so **Range requests** (every
seek, and Safari's first request) and HEAD work, and a download can resume. The root
backend's helper takes `--offset` for that, and `files.Seeker` opens the backend once, at
the range asked for, rather than streaming from the top and skipping; seeking costs
nothing until a read wants somewhere else. `/proc` files, which stat at size 0, keep the
plain streaming path, as does the editor's capped read. Audio became a preview kind at
the same time (`thumbs.Kind` → `audio`): its cover art, where it has any, is the row's
thumbnail, with a ♪ badge.
- *Not done, on purpose:* no transcoding or HLS for what the browser lacks (that is the
opposite of "keep it simple"; Jellyfin exists for it), no playlist or next/previous, no
subtitles.
- **Docker read-only view** — `docker ps`/logs; dockhand stays the source of truth. - **Docker read-only view** — `docker ps`/logs; dockhand stays the source of truth.
- **Notifications** — push on service failure / SMART warning / UPS event. - **Notifications** — push on service failure / SMART warning / UPS event.
- **Terminal extras** — search, copy-mode, font/theme, split panes, upload via - **Terminal extras** — search, copy-mode, font/theme, split panes, upload via